Sophie

Sophie

distrib > Fedora > 18 > x86_64 > media > updates > by-pkgid > ff3d1e8aa70062caf828e1ecb206ee8a > files > 19

freeciv-2.3.3-1.fc18.x86_64.rpm

=========================================================================
  Delta
=========================================================================

If delta is enable for this packet the packet-payload (after the 3
byte packet-header) is followed by the delta-header. The delta-header
is a bitvector which represents all non-key fields of the packet. If
the the field has changed the corresponding bit is set and the field
value is so included in delta-body. The values of the unchanged fields
will be filled in from an old version at the receiving side.

For bool field another optimization called bool-header-folding is
applied. Instead of sending an indicator in the bitvector if the given
bool values has changed (and so using 1 byte for the real value) the
actual value of the bool is transfered in the bitvector bit of this
bool field.

Another optimization called array-diff is used to reduce the amount of
elements transfered if an array is changed. This is independent of the
delta-header bit i.e. it will only be used if the array has changed
its value and the bit indicates this. Instead of transferring the
whole array only a list of (index,new value of this index) pairs are
transferred. The index is 8bit and the end of this pair list is
denoted by an index of 255.

=========================================================================
  Compression
=========================================================================

To further reduce the network traffic the (delta) packets are
compressed. To get better compression results multiple packets are
grouped together and compressed into a chunk. This chunk is then
transfered as a normal packet. A chunk packet start with the 2 byte
length field which every packet has. A chunk packet has no type. A
chunk packet is identified by having a too large length field. If the
length of the packet is over COMPRESSION_BORDER it is a chunk
packet. It will be uncompressed at the receiving side and re-feed into
the receiving queue.

If the length of the chunk packet can't be expressed in the available
space of the 16bit length field (>48kb) the chunk is sent as a jumbo
packet. The difference between a normal chunk packet and a jumbo chunk
packet is that the jumbo packet has JUMBO_SIZE in the size field and
has an additional 4 byte len field after the 2 byte len field. The
second len field contains the the size of the whole packet (2 byte
first length field + 4 byte second length field + compressed data).

Packets are grouped for the compression based on the
PACKET_PROCESSING_STARTED/PACKET_PROCESSING_FINISHED and
PACKET_FREEZE_HINT/PACKET_THAW_HINT packet pairs. If the first
(freeze) packet is encountered the packets till the second (thaw)
packet are put into a queue. This queue is then compressed and sent as
a chunk packet. If the compression would expand in size the queued
packets are sent uncompressed as "normal" packets.

The compression level can be controlled by the
FREECIV_COMPRESSION_LEVEL environment variable.

=========================================================================
  Files
=========================================================================

There are four file/filesets involved in the delta protocol:
 1) the definition file (common/packets.def).
 2) the generator (common/generate_packets.py).
 3) the generated files (*/*_gen.[ch] or as a list
 client/civclient_gen.c, client/packhand_gen.h, common/packets_gen.c,
 common/packets_gen.h, server/hand_gen.h and server/srv_main_gen.c).
 4) the overview (README.delta, this file)

The definition file lists all valid packet types with their
fields. The generator takes this as input and creates the generated
files.

For adding and/or removing packets and/or fields you only have to
touch the definition file. If you however plan to change the generated
code (adding more statistics for example) you have to change the
generator.

=========================================================================
  Changing the definition file
=========================================================================

Adding a packet:
 1) choose an unused packet number. The generator will make sure that
 you don't use the same number two times.
 2) choose a packet name. It should follow the naming style of the
 other packets: PACKET_<group>_<remaining>. <group> may be SERVER,
 CITY, UNIT, PLAYER, DIPLOMACY and so on.
 3) decide if this packet goes from server to client or client to server
 4) choose the field names and types
 5) choose packet and field flags
 6) write the entry into the corresponding section of common/packets.def

If you add a field which is a struct (say "foobar") you have to write
the following functions: dio_get_foobar, dio_put_foobar and
are_foobars_equal.

Removing a packet:
 1) add a mandatory capability
 2) remove the entry from common/packets.def

Adding a field:
 Option A:
   1) add a mandatory capability
   2) add a normal field line:
      COORD x
 Option B:
   1) add a non-mandatory capability (say "new_version")
   2) add a normal field line containing this capability in an add-cap
   flag:
      COORD x; add-cap(new_version)

Removing a field:
 Option A:
   1) add a mandatory capability
   2) remove the corresponding field line
 Option B:
   1) add a non-mandatory capability (say "cleanup")
   2) add to the corresponding field line a remove-cap flag

After changing the definition file the generator has to be run. The
common/Makefile will take care of this. You don't need to run
autoconf/automake/configure.

=========================================================================
  Capabilities and variants
=========================================================================

The generator has to generate code which supports different
capabilities at runtime according to the specification given in the
definitions with add-cap and remove-cap. The generator will find the
set of used capabilities for a given packet. Lets say there are two
fields with "add-cap(cap1)" and one field with an "remove-cap(cap2)"
flag. So the set of capabilities are cap1, cap2. At runtime the
generated code may run under 4 different capabilities:
 - neither cap1 nor cap2 are set
 - cap1 is set but cap2 isn't
 - cap1 is not set but cap2 is
 - cap1 and cap2 are set

Each of these combinations is called a variant. If n is the number of
capabilities used by the packet the number of variants is 2^n.

For each of these variant a seperate send and receive function will be
generated. The variant for a packet and a connection are calculated
once and then saved in the connection struct.