Skip to content

Latest commit

 

History

History
134 lines (99 loc) · 5.06 KB

README.md

File metadata and controls

134 lines (99 loc) · 5.06 KB

About the SOE Protocol

The SOE protocol is a UDP transport layer for the networking traffic of many games developed by Sony Online Entertainment, newer examples of which include Free Realms, H1Z1, Landmark and PlanetSide 2.

The protocol can be thought of, in essence, as a stripped-back version of TCP. It offers basic sessions, packet verification (CRC32), optional compression (zlib), reliable/ordered transmission of data, and optional encryption (RC4).

This documentation covers version 3 of the SOE protocol, using 2022 versions of PlanetSide 2 as a reference.

Warning

This documentation is reverse engineered. As such, it may be incomplete and/or incorrect, and is not necessarily applicable to other games that use the SOE protocol.

Structural Overview

All packets of the SOE protocol use big endian and are prefixed by a two-byte OP code. Packets have a maximum length, which is dictated by both parties using the SessionRequest and SessionResponse packets. This length is usually 512.

The names and OP codes of the protocol packets are:

SessionRequest = 0x01,
SessionResponse = 0x02,
MultiPacket = 0x03,
Disconnect = 0x05,
Heartbeat = 0x06,
NetStatusRequest = 0x07,
NetStatusResponse = 0x08,
ReliableData = 0x09,
ReliableDataFragment = 0x0D,
Acknowledge = 0x11,
AcknowledgeAll = 0x15,
UnknownSender = 0x1D,
RemapConnection = 0x1E

Note: 'data packets' (ReliableData/ReliableDataFragment/Acknowledge/AcknowledgeAll) are actually duplicated four times each, using consecutive OP codes. This allows data to be sent on multiple 'channels'. However, to the author's knowledge, only the first channel has been observed in any games utilising the SOE protocol thus far.


The SOE protocol utilises two sets of packets. The first are concerned with creating, sustaining and failing sessions. As such, having no context, they are not verified and cannot be compressed.

The second set, used within the context of a session, are largely concerned with the transfer of application data. These packets may be pre/suffixed with additional data to facilitate verification and compression.

Session Control Packets

Those packets involved with negotiating a session are:

  • SessionRequest
  • SessionResponse
  • NetStatusRequest
  • NetStatusResponse
  • UnknownSender
  • RemapConnection

Session-context Packets

Those packets requiring a session to be utilised are:

  • MultiPacket
  • Disconnect
  • Heartbeat
  • ReliableData
  • ReliableDataFragment
  • Acknowledge
  • AcknowledgeAll

All SOE packets are prefixed with an OP code. However, those packets which are sent within the context of a session can also include additional data, except for when they are bundled within a MultiPacket.

For a non-sub-packet, the overall structure is as follows:

struct PacketWrapper
{
    ushort OpCode;
    bool? IsCompressed;
    <packet_fields>;
    byte[] Crc; 
}

The IsCompressed field is optional, and will only be included if the server indicates that compression should be enabled, via SessionResponse#IsCompressionEnabled. Should this flag be set, the entirety of the wrapped packet's data (<packet_fields>) is compressed using ZLIB before being wrapped. The default level of compression (FLEVEL = 2) is used.

The length of the Crc field is dictated by the SessionResponse#CrcLength field. It is calculated using the entirety of the packet buffer; starting from the OP code and ending immediately before the CRC bytes. The algorithm is a variant of CRC-32 which performs a more lengthy initialization step. See Appendix A for more info.

Session Control

Note: before continuing, please consult the Packet Reference.

Starting a Session

  1. To begin a session, the client party should send a SessionRequest packet to the server.

    • The SessionId must be a randomly generated number.
    • The UdpLength field is typically 512 (bytes).
    • The ApplicationProtocol field describes the application protocol that the client wishes to proxy over this session. Using PlanetSide 2 as an example, this might be LoginUdp_X or ExternalGatewayApi_X.
  2. If the server decides to accept the session, it must respond with a SessionResponse packet.

    • The SessionId field must contain the ID generated by the client.
    • The CrcSeed must be a randomly generated number.
    • The CrcLength is typically 2 (bytes). Must be between 0 and 4, inclusive.
    • The UdpLength field is typically 512 (bytes).
  3. At this point the session is active, and data transmission may begin.

Ending a Session

At any point, either party may send a Disconnect packet to terminate the session. If the ConnectionRefused or ConnectingToSelf reasons are provided, the client should not attempt to reconnect. In other cases, the client may decide how to proceed.

Handling UnknownSender and RemapConnection

// TODO

Data Transmission

The main purpose of the SOE protocol is to provide reliable and ordered transmission of data from a higher level protocol. This is documented here.