-
Notifications
You must be signed in to change notification settings - Fork 88
Compression
length | description |
---|---|
1 | packet type |
4 | retransmit mask |
2 | encapsulation seq |
2 | encapsulation ack |
2 | command stream seq |
2 | command stream ack |
2 | command stream len |
command stream length field is completely redundant with length field in the udp header.
encapsulation seq/ack and command stream seq/ack can be 8 bit fields since it takes 30 seconds for them to wrap around even then. In case of 10 seconds of no communication between 2 peers, a special value of 0xff in them can signal that a 16bit seq/ack field follows.
retransmit mask can be replaced by 1 bit in most cases, since it is zero basically all the time. bit=0 signals mask==0, bit=1 signals mask follows.
packet type can be replaced by 2 bits, since after the initial game setup stage, only command 4 and 5 are seen on the wire. 0==command4, 1==command5, 2==8bit command follows, 3==reserved
encapsulation header savings: 6 + 31 + 4*8 + 16 bits == 85 bits of 120 bits (70%) assuming 8 * (20 + 8) bits for IP4+UDP, total savings: 85 bits of 344 (25%)
the command stream (for when encapsulation.type == 4) consist of a sequence of command packets with this structure:
length | description |
---|---|
1 | command code |
2 | length |
N | contents |
Known command codes
code | length | argument | description |
---|---|---|---|
0 | 4 | simtick increment | sender target simtick += argument |
0x32 | 5 | playerid,simtick | sender acknowledges simtick for playerid |
0x33 | 4 | simtick | ? (simtick that was executed?) |
0x34 | 4 | simtick | ? (simtick that is is closed and ready to be executed?) |
0xc | var | ? | ? (sim command?) |
0x16 | var | ? | ? (lua command? e.g.: give resources, chat) |
0x3 | 20 | hash,simtick | desync detection hash |
many more command codes that are still unknown.
The deflate compression appears to achieve a ca. 50% compression ratio, albeit for a case where not many commands were given to the simulation.
example packet dump (3 player game): https://github.com/faf5678/stuff/blob/master/packet_dump
it can be seen in the example dump that the majority of the communication consists of commands: 0,32,33,34.
Proposed new command packet structure:
code(4bit) + variable length content
code | description |
---|---|
0 | ADV |
1 | C33 |
2 | C34 |
3 | ACK8-24 |
4 | ACK0 |
5 | ACK1 |
6 | ACK2 |
7 | ACK3 |
8 | ACK4 |
9 | ACK5 |
10 | ACK6 |
11 | ACK7 |
12 | reserved |
13 | normal command packet follows |
14 | select sources/destinations |
15 | reserved |
ADV +1bit [+7bit]
1: ADV 1
0: +7bit ADV 0-127
C33 +1bit [+3bit]
1: previous C33 + 1
0: +3bit previous C33 +2-9
C34 +1bit [+3bit]
1: previous C34 + 1
0: +3bit previous C33 +2-9
ACK0-ACK8 +1bit [+3bit]
1: previous ACKn + 1
0: +3bit previous ACKn +2-9
ACK8-24 +4bit +1bit [+3bit]
4bit: playerid 8-24
variable length
1: previous ACKn + 1
0: +3bit previous ACKn +2-9
normal command packet:
1 byte type, 2 byte length, var content as before
deflate compression as before
(TBD) select destinations: variable length
1: all
0: +N bits bitfield of destinations
(TBD) select sources: variable length
+N bits bitfield of sources
justification: since any encapsulation packet can rely on the fact that any previous packets are received before it is being evaluated (with the help of command seq/ack), one can without complications reference any previous command package. Since simtick counters are basically always incremented by one, a relative encoding is much better.
the expected gains are for ADV, C33 and C34: 5 bits instead of 35 bits and for C32: 5 or 9 bits instead of 40
for the majority of command packets the compression is expected to be closer to 10-20% instead of 50% for deflate.
Since most restricting link is assumed to be the uplink of a few peers and the fact that FA.exe sends identical data to all peers, the most urgent improvement would be in the form of a proxy that can read a command packet once and send out many copies to all peers. the back route would still go to the originating peer directly since it can be expected that the downlink is not so heavily limited as the uplink. In this case the originating peer has to initiate lost packet retransmissions, but it can instruct the proxy to do the retransmission (meaning that the proxy will have to keep the packets around for a little while). Note that the originating peer still has to send all seq/ack numbers for all peers to the proxy, since the proxy has no knowledge of returned packets. Alternatively the proxy could also participate in the back route, the penalty there being added latency and added traffic for the proxy, the benefit there is that it could manage all sequence numbers for itself.