139 lines
6.4 KiB
Markdown
139 lines
6.4 KiB
Markdown
# Shared server framework ("Magi") — configuration and database access
|
||
|
||
The server EXEs share one in-house framework. Its classes are named `Magi*`,
|
||
and the network sessions are `MG*Session`. This document defines the parts
|
||
every binary shares:
|
||
- server identity;
|
||
- startup modes;
|
||
- configuration files;
|
||
- the path to the database.
|
||
|
||
Analyse each new binary against this document, and record in its own
|
||
`evidence.md` where it differs, rather than re-deriving the framework.
|
||
|
||
Status: first pass. **Primary evidence:** `MessageServer_Release_x64.exe`
|
||
(`decomp/MessageServer_Release_x64/`). **Cross-binary checks:** strings and RTTI
|
||
only, unless a row says otherwise. Field offsets are from MessageServer. Other
|
||
binaries share the same code, so they are *expected* to match, but this hasn't
|
||
been verified. Every claim is static; nothing here was observed at runtime.
|
||
|
||
Notation: **O** = observed in decompiled code, **S** = observed in
|
||
strings/RTTI only, **I** = inference, **?** = unknown. `MS:0x…` means a
|
||
function in `decomp/MessageServer_Release_x64/full/functions/0x….c`.
|
||
|
||
---
|
||
|
||
## 1. Framework presence across binaries (S)
|
||
|
||
| Marker | Present in |
|
||
|---|---|
|
||
| RTTI `MagiServerOption`, `MagiCustomOption`, `MagiServerFile`, `MagiServerManager` | all 14 server EXEs. The two SMMonitoring EXEs only have `MagiServerManager`. |
|
||
| Option-loader keys (`write_thread_count`, `each_option`), the `-AGNET MODE-` banner [sic], and the `DBC_CHAT`/`DBC_EMERGENCY` names | all 14 server EXEs; none in SMMonitoring |
|
||
| `Servers2DbcProxy` RTTI (client of the DBC servers) | Auction, Dungeon, GameGateway, Game, GM, Guild, Manager, Message, PVP |
|
||
| ADO / `_Connection` strings (direct SQL access) | DBCServer and DBCServer_LOG (4 hits each); 1–2 hits in Auction, Dungeon, Game, Guild, Manager and PVP (**?** — may be incidental) |
|
||
|
||
**Inference:** only the DBC servers talk to SQL Server. Every other server
|
||
reaches the database through ProudNet RMI to a DBC server (§5). This needs
|
||
confirming by decompiling the ADO usage in the six non-DBC servers that have
|
||
hits.
|
||
|
||
## 2. Server-kind enum (O, `MS:0x140002930`)
|
||
|
||
The one-byte server type is stored in the option object (`+0x1e8`) and in
|
||
peer/session records. Names below are the wide strings the binary prints.
|
||
|
||
| Value | Name | Value | Name |
|
||
|---|---|---|---|
|
||
| 1 | Lobby (= GameServer EXE, D: `ServerFile`) | 0x0c | DBC_GAME |
|
||
| 2 | Dungeon | 0x0d | Agent |
|
||
| 3 | PVP | 0x11 | DBC_LOG |
|
||
| 4 | WAR | 0x12 | DBC_CHAT |
|
||
| 5 | Guild | 0x13 | DBC_EMERGENCY |
|
||
| 6 | Message | 0x15 | Agentmanager |
|
||
| 7 | GM | 0x16 | MiniGame |
|
||
| 8 | Gate | 0x17 | `api` peer (no display name; `MS:0x14005dc20`) |
|
||
| 9 | Manager | 0x0e–0x10, 0x14 | ? |
|
||
| 0x0a | Auction | | |
|
||
| 0x0b | Match | 0x18 (24) | PatchServer (D: `ServerFile` only; not shipped) |
|
||
|
||
The same numbers are stored in `RustyHearts_Auth.ServerOption.Type`, and
|
||
`ServerFile` maps each one to an EXE (D; see `CONFIG.md` §5).
|
||
|
||
Separately, servers also have a numeric **code** (the instance ID). It appears
|
||
in XML as `code="61"` and in file names such as `MSG_61.xml`. In the shipped
|
||
deployment config every kind has one code: DBC_GAME=1, DBC_LOG=2, DBC_CHAT=3,
|
||
DBC_EMERGENCY=4, Msg=61, GM=71, Gate=81, Manager=91, Auction=101, Match=111,
|
||
Agent=800, AgentManager=900, Dungeon=2001, PvP=3003, Guild=5001, Lobby=21001
|
||
(S, `binaries/Option/*.xml`).
|
||
|
||
## 3. Startup modes (O, `MS:0x14005c7b0`)
|
||
|
||
`MagiServerOption::Init(argv1)` records the PID and the start time
|
||
(`+0x1ec`, `+0x1f0`), then branches on the first character of the argument:
|
||
|
||
| `argv[1]` | Mode | What is loaded |
|
||
|---|---|---|
|
||
| does not start with a digit | **standalone** | `argv[1]` is a path to a per-server XML file, which `MS:0x14005dc20` parses (§4.1) |
|
||
| starts with a digit | **agent mode** (prints `-AGNET MODE-`) | `atoi(argv1)` is this server's **code**. `MS:0x14005ceb0` reads `option\total_option.xml` (§4.3). The full server list then arrives from the Agent over RMI: the `MGSAgentSession` vftable slot 7 is `MS:0x140065ab0`. The entry whose code equals our code configures this server (`MS:0x14005c9f0`); every other entry is added as a peer (`MS:0x14005ff50`). |
|
||
|
||
This matches the Agent side: the Agent launches a server with the numeric
|
||
server code as its argument (`decomp/Agent_Release_x64/evidence.md` finding 3).
|
||
|
||
**ServerInfo record** pushed by the Agent (O, copy constructor `MS:0x140065900`; offsets in bytes):
|
||
|
||
| Off | Type | Field (I) |
|
||
|---|---|---|
|
||
| +0x00 | int | world |
|
||
| +0x04 | int | code |
|
||
| +0x08 | int | ? |
|
||
| +0x0c | u8 | server kind (§2) |
|
||
| +0x10 | int | private_port |
|
||
| +0x14 | int | public_port |
|
||
| +0x18 | int | public_udpport |
|
||
| +0x1c | int | udp_count |
|
||
| +0x20 | u8 | ? |
|
||
| +0x28 | `std::wstring` | private_ip |
|
||
| +0x50 | `std::wstring` | public_ip |
|
||
| +0x78 | `std::wstring` | name |
|
||
|
||
## 4. Configuration files
|
||
|
||
Moved to [`CONFIG.md`](CONFIG.md). It covers:
|
||
- the per-server XML schema with field offsets;
|
||
- `total_option.xml` and `customoption.xml`;
|
||
- the database-backed server topology (`RustyHearts_Auth.ServerOption` /
|
||
`ServerFile`).
|
||
|
||
The `MagiServerOption` field layout matches between MessageServer and
|
||
DBCServer (O).
|
||
|
||
## 5. Database access path
|
||
|
||
Moved to [`DATABASE.md`](DATABASE.md). It covers the RMI → command queue →
|
||
`DBReq*` → stored procedure chain, the four connection types, the
|
||
RMI → procedure map and the schema of the five databases.
|
||
|
||
Summary:
|
||
- **Clients and connections:** client servers keep 4 `MGDBCMsgSession` pools
|
||
(GAME/LOG/CHAT/EMERGENCY), sized by `db_cache session_count`. They send
|
||
`SERVERS2DBC` RMIs (262, IDs 0x2ee1–0x2fe6); this table is **identical in
|
||
MessageServer and DBCServer**, O. DBCServer runs stored procedures over ADO
|
||
and answers with `DBC2SERVERS` (76 RMIs, 0x2af9–0x2b46).
|
||
|
||
## 6. Other shared protocols seen in MessageServer (O)
|
||
|
||
| Protocol | IDs | Direction |
|
||
|---|---|---|
|
||
| `SERVERS2MSG` (stub) / `MSG2SERVERS` (proxy) | 0x3a99–0x3aa0 | servers ↔ MessageServer (`decomp/MessageServer_Release_x64/evidence.md`) |
|
||
| `SERVER2AGENT` | 12 proxy RMIs | see the TSV |
|
||
| `AGENT2SERVER` (stub) | ? | Agent pushes ServerInfo (§3) |
|
||
|
||
## 7. Open questions (priority order)
|
||
|
||
1. AgentManager: confirm that it reads `ServerOption`/`ServerFile` and pushes
|
||
the topology (`CONFIG.md` §5).
|
||
2. DBCServer_LOG: the LOG RMIs and RustyHearts_Log (`DATABASE.md` §5).
|
||
3. Diff the `SERVERS2DBC` table in the remaining client binaries.
|
||
4. Semantics of `send`, `auto`, `lock`, `each_option`, `guildlobby`,
|
||
`channel`, and of the `api` peer.
|
||
5. Server kinds 0x0e–0x10 and 0x14.
|