A gameserver can accept the same game sessions over WebSocket as well as its TCP port, for a client that cannot open a TCP socket, such as one running in a browser. It is off unless you set WS_LISTEN. Gate to Heavens has no WebSocket option, because its game traffic is UDP.
No released client uses this yet, so leave it off unless you are testing one.
Limits Today
- On World of Kung Fu and DragonSoul, a client must ignore the address the server advertises and reconnect to its own WebSocket URL. That reply carries a TCP address, so it cannot name a WebSocket URL.
- Keep a read buffer. The server sends each message in one binary frame today, and it reads your frames as a stream, so you may split or join what you send. Parse the length the game's own framing carries rather than trusting a frame boundary.
Settings
All four are empty by default, are in every settings.ini, and can be set from the environment as GOMMO_<KEY> (Configuration).
| key | section | what it does |
|---|---|---|
WS_LISTEN | [gameserver] | Where to listen: host:port, or a bare port on SERVICE_IP's host. Binary frames only; the server pings every 30 seconds. Empty is off. |
WS_TRUSTED_PROXIES | [gameserver] | IPs and CIDRs of a reverse proxy whose X-Forwarded-For header is believed. Empty trusts nobody, so a proxied player's address is the proxy's. A value that cannot be read stops the server starting. |
WS_ORIGINS | [gameserver] | Browser Origin values allowed to connect, comma-separated with no spaces. Empty accepts any. |
WS_PROXY | [webserver] | The WS_LISTEN address as the webserver reaches it; a bare port means 127.0.0.1. The GameCP then carries the socket on its own address. |
A client opens the socket with the subprotocol gommo.<game key>, for example gommo.rf2232.
Through the GameCP
This keeps the game's WebSocket port private: browsers use your site's wss:// address.
- In
settings.ini, pick a free port and set:
[gameserver]
WS_LISTEN = 127.0.0.1:27805
WS_TRUSTED_PROXIES = 127.0.0.1
[webserver]
WS_PROXY = 127.0.0.1:27805
- Restart the gameserver and the webserver.
- A browser opens
wss://<your site>/api/game/wswith the subprotocol above.
Directly
Set WS_LISTEN to an address outside this machine, for example 0.0.0.0:27805, open that port in your firewall, and connect to ws://<host>:27805/. For HTTPS pages, use the GameCP route above.
DragonSoul
DragonSoul has two connections, and each has its own path:
| connection | direct | through the GameCP |
|---|---|---|
| login | / | /api/game/ws |
| gateway | /gateway | /api/game/ws/gateway |
Building Your Own Client
On RF Online you can write your own client, for a browser or anything else. The server speaks the same game protocol over the socket as it does over TCP, and it needs one thing from you first: a one-time key that proves the account signed in. The launcher gets that key on a port a browser cannot reach, so the GameCP hands it out too. Every step below works from a client on any site.
- Trade the player's email and password for a token. It lasts an hour and does only one thing: ask for keys.
curl -H "Content-Type: application/json" \
-d '{"email": "[email protected]", "password": "..."}' \
https://play.example.com/api/auth/token
{"token": "...", "tokenType": "Bearer", "expiresIn": 3600, "accountId": 42, "name": "You"}
- Ask for a key each time you connect.
curl -X POST -H "Authorization: Bearer <token>" https://play.example.com/api/game/key
{"key": "rf1:...", "accountId": 42, "expiresIn": 900,
"subprotocol": "gommo.rf2232", "wsPath": "/api/game/ws"}
key is rf1: and then 32 hex digits, which are the 16 bytes the launcher would have handed the game client. A client driven by a script sends {"scripted": true} in the body, the same declaration as any scripted client.
- Open
wss://<your site><wsPath>withsubprotocolas the WebSocket protocol, and send binary frames only.wsPathis missing when the site does not carry the socket, so connect to theWS_LISTENaddress instead.
- Send the game's first login message with
accountIdand the 16 key bytes where the launcher's client puts its account and key. From there it is that version's client protocol, unchanged. A server with a client version key set needs that too.
A key works once, for that account, and is gone after 15 minutes or the next server restart. Any attempt spends it, right account or wrong, so ask for a new one rather than retrying.
A native client needs nothing more. A page on another site also needs its origin in two places, because the two connections are checked separately:
| setting | section | allows |
|---|---|---|
CORS_ORIGINS | [webserver] | calling /api/auth/token and /api/game/key |
WS_ORIGINS | [gameserver] | opening the socket; empty accepts any |
CORS_ORIGINS = * is enough for the token path, because a bearer token is not a cookie. A signed-in visitor's cookie also works on /api/game/key, from your site's own pages or an exact CORS_ORIGINS entry, and never from anywhere else.
Both routes need HTTPS when the caller is on the public internet, because one carries a password and the other a key. Loopback and private addresses may use plain HTTP, for testing. With TLS ended at a proxy, the proxy must send X-Forwarded-Proto: https.
Bans hold on this path as they do at the launcher: a banned account gets no token and no key, a token stops working when the account is banned or its password is reset from the panel, and a key already issued is refused at the door. ALLOW_SCRIPTED_CLIENTS = 0 refuses a client that declares a script. With WS_LISTEN empty the server hands out no keys at all.
A game server refuses to start without its accounts database, so every key belongs to an account that signed in. World of Kung Fu and DragonSoul sign in on their own game protocol and need no key. GameCP API lists both routes with the rest.
Docker
The gameserver and webserver containers share a network namespace, so the GameCP route publishes no extra port: keep WS_LISTEN on 127.0.0.1. gommoctl publishes only the game's own ports, so use the GameCP route under Docker rather than exposing WS_LISTEN directly. Docker and Linux Services covers the rest of the Docker setup.