UDP Packet handling
Once the session is established after a login, the server will being sending
messages to the Core over UDP. These packets are received using the process
that we started when establishing the
session after a successful login.
1.
Raw UDP packets enter the Core from
start_udp_read(). It continuously receives messages from the server as they come into
the socket.
2.
The raw data is then converted to a
Packet
object using the packet's
from_bytes
function.
3.
The packet's from_bytes functon
then
tries to parse the
Header, which contains the information about what type of packet the
following data will be.
4.
Handle edgecases like if the packet has no body, or if the packet
header tells you the packet body is
zerocoded.
Headers
Header parsing in the open metaverse protocol can be challenging. Headers can
be a variable number of bytes long, depending on previous values read from the
stream.
The layout is as follows:
| Flags |
1 byte |
Flag values are set with a bitwise and. The last four bytes are unused.
| Zerocoded |
0x80 |
| Reliable |
0x40 |
| Resent |
0x20 |
| Ack |
0x10 |
|
| Sequence Number |
4 bytes |
The sequence number of this packet. This is used to handle
acknowledgment packets.
|
| Extra |
1 byte |
How many bytes are used to describe the packet ID and frequency. |
| Packet ID and frequency |
1, 2, or 4 bytes |
The combined ID and frequency of the packet |
The Packet ID and frequency is handled differently depending on if it is a
high, medium, low, or fixed frequency packet, based on the location of a 0xFF
byte.
| High |
The following byte after Extra is not 0xFF. That byte is the packet's
ID.
|
|
| Medium |
If the following byte after Extra is 0xFF, the following byte is the
packet's ID
|
| Extra Byte |
0xFF |
Packet ID |
|
| Low |
If the following two bytes after Extra is 0xFF, the following byte is
the packet's ID. Low packets are stored in two bytes instead of one.
|
| Extra Byte |
0xFF |
0xFF |
Packet ID low byte |
Packet ID high byte |
|
| Fixed |
If the following three bytes after Extra is 0xFF, the following byte is
the packet's ID
|
| Extra Byte |
0xFF |
0xFF |
0xFF |
Packet ID |
|
Zerocoded Headers
A specific bug can appear only in the headers of certain zerocoded packets of
low frequency, which offsets reading the bytes and creates incorrect packet
IDs.
The zerocoding algorithm runs on the entire packet when leaving the server,
sometimes zerocoding the header itself. What you might attempt to decode as
| Extra Byte |
0xFF |
0xFF |
Packet ID low byte |
Packet ID high byte |
is in reality
| Extra Byte |
0xFF |
0xFF |
0x00 |
0x01 |
Packet ID high byte |
That
is actually a single zero in the u16's low byte, followed by the u16's high
byte. Failing to account for this will result in the entire body of this
packet to be improperly decoded, and the ID of the packet to parse as 1 for
any zerocoded packet of low frequency with a 0 in the low byte, such as
RegionHandshake
packets.
For these packets, this can be easily avoided by handling parsing like this:
| Extra Byte |
0xFF |
0xFF |
Packet ID low byte |
0x01 (ignored) |
Packet ID high byte |
Reliable Packets
Some packets have a "reliable" flag. This means that on receive, the client
needs to respond with an
ack packet, or else the server will continue sending it.
When a reliable packet is received, the core will immediately
add the packet's sequence number
to the ack list. The mailbox is then triggered to
send the list.
Packet Body
The following bytes after the header are the data block containing the packet
body. Some packets contain no body, and are only sent to inform the viewer of
simple events, such as the
Disable Simulator
packet.
Packet bodies are parsed based on the combination of the frequency and ID to
determine the packet type. Each packet body has its own parsing rules and
strucs.