Newer
Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
/**
* @file packet_interface.h
* @brief This header contains structs and definitions needed in order to encode and decode TRTP packets
*/
#ifndef __PACKET_INTERFACE_H_
#define __PACKET_INTERFACE_H_
#include <stddef.h> /* size_t */
#include <stdint.h> /* uintx_t */
#include <stdio.h> /* ssize_t */
/* Raccourci pour struct pkt */
typedef struct pkt pkt_t;
/* Types de paquets */
typedef enum {
PTYPE_DATA = 1,
PTYPE_ACK = 2,
PTYPE_NACK = 3,
} ptypes_t;
/* Taille maximale permise pour le payload */
#define MAX_PAYLOAD_SIZE 512
/* Taille maximale de Window */
#define MAX_WINDOW_SIZE 31
/* Valeur de retours des fonctions */
typedef enum {
PKT_OK = 0, /* Le paquet a ete traite avec succes */
E_TYPE, /* Erreur liee au champs Type */
E_TR, /* Erreur liee au champ TR */
E_LENGTH, /* Erreur liee au champs Length */
E_CRC, /* CRC invalide */
E_WINDOW, /* Erreur liee au champs Window */
E_SEQNUM, /* Numero de sequence invalide */
E_NOMEM, /* Pas assez de memoire */
E_NOHEADER, /* Le paquet n'a pas de header (trop court) */
E_UNCONSISTENT, /* Le paquet est incoherent */
} pkt_status_code;
/* Alloue et initialise une struct pkt
* @return: NULL en cas d'erreur */
pkt_t* pkt_new();
/* Libere le pointeur vers la struct pkt, ainsi que toutes les
* ressources associees
*/
void pkt_del(pkt_t*);
/*
* Decode des donnees recues et cree une nouvelle structure pkt.
* Le paquet recu est en network byte-order.
* La fonction verifie que:
* - Le CRC32 du header recu est le même que celui decode a la fin
* du header (en considerant le champ TR a 0)
* - S'il est present, le CRC32 du payload recu est le meme que celui
* decode a la fin du payload
* - Le type du paquet est valide
* - La longueur du paquet et le champ TR sont valides et coherents
* avec le nombre d'octets recus.
*
* @data: L'ensemble d'octets constituant le paquet recu
* @len: Le nombre de bytes recus
* @pkt: Une struct pkt valide
* @post: pkt est la representation du paquet recu
*
* @return: Un code indiquant si l'operation a reussi ou representant
* l'erreur rencontree.
*/
pkt_status_code pkt_decode(const char *data, const size_t len, pkt_t *pkt);
/*
* Encode une struct pkt dans un buffer, prêt a être envoye sur le reseau
* (c-a-d en network byte-order), incluant le CRC32 du header et
* eventuellement le CRC32 du payload si celui-ci est non nul.
*
* @pkt: La structure a encoder
* @buf: Le buffer dans lequel la structure sera encodee
* @len: La taille disponible dans le buffer
* @len-POST: Le nombre de d'octets ecrit dans le buffer
* @return: Un code indiquant si l'operation a reussi ou E_NOMEM si
* le buffer est trop petit.
*/
pkt_status_code pkt_encode(const pkt_t*, char *buf, size_t *len);
/* Accesseurs pour les champs toujours presents du paquet.
* Les valeurs renvoyees sont toutes dans l'endianness native
* de la machine!
*/
ptypes_t pkt_get_type (const pkt_t*);
uint8_t pkt_get_tr (const pkt_t*);
uint8_t pkt_get_window (const pkt_t*);
uint8_t pkt_get_seqnum (const pkt_t*);
uint16_t pkt_get_length (const pkt_t*);
uint32_t pkt_get_timestamp(const pkt_t*);
uint32_t pkt_get_crc1 (const pkt_t*);
/* Renvoie un pointeur vers le payload du paquet, ou NULL s'il n'y
* en a pas.
*/
const char* pkt_get_payload(const pkt_t*);
/* Renvoie le CRC2 dans l'endianness native de la machine. Si
* ce field n'est pas present, retourne 0.
*/
uint32_t pkt_get_crc2(const pkt_t*);
/* Setters pour les champs obligatoires du paquet. Si les valeurs
* fournies ne sont pas dans les limites acceptables, les fonctions
* doivent renvoyer un code d'erreur adapte.
* Les valeurs fournies sont dans l'endianness native de la machine!
*/
pkt_status_code pkt_set_type (pkt_t*, const ptypes_t type);
pkt_status_code pkt_set_tr (pkt_t*, const uint8_t tr);
pkt_status_code pkt_set_window (pkt_t*, const uint8_t window);
pkt_status_code pkt_set_seqnum (pkt_t*, const uint8_t seqnum);
pkt_status_code pkt_set_length (pkt_t*, const uint16_t length);
pkt_status_code pkt_set_timestamp(pkt_t*, const uint32_t timestamp);
pkt_status_code pkt_set_crc1 (pkt_t*, const uint32_t crc1);
/* Defini la valeur du champs payload du paquet.
* @data: Une succession d'octets representants le payload
* @length: Le nombre d'octets composant le payload
* @POST: pkt_get_length(pkt) == length */
pkt_status_code pkt_set_payload(pkt_t*,
const char *data,
const uint16_t length);
/* Setter pour CRC2. Les valeurs fournies sont dans l'endianness
* native de la machine!
*/
pkt_status_code pkt_set_crc2(pkt_t*, const uint32_t crc2);
/*
* Decode un varuint (entier non signe de taille variable dont le premier bit indique la longueur)
* encode en network byte-order dans le buffer data disposant d'une taille maximale len.
* @post: place à l'adresse retval la valeur en host byte-order de l'entier de taille variable stocke
* dans data si aucune erreur ne s'est produite
* @return:
*
* -1 si data ne contient pas un varuint valide (la taille du varint
* est trop grande par rapport à la place disponible dans data)
*
* le nombre de bytes utilises si aucune erreur ne s'est produite
*/
ssize_t varuint_decode(const uint8_t *data, const size_t len, uint16_t *retval);
/*
* Encode un varuint en network byte-order dans le buffer data disposant d'une
* taille maximale len.
* @pre: val < 0x8000 (val peut être encode en varuint)
* @return:
* -1 si data ne contient pas une taille suffisante pour encoder le varuint
*
* la taille necessaire pour encoder le varuint (1 ou 2 bytes) si aucune erreur ne s'est produite
*/
ssize_t varuint_encode(uint16_t val, uint8_t *data, const size_t len);
/*
* @pre: data pointe vers un buffer d'au moins 1 byte
* @return: la taille en bytes du varuint stocke dans data, soit 1 ou 2 bytes.
*/
size_t varuint_len(const uint8_t *data);
/*
* @return: la taille en bytes que prendra la valeur val
* une fois encodee en varuint si val contient une valeur varuint valide (val < 0x8000).
-1 si val ne contient pas une valeur varuint valide
*/
ssize_t varuint_predict_len(uint16_t val);
/*
* Retourne la longueur du header en bytes si le champs pkt->length
* a une valeur valide pour un champs de type varuint (i.e. pkt->length < 0x8000).
* Retourne -1 sinon
* @pre: pkt contient une adresse valide (!= NULL)
*/
ssize_t predict_header_length(const pkt_t *pkt);
#endif /* __PACKET_INTERFACE_H_ */