Netcode 1.25

De T4C Tech
Aller à la navigation Aller à la recherche

Généralités

Le protocole réseau utilisé par T4C est du type non-connecté. Ce sont des datagrammes UDP.

Les données de ce datagramme comprennent un en-tête sur 12 octets, éventuellement suivis d'une clé de cryptage, d'une somme de contrôle ainsi que d'une chaîne de données cryptées (le pak).

Le cryptage est une série mathématique qui porte sur les octets 16 du datagramme et suivants, dont la clé est donnée à l'octet 12 sur 2 octets.

Le checksum (somme de contrôle) est donné sur 2 octets à l'octet 14 et porte sur les octets 16 du datagramme et suivants, avant encryption.

Les datagrammes de taille supérieure à 1024 octets sont systématiquement fragmentés (c'est-à-dire, envoyés en plusieurs parties de sorte que chaque partie envoyée ne fasse pas plus de 1024 octets).

Schéma canonique d'un datagramme du protocole 1.25 :

[HEADER][seed][checksum][DATA.........................]
                        [.......partie encryptée......]

ATTENTION: toutes les valeurs de l'en-tête, la clé de cryptage et la somme de contrôle sont en LITTLE ENDIAN (format de représentation des types de données Intel), mais les données du pak sont en BIG ENDIAN (format de représentation des types de données données Motorola). En lisant les données du pak sur un ordinateur de type x86, le programmeur doit penser à INVERSER l'ordre des octets. Les chaînes de caractères, étant considérées comme des tableaux d'octets, ne sont pas affectées.

Méthode de cryptage

Seules les données du pak sont cryptées, c'est-à-dire tout ce qui se situe au-delà du header, de la clé de cryptage et du checksum.

void Pak_ToggleEncryption_125 (pak_t *pak, unsigned short first_seed)
{
   // this function toggles Vircom's encryption on/off on the pak data. Note that the checksum
   // must be computed on the decrypted data, so it has to be done before calling this function.

   unsigned short seed;
   unsigned long index;

   seed = first_seed;

   // for each byte of data...
   for (index = 0; index < pak->data_size; index++)
   {
      seed = seed * 145 + 1; // apply an infinite suite to seed
      pak->data[index] ^= (char) seed; // use it to mask the data (XOR)
   }

   return; // finished
}

NOTE: La même fonction sert à la fois pour le cryptage et le décryptage.

Méthode de calcul de la somme de contrôle

La somme de contrôle est l'addition octet par octet des octets des données du pak, le résultat étant représenté sur deux octets non signés (dépassement de capacité compris).

signed short Pak_ComputeChecksum_125 (pak_t *pak)
{
   // this function computes and returns the pak data's checksum

   unsigned long index;
   signed short sum;

   sum = 0; // start at zero

   // for each byte of data...
   for (index = 0; index < pak->data_size; index++)
      sum += ((unsigned char *) pak->data)[index]; // add its value to the checksum

   return (sum); // return the checksum we found
}

Format des datagrammes UDP de T4C

Pak non fragmenté

Taille	Type			Description
===============================================================================
1	unsigned char		0
1	unsigned char		Type de datagramme (tableau de bits)
2	unsigned short		Longueur du datagramme
4	unsigned long		ID du datagramme
4	unsigned long		0

2	unsigned short		Clé de cryptage du pak
2	signed short		Somme de contrôle des données du pak NON CRYPTEES (checksum)

*	char *			Données du pak (cryptées), encodées en "big endian"

Pak fragmenté

Premier fragment de pak fragmenté

Taille	Type			Description
===============================================================================
1	unsigned char		0
1	unsigned char		Type de datagramme (tableau de bits)
2	unsigned short		Longueur du header + clé + checksum + données bout à bout
4	unsigned long		ID du datagramme
4	unsigned long		copie de l'ID du datagramme

2	unsigned short		Clé de cryptage du pak
2	signed short		Somme de contrôle des données du pak NON CRYPTEES (checksum)

1008	char *			Données du pak (cryptées), encodées en "big endian"

Fragment de pak

Taille	Type			Description
===============================================================================
1	unsigned char		Numéro du fragment
1	unsigned char		Type de datagramme (tableau de bits)
2	unsigned short		Longueur du header + clé + checksum + données bout à bout
4	unsigned long		ID du datagramme
4	unsigned long		ID du datagramme de référence (premier de la série)

1012	char *			Données du pak (cryptées), encodées en "big endian"

Attention : 0 est une ID de datagramme valide !

Valeurs des différents champs

Tableau de bits du type de datagramme

Cet octet considéré comme un tableau de bits permet au datagramme de transporter jusqu'à huit flags différents. Voici ceux utilisés par le jeu :

  • 00000000 (0x00): aucun flag, datagramme normal
  • 00000001 (0x01): ce datagramme est l'accusé de réception d'un autre datagramme
  • 00000010 (0x02): ce datagramme demande un accusé de réception
  • 00000100 (0x04): ce datagramme contient un fragment de pak fragmenté

Ces valeurs peuvent bien entendu être combinées. Ainsi, un datagramme porteur des flags 00000110 sera un fragment de pak fragmenté qui demande un accusé de réception.

ID du datagramme

Il s'agit d'un numéro unique, normalement incrémentiel, mais qui peut parfaitement être aléatoire. Le premier datagramme envoyé par le client a toujours l'ID 0. Ensuite, le serveur renvoie un pak porteur de l'ID à partir de laquelle le client peut commencer son incrémentation.

Système d'accusé de réception

UDP étant un protocole non fiable, quand les données à envoyer sont importantes et nécessitent l'assurance que le destinataire (client ou serveur) les reçoit effectivement, les datagrammes envoyés portent le flag ACK REQUEST (deuxième bit le moins significatif dans l'octet du type de datagramme).

Quand l'un des hôtes reçoit un datagramme portant le flag ACK REQUEST, il doit aussitôt renvoyer un datagramme accusé de réception au format suivant (il s'agit d'une en-tête vide, portant seulement le flag ACK REPLY et l'ID du datagramme concerné).

Accusé de réception :

Taille	Type			Description
===============================================================================
1	unsigned char		0
1	unsigned char		1
2	unsigned short		0
4	unsigned long		ID du datagramme faisant l'objet d'un accusé de réception
4	unsigned long		0

Ce système est implémenté au niveau DATAGRAMME, et non au niveau des paks assemblés. Ce qui signifie que si un pak fragmenté demande un accusé de réception, il le demande dans le header de chacun de ses fragments et il convient d'envoyer un accusé de réception à chaque fragment de pak reçu.

--Sorkvild 14 mars 2008 à 05:05 (MSK)