Transport & connections

Connections

Environments

The Meta-Lobby exists in two separate environments:

  • staging

  • production

The staging environment allows to test multiple room integration. Note that the staging environment is sharing the user datastore with the production environment.

All developers are sharing the same environments. Hopefully all staging application will use the staging instance and all production application will use the production instance. The idea is that all game will use the same instance in order for all players to share and chat together.

Connecting to an Environment

The Client connects to the Meta-Lobby with a TLS (1.0+) TCP connection (preferably TLSv1.2 or better).

The client doesn’t authenticate to the server with a certificate (it is an anonymous client), but the player authenticates herself to the server (see authentication).

The client might choose to keep the connection open as much as possible, in this case it should send Ping requests so that the server can detect connection issues (in return the Client receives Ping responses, which also can help detect connection issues), and compute presence information for the given player.

In the event a player is not connected and the Meta-Lobby needs to inform her of an important event, no push notification is intended, only live chat enabler.

A connection is valid for a Player.

TLS Public Key Pinning

To be noted that the production and staging Meta-Lobby present a self-signed certificate to the Client. Clients are supposed to validate the server certificate public key with a procedure called Public Key Pinning.

This is a counter-cheating measure that prevents Man in the Middle attacks where the attacker puts a proxy between the client and the server and is able to decrypt/modify the traffic because the client might not check the server is whom it pretends to be.

To prevent this, the client must check that the server offered certificate public key is the correct one. It should also check that the CN part of the certificate DN is the one that it connected to (each developer have a different one).

To check that the public key is correct, the client extracts the public key of the certificate presented by the server, and computes a SHA256 hash of it.

The hash should match one of this checksum (valid for the staging environment, the production one will be given to the developer):

Primary:

//TODO

Backup:

//TODO

If the presented public key checksum doesn’t match any of those hash, the client must drop the connection and possibly inform the user that something went wrong.

TLS Troubleshooting

The Meta-Lobby listens on the TCP port 2445. You can check that your own network allows to connect to our staging Meta-Lobby with the following command:

openssl s_client -host metalobby-staging.games.asmodee.net -port 2445

This should print the certificate chain and the various TLS parameters that were used.

If you want to check your client code can connect to a TLS server, you can emulate the Meta-Lobby with the following command:

openssl req -x509 -newkey rsa:2048 -keyout key.pem -out cert.pem -nodes -days 3650
openssl s_server -no_ssl3 -accept 2445 -key key.pem -cert cert.pem

Then point your client to this fake server to be able to troubleshoot the TLS connection.

On the wire transport protocol

Both the client to server and server to client communications use the same transport protocol.

The Meta-Lobby transport protocol is a message based protocol, where client and server exchange messages. Most of the time, the message flow obey a request/response kind of protocol. Sometimes the server might send messages to a client on its own.

The messages are described and serialized/deserialized on the wire with Protocol Buffers (v3) which is an efficient, cross-platform, maintainable system.

Length Delimited Packets

The messages are sent over the TLS connection as size-delimited fragments.

The size of the fragment is serialized in RFC1700 network order also called Big Endian, that is the most significant bits will be serialized first, and the last significant bit will be serialized last.

For example, if the payload size is 498 bytes, the size will be serialized to the following byte string:

00 00 01 f2

After this size, we’ll find the serialized payload.

Protobuf matriochkas

The Protocol defines several Protobuf messages, but those are not sent verbatim on the wire. They are encapsulated in two different more generic protobuf structures.

Message

Each request is encapsulated into a Protobuf oneof field of Message

message Message {
      int32 request_number = 1; /// id of the underlying request
      oneof request {
              PingRequest ping_request = 777; /// 777

              com.daysofwonder.metalobby.AsyncAuthRequest async_auth_request = 400; /// 400
      [...]
              com.daysofwonder.metalobby.RoomCreatedRequest room_created_request = 2001; /// 2001
      [...]
  }
}

Let’s imagine we’re serializing a Ping request which is defined as this:

message PingRequest {
  int64 timestamp = 1;
}

Then the request_number will be 777. When serializing, we’ll get the following (shown as Protobuf decoded text):

{
   request_number: 777
   ping_request {
     timestamp: 12343344456
   }
}

The complete definition of the syntax is available on the Protobuf proto3 page.

Note

The wire format is compatible between Protobuf 2 and Protobuf 3. Any client serializing/deserializing the protocol with Protobuf 2.x can successfully connect to the server which uses Protobuf 3.

Packet

Before being sent over the wire the Message needs to be encapsulated into a Packet structure:

message MetaPacket {
  int64 id = 1;
  com.daysofwonder.mm.MetaMessage payload = 3;
}

The id field is filled by the Client with any arbitrary value. If this request allows a response from the server, the Meta-Lobby will do its best to put the same id in the response to allow the client to match a response to a sent request. Requests sent by the server without any prior request, or requests sent to another client in response of an incoming request will the id field set at 0 or unset.