Skip to content
This repository has been archived by the owner on Nov 19, 2024. It is now read-only.

Commit

Permalink
Merge pull request #2 from ggmolly/localized
Browse files Browse the repository at this point in the history
Add localized handlers, and region-based data populating
  • Loading branch information
Molly authored Apr 14, 2024
2 parents a4bd791 + 1e6134b commit 2918358
Show file tree
Hide file tree
Showing 19 changed files with 507 additions and 121 deletions.
4 changes: 3 additions & 1 deletion .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,6 @@ POSTGRES_USER=belfast
POSTGRES_HOST=localhost
POSTGRES_PORT=5432
POSTGRES_DB=belfast
POSTGRES_HOST_AUTH_METHOD=trust
POSTGRES_HOST_AUTH_METHOD=trust
# China, Overseas, Japan, Korea, Taiwan
AL_REGION={CN,EN,JP,KR,TW}
4 changes: 4 additions & 0 deletions .github/workflows/go.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,12 @@ name: Go
on:
push:
branches: [ "main" ]
paths:
- '**.go'
pull_request:
branches: [ "main" ]
paths:
- '**.go'

jobs:
build:
Expand Down
7 changes: 3 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,12 +58,11 @@ Before continuting the implementation of the game's protocol.

# 📦 Python requirements

Any versions of these python packages will do:
To use the dissection tool (`import_pcap.py`), you need to install the following python dependencies:

- `python-dotenv`
- `psycopg2`
- `beautifulsoup4`
- `requests`
- `scapy`
- `python-dotenv`

# ⚠️ Note

Expand Down
26 changes: 0 additions & 26 deletions _tools/insert_packet_names.py

This file was deleted.

44 changes: 1 addition & 43 deletions answer/servers.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import (

"github.com/ggmolly/belfast/connection"
"github.com/ggmolly/belfast/protobuf"
"google.golang.org/protobuf/proto"
)

const (
Expand All @@ -19,48 +18,7 @@ const (

var (
// Server list
Servers = []*protobuf.SERVERINFO{
{
Ids: []uint32{1},
Ip: proto.String("blhxusgs1api.yo-star.com"),
Port: proto.Uint32(80),
State: proto.Uint32(SERVER_STATE_OFFLINE),
Name: proto.String("Belfast - @ggmolly"),
Sort: proto.Uint32(1),
ProxyIp: proto.String("blhxusproxy.yo-star.com"),
ProxyPort: proto.Uint32(20001),
},
{
Ids: []uint32{2},
Ip: proto.String("blhxusgs1api.yo-star.com"),
Port: proto.Uint32(80),
State: proto.Uint32(SERVER_STATE_FULL),
Name: proto.String("Belfast - @ggmolly"),
Sort: proto.Uint32(2),
ProxyIp: proto.String("blhxusproxy.yo-star.com"),
ProxyPort: proto.Uint32(20001),
},
{
Ids: []uint32{3},
Ip: proto.String("blhxusgs1api.yo-star.com"),
Port: proto.Uint32(80),
State: proto.Uint32(SERVER_STATE_BUSY),
Name: proto.String("Belfast - @ggmolly"),
Sort: proto.Uint32(3),
ProxyIp: proto.String("blhxusproxy.yo-star.com"),
ProxyPort: proto.Uint32(20001),
},
{
Ids: []uint32{4},
Ip: proto.String("blhxusgs1api.yo-star.com"),
Port: proto.Uint32(80),
State: proto.Uint32(SERVER_STATE_ONLINE),
Name: proto.String("Belfast - @ggmolly"),
Sort: proto.Uint32(4),
ProxyIp: proto.String("blhxusproxy.yo-star.com"),
ProxyPort: proto.Uint32(20001),
},
}
Servers = []*protobuf.SERVERINFO{}
)

// Answer to a pseudo CS_8239 packet with a SC_8239 packet + server list (HTTP/1.1 200 OK)
Expand Down
23 changes: 13 additions & 10 deletions answer/update_packet.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@ package answer

import (
"fmt"
"os"
"time"

"github.com/ggmolly/belfast/connection"
"github.com/ggmolly/belfast/consts"
"github.com/ggmolly/belfast/misc"

"github.com/ggmolly/belfast/protobuf"
Expand All @@ -13,8 +15,8 @@ import (

var (
platformMap = map[string]string{
"0": "Android", // supposedly
"1": "iOS", // known
"0": "Android", // Possibly means 'Play Store'
"1": "iOS", // Possibly means 'App Store'
// maybe more?
}
versions []string
Expand All @@ -36,17 +38,19 @@ func Forge_SC10801(buffer *[]byte, client *connection.Client) (int, int, error)
}
versions = append(versions, "dTag-1")
}
belfastRegion := os.Getenv("AL_REGION")

// It seems like the game kind of ignore anything but the versions, timestamp & Monday_0OclockTimestamp
response := protobuf.SC_10801{
GatewayIp: proto.String("blhxusgate.yo-star.com"),
GatewayIp: proto.String(consts.RegionGateways[belfastRegion]),
GatewayPort: proto.Uint32(80),
Url: proto.String(""),
Version: versions,
ProxyIp: proto.String("blhxusproxy.yo-star.com"),
ProxyIp: proto.String(consts.RegionProxies[belfastRegion]),
ProxyPort: proto.Uint32(20000),
IsTs: proto.Uint32(0),
Timestamp: proto.Uint32(uint32(time.Now().Unix())),
Monday_0OclockTimestamp: proto.Uint32(1606114800), // 23/11/2020 08:00:00
Monday_0OclockTimestamp: proto.Uint32(consts.Monday_0OclockTimestamps[belfastRegion]), // // 23/11/2020 08:00:00

// wtf is this i don't even understand what monday_0oclock_timestamp is
// who would even do such a thing
Expand All @@ -57,12 +61,11 @@ func Forge_SC10801(buffer *[]byte, client *connection.Client) (int, int, error)
resolvedPlatform = "Unknown"
}

if updateCheck.GetPlatform() == "1" { // iOS, set the iTunes URL
response.Url = proto.String("https://itunes.apple.com/us/app/azur-lane/id1411126549")
} else if updateCheck.GetPlatform() == "0" { // Android, set the Play Store URL (untested)
response.Url = proto.String("https://play.google.com/store/apps/details?id=com.YoStarEN.AzurLane")
} else { // Unsupported platform
url, ok := consts.GamePlatformUrl[belfastRegion][updateCheck.GetPlatform()]
if !ok {
return 0, 10801, fmt.Errorf("unknown platform '%s' (id='%s')", resolvedPlatform, updateCheck.GetPlatform())
} else {
response.Url = proto.String(url)
}

return client.SendMessage(packetId, &response)
Expand Down
3 changes: 3 additions & 0 deletions connection/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"fmt"
"log"
"net"
"os"
"reflect"
"syscall"

Expand All @@ -25,6 +26,7 @@ type Server struct {
Clients map[int]*Client
Dispatcher ServerDispatcher
rooms map[uint32][]*Client
Region string
}

var (
Expand Down Expand Up @@ -205,6 +207,7 @@ func NewServer(bindAddress string, port int, dispatcher ServerDispatcher) *Serve
Port: port,
Dispatcher: dispatcher,
Clients: make(map[int]*Client),
Region: os.Getenv("AL_REGION"),
rooms: make(map[uint32][]*Client),
}
}
Expand Down
27 changes: 27 additions & 0 deletions consts/update_data.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package consts

// NOTE: All of the following consts are used in the update packet and game update
// functions to re-emit a SC_10801 packet with the game's update information
// and to automatically fetch the game's updates
// Upon implementing a new region, the gateway and proxy must be added here
// check answer/update_packet.go for more information
var (
RegionGateways = map[string]string{
"EN": "blhxusgate.yo-star.com",
}
RegionProxies = map[string]string{
"EN": "blhxusproxy.yo-star.com",
}
// This might not change between regions, but it's here just in case
Monday_0OclockTimestamps = map[string]uint32{
"EN": 1606114800,
}

// This map represents the game's url on the respective platforms
GamePlatformUrl = map[string]map[string]string{
"EN": {
"0": "https://play.google.com/store/apps/details?id=com.YoStarEN.AzurLane",
"1": "https://itunes.apple.com/us/app/azur-lane/id1411126549",
},
}
)
19 changes: 17 additions & 2 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,14 @@ import (
"google.golang.org/protobuf/proto"
)

var validRegions = map[string]interface{}{
"CN": nil,
"EN": nil,
"JP": nil,
"KR": nil,
"TW": nil,
}

func main() {
server := connection.NewServer("0.0.0.0", 80, packets.Dispatch)
// wait for SIGINT
Expand All @@ -44,12 +52,19 @@ func init() {
if err != nil {
logger.LogEvent("Environment", "Load", err.Error(), logger.LOG_LEVEL_ERROR)
}
// Check if the region is valid
if _, ok := validRegions[os.Getenv("AL_REGION")]; !ok {
logger.LogEvent("Environment", "Invalid", fmt.Sprintf("AL_REGION is not a valid region ('%s' was supplied)", os.Getenv("AL_REGION")), logger.LOG_LEVEL_ERROR)
os.Exit(1)
}
if orm.InitDatabase() { // if first run, populate the database
misc.UpdateAllData("EN")
misc.UpdateAllData(os.Getenv("AL_REGION"))
}
packets.RegisterPacketHandler(10800, []packets.PacketHandler{answer.Forge_SC10801})
packets.RegisterPacketHandler(8239, []packets.PacketHandler{answer.Forge_SC8239})
packets.RegisterPacketHandler(10020, []packets.PacketHandler{answer.Forge_SC10021})
packets.RegisterLocalizedPacketHandler(10020, packets.LocalizedHandler{
EN: &[]packets.PacketHandler{answer.Forge_SC10021},
})
packets.RegisterPacketHandler(10022, []packets.PacketHandler{answer.JoinServer})
packets.RegisterPacketHandler(11001, []packets.PacketHandler{
answer.LastLogin, // SC_11000
Expand Down
22 changes: 11 additions & 11 deletions misc/game_update.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,14 @@ import (
"time"

"github.com/ggmolly/belfast/connection"
"github.com/ggmolly/belfast/consts"
"github.com/ggmolly/belfast/logger"
"github.com/ggmolly/belfast/protobuf"
"google.golang.org/protobuf/proto"
)

const (
versionURL = "https://raw.githubusercontent.com/ggmolly/belfast-data/main/versions.json"
region = "EN"
)

var (
Expand Down Expand Up @@ -67,33 +67,33 @@ func hashFromCache() (HashMap, error) {
logger.LogEvent("GameUpdate", "GetHashes", err.Error(), logger.LOG_LEVEL_ERROR)
return nil, err
}
if cache.Region != region {
if cache.Region != os.Getenv("AL_REGION") {
return nil, errRegionMismatch
}
if cache.Version != azurLaneVersions[region].Version {
if cache.Version != azurLaneVersions[os.Getenv("AL_REGION")].Version {
return nil, errVersionMismatch
}
return cache.Hashes, nil

}

func GetGameHashes() HashMap {
version := azurLaneVersions[region].Version
version := azurLaneVersions[os.Getenv("AL_REGION")].Version

if azurLaneHashes != nil && azurLaneVersions[region].Version == version {
if azurLaneHashes != nil && azurLaneVersions[os.Getenv("AL_REGION")].Version == version {
return azurLaneHashes
}

// check if we have a cached version
hashes, err := hashFromCache()
if err == nil && azurLaneVersions[region].Version == version {
if err == nil && azurLaneVersions[os.Getenv("AL_REGION")].Version == version {
azurLaneHashes = hashes
return hashes
}

// no cache, get the hashes from the server
logger.LogEvent("GameUpdate", "GetHashes", "No cached hashes, fetching from server", logger.LOG_LEVEL_INFO)
sock, err := net.Dial("tcp", "blhxusgate.yo-star.com:80")
sock, err := net.Dial("tcp", fmt.Sprintf("%s:80", consts.RegionGateways[os.Getenv("AL_REGION")]))
if err != nil {
logger.LogEvent("GameUpdate", "GetHashes", err.Error(), logger.LOG_LEVEL_ERROR)
return nil
Expand Down Expand Up @@ -145,8 +145,8 @@ func GetGameHashes() HashMap {
}
// Cache the hashes
cache := hashCache{
Region: region,
Version: azurLaneVersions[region].Version,
Region: os.Getenv("AL_REGION"),
Version: azurLaneVersions[os.Getenv("AL_REGION")].Version,
Hashes: azurLaneHashes,
}
file, err := os.OpenFile(".cached_hashes", os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0644)
Expand All @@ -161,7 +161,7 @@ func GetGameHashes() HashMap {
logger.LogEvent("GameUpdate", "GetHashes", err.Error(), logger.LOG_LEVEL_ERROR)
return nil
}
go UpdateAllData("EN")
go UpdateAllData(os.Getenv("AL_REGION"))
return azurLaneHashes
}

Expand All @@ -177,7 +177,7 @@ func LastCacheUpdateVersion() string {
if azurLaneHashes == nil {
return ""
}
return azurLaneVersions[region].Version
return azurLaneVersions[os.Getenv("AL_REGION")].Version
}

func init() {
Expand Down
10 changes: 10 additions & 0 deletions misc/get_specified_region.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package misc

import "os"

// GetSpecifiedRegion returns the value of the environment variable AL_REGION
// it is needed for the web UI to highlight the correct region since we cannot call os.Getenv
// from the web template engine ¯\_(ツ)_/¯
func GetSpecifiedRegion() string {
return os.Getenv("AL_REGION")
}
Loading

0 comments on commit 2918358

Please sign in to comment.