When a player starts WildStar and types their email and password, the client talks to three servers, one after the other. Each one checks what the previous one handed out and passes the player on. This page follows that path up to the moment the player picks a character.
1. The login server (STS)
The first server the client calls is the login server, bezgelor_auth, on port 6600. WildStar's login
protocol is called STS. It doesn't look like the rest of the game's protocol: its
messages read like web requests, a line such as POST /Auth/LoginStart STS/1.0, a few headers and an XML
body. BezgelorAuth.Sts.Packet (apps/bezgelor_auth/lib/bezgelor_auth/sts/packet.ex) reads and writes them.
Each login gets its own process, BezgelorAuth.Sts.Connection, started by
Ranch (the library that accepts network connections) for every client that
connects. BezgelorAuth.Sts.Handler routes each message by its path:
-
/Auth/LoginStart: the client sends the email.AuthHandlerlooks the account up (BezgelorDb.Accounts.get_by_email), checks it isn't suspended, and answers with the values the client needs for the key exchange. -
/Auth/KeyData: the client proves it knows the password without ever sending it. This is SRP6, inBezgelorCrypto.SRP6: both sides compute the same secret key from the password's verifier and random numbers they exchange, and each proves to the other that it has it. From here on the conversation is encrypted with RC4 (BezgelorCrypto.RC4), keyed with that secret. -
/Auth/LoginFinish: if the account has two-step verification on,BezgelorAuth.Sts.TwoStepasks the client to show its code keypad and checks the code (BezgelorDb.TwoFactor). -
/Auth/RequestGameToken: the server makes a random game token, stores it with the account (Accounts.update_game_token) and sends it to the client.
BezgelorAuth.Sts.Session keeps track of how far a login has got (connected, login started, keys
exchanged, authenticated), so a message that arrives out of order is refused. The client leaves the login
server with one thing: the game token.
2. The realm server
Next the client connects to the realm server, bezgelor_realm, on port 23115. From here on the client
speaks WildStar's binary protocol, which The wire explains. The realm app itself is tiny:
apps/bezgelor_realm/lib/bezgelor_realm/application.ex starts a listener, and everything else is shared
code in bezgelor_protocol, the same code the world server uses.
The client sends ClientHelloAuth with its email and the game token. BezgelorProtocol.Handler.RealmAuthHandler
(apps/bezgelor_protocol/lib/bezgelor_protocol/handler/realm_auth_handler.ex):
- checks that the client is the build we support (16042, the final live client);
-
redeems the game token (
Accounts.consume_game_token): it works once, and only for a couple of minutes; - checks the account isn't suspended;
- makes a new random session key and stores it with the account;
-
answers with
ServerAuthAccepted, any login notices (ServerRealmMessages), andServerRealmInfo, which carries the world server's address and port and the session key.
ServerRealmInfo is the hand-off: the client disconnects from the realm server and connects to the address
it was given.
3. The world server, before the world
The world server, bezgelor_world, listens on port 24000. Its first job is the character screens, before
any zone is involved. These handlers also live in apps/bezgelor_protocol/lib/bezgelor_protocol/handler/:
| The client sends | Handler | What happens |
|---|---|---|
ClientHelloRealm (with the session key) |
WorldAuthHandler |
Checks the key against the account (Accounts.validate_session_key_with_account) and switches the connection's encryption to a key made from it. Nothing is sent back. |
ClientCharacterList |
CharacterListHandler |
Sends the account's currencies, unlocks and entitlements, then ServerCharacterList. |
ClientCharacterCreate |
CharacterCreateHandler |
Looks up the chosen template (race, class, sex, faction) in the client's own CharacterCreation table, checks the name and the slot limit, and creates the character (BezgelorDb.Characters). |
ClientCharacterDelete |
CharacterDeleteHandler |
Deletes a character. |
ClientRealmList, ClientRealmSelect |
RealmListHandler, RealmSelectHandler |
The "change realm" screen. |
ClientCharacterSelect |
CharacterSelectHandler |
Checks the character belongs to the account and starts entering the world. |
Selecting a character sends ServerChangeWorld, which tells the client which map to load, together with
everything the client needs to draw the player: the player's own entity, stats, spells and more. That
burst is built by BezgelorProtocol.MapEntry (map_entry.ex), which is also used for every teleport.
While the map loads, the client shows its loading screen; when it is done it sends ClientEnteredWorld,
and the player is in a zone. Into the world picks up from there.
Where the accounts live
Accounts, game tokens, session keys and suspensions are rows in PostgreSQL, behind the
BezgelorDb.Accounts context (apps/bezgelor_db/lib/bezgelor_db/accounts.ex).
Players create accounts on the website, which stores an SRP6 verifier made by BezgelorCrypto.Password, never
the password itself.
Where to look
-
apps/bezgelor_auth/lib/bezgelor_auth/sts/: the login server (connection.ex,handler.ex,session.ex,two_step.ex). -
apps/bezgelor_crypto/lib/bezgelor_crypto/:srp6.ex,rc4.ex,packet_crypt.ex,password.ex,totp.ex. -
apps/bezgelor_protocol/lib/bezgelor_protocol/handler/realm_auth_handler.exandworld_auth_handler.ex: the two hand-offs. -
apps/bezgelor_protocol/lib/bezgelor_protocol/packets/realm/: the realm server's packets. -
config/config.exs: the ports and the address the realm server sends to clients.
Next: The wire.