edit | blame | history | raw

RendezVous: RMC Protocol

The RMC protocol, standing for Remote Method Call, is used to make transactional requests, such that "methods" are called by the client and responses are generated by the server.

RMC itself is designed as a transport for several other application-defined protocols, such that services can send and handle requests through RMC. This means that there's another level deeper to go before we get to application/game data, as each protocol implements its own reading and writing of bytes, although they follow similar patterns and standardised ways.

Official Implementation

As seen in HyperScape, this protocol is done over RendezVous data packets.

When a request is made, usually in a function going by <protocol name>Protocol::Call<method name>, a call context is created and containers in memory for data returned by the server are associated with return value pointers, with IDs from [0, n), where n is the number of parameters.

When a response is received, these return value pointers are fetched from the call context, and the packet is parsed and data is placed into these pointers.

Known Protocols

Here are the currently understood RMC protocols implemented in HyperScape. Some appear to be standard to Ubisoft games as a whole, while others appear to be designed specifically for the game.

Protocol Description HyperScape-specific?
LoginProtocol Used for authenticating with an RMC server using a Ubisoft token. ✖️
CloudServersProtocol Used for listing datacenters for connecting to game servers. ✔️
ApexAntitoxicityProtocol Currently unknown, possibly for managing bans and mutes. ✔️
SessionProtocol Presumably for creating, joining and leaving game sessions, but it is unknown what that entails. ✔️
... ... ...

[!NOTE]
This list is far from complete.

Base Packet Format

Parsing
Name Description Type
Packet Length The total number of bytes in the packet, not including the length itself. u32
Protocol Name The protocol service on the server that is responsible for managing this request String
Is Request? Whether or not this packet is for a request. bool
... See Request Packet Format or Response Packet Format for parsing the packet depending on Is Request?. ...

Request Packet Format

Example
Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
00000000  F9 00 00 00 0E 00 4C 6F 67 69 6E 50 72 6F 74 6F  ù.....LoginProto
00000010  63 6F 6C 00 01 06 00 00 00 1B 00 4C 6F 67 69 6E  col........Login
00000020  50 72 6F 74 6F 63 6F 6C 3A 3A 52 65 67 69 73 74  Protocol::Regist
00000030  65 72 5F 56 31 00 00 00 00 00 04 00 00 00 2F 00  er_V1........./.
00000040  70 72 75 64 70 3A 2F 61 64 64 72 65 73 73 3D 30  prudp:/address=0
00000050  30 30 2E 30 30 30 2E 30 30 2E 30 30 30 3B 70 6F  00.000.00.000;po
00000060  72 74 3D 39 31 30 33 3B 73 69 64 3D 31 35 00 2E  rt=9103;sid=15..
00000070  00 70 72 75 64 70 3A 2F 61 64 64 72 65 73 73 3D  .prudp:/address=
00000080  30 30 30 2E 30 30 30 2E 30 30 30 2E 30 3B 70 6F  000.000.000.0;po
00000090  72 74 3D 39 31 30 33 3B 73 69 64 3D 31 35 00 2D  rt=9103;sid=15.-
000000A0  00 70 72 75 64 70 3A 2F 61 64 64 72 65 73 73 3D  .prudp:/address=
000000B0  30 30 30 2E 30 30 30 2E 30 30 2E 30 3B 70 6F 72  000.000.00.0;por
000000C0  74 3D 39 31 30 33 3B 73 69 64 3D 31 35 00 2D 00  t=9103;sid=15.-.
000000D0  70 72 75 64 70 3A 2F 61 64 64 72 65 73 73 3D 30  prudp:/address=0
000000E0  30 30 2E 30 30 30 2E 30 30 2E 30 3B 70 6F 72 74  00.000.00.0;port
000000F0  3D 39 31 30 33 3B 73 69 64 3D 31 35 00           =9103;sid=15.
Parsing
Name Description Type
... See Base Packet Format for parsing the prologue of a request packet. ...
Call ID The nonce token for this call to identify the response associated with this request. u32
Method Name The method to call on the server. String
Class Versions Version information about the data in the request List<ClassVersion>
... See the respective protocol and method specification to parse and write the rest of the packet.

Structure: ClassVersion

Example:
Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 00000000 12 00 43 6C 69 65 6E 74 56 65 72 73 69 6f 6E 49 ......ClientVersionI 00000010 6E 66 6F 00 01 00 nfo...

Name Description Type
Structure Name The name of the structure to assign a version to. String
Version The version of the structure. u16

Response Packet Format

Example
Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
00000000  25 00 00 00 0E 00 4C 6F 67 69 6E 50 72 6F 74 6F  %.....LoginProto
00000010  63 6F 6C 00 00 00 0B 00 52 65 6E 64 65 7A 56 6F  col.....RendezVo
00000020  75 73 00 81 00 05 00 00 00                       us.......

[!NOTE]
TODO: Successful response example

Parsing
Name Description Type
... See Base Packet Format for parsing the prologue of a response packet. ...
Is Successful? Whether or not this request was successful bool
... See Successful Response Format or Unsuccessful Response Format for parsing this packet depending on Is Successful?. ...

Successful Response Format

Parsing
Name Description Type
... See Response Packet Format for parsing the prologue of a successful response packet. ...
Call ID The nonce token for the call to associate the response to the request. u32
Method Name The method that was called by the client, see note below. String
... See the respective protocol and method specification to parse and write the rest of the packet.

[!NOTE]
Typically, a * is appended to the Method Name in responses for currently unknown reasons. Likely to do with the fact that the response handlers update pointers to data containers created in the original request.

For example, where the request might be LoginProtocol::LoginWithToken_V1, the response would be for LoginProtocol::LoginWithToken_V1*.

Unsuccessful Response Format

Parsing
Name Description Type
... See Response Packet Format for parsing the prologue of an unsuccessful response packet. ...
Error Namespace The category of error that occurred. String
Error Code The code of the error in the specified namespace u16
Call ID The nonce token for the call to associate the response to the request. u32