-
Notifications
You must be signed in to change notification settings - Fork 10
/
Copy pathrudp_imp.h
290 lines (231 loc) · 7.23 KB
/
rudp_imp.h
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
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
#ifndef __rudp_imp_h__
#define __rudp_imp_h__
#include "basetype.h"
#include "linux_list.h"
#include "platform_adpt.h"
#ifndef BYTE_ORDER
#define BYTE_ORDER LITTLE_ENDIAN
#endif
#define RUDP_HEADER_TAG 3
#define MAX_LOSS_REPORT 63 //6 bits
#define MAX_WINDOW 4095 //12 bits
//rudp packet header: 16 bytes
struct rudp_hdr {
union {
uint32_t u32_flags;
/*
struct {
uint8_t tag;
uint8_t flags;
uint8_t window;
uint8_t chno;
} u8_flags;
*/
struct {
//little endian
#if BYTE_ORDER == LITTLE_ENDIAN
uint32_t chno:8;
uint32_t window:12;
uint32_t n_loss:6; //number of lost packets from "ackno". all packets before ackno are confirmed
uint32_t ack:1; //0: no ack; 1: accumulated ack
uint32_t rst:1;
uint32_t fin:1;
uint32_t syn:1;
uint32_t rudp:2; //RUDP_HEADER_TAG
#else
uint32_t rudp:2;
uint32_t syn:1;
uint32_t fin:1;
uint32_t rst:1;
uint32_t ack:1;
uint32_t n_loss:6;
uint32_t window:12; //counted by packages
uint32_t chno:8;
#endif
} flags;
};
uint32_t seqno; //
uint32_t ackno; //Ackknowlage all packets BEFORE "ackno". !!!
uint32_t crc32; //crc32 for header
};
#define PHY_HDR_CHN(hdr) (hdr.flags.chno&1)
#define PHY_CHN(chno) ((chno)&1)
//for 8bits window value
#define WINDOW_NTOH(window) window
#define WINDOW_HTON(window) window
//for 16bits window value
//#define WINDOW_NTOH(window) ntohs(window)
//#define WINDOW_HTON(window) htons(window)
//1456 = 1492(IEEE802.2) - 20(Ethernet) - 8(UDP) - 8(PPPoE) - ?
#define MAX_PACKET_SIZE 1448
#define MAX_DATA_SIZE (MAX_PACKET_SIZE-sizeof(struct rudp_hdr))
struct rudp_pkt {
struct rudp_pkt *next;
//data for sending
uint32_t seqno; //=ntohl(hdr.seqno), for quick reference
unsigned int ts; //timestamp when sending
int trans; //transmission count
int priority;
int len; //length of data, exclude hdr
unsigned char *pdata; //=data by default, move ahead when RUDPRecv is called and partial data in this packet are read out
//-----------------
struct rudp_hdr hdr;
unsigned char data[MAX_DATA_SIZE];
};
typedef enum {
RS_DEAD = -1, //all resources except the pointer to rudp_socket itself are freed, only RUDPClose() is allowed
RS_CLOSED = 0, //initally created or accepted
RS_LISTEN,
RS_SYN_SENT,
RS_SYN_RCVD,
RS_ESTABLISHED,
RS_CLOSE_WAIT,
RS_FIN_QUEUED,
RS_FIN_WAIT_1,
RS_FIN_WAIT_2,
RS_CLOSING,
RS_TIME_WAIT
} RUDPSTATE;
//----------------------------------------------
//
// 500ms TIMERs Used in RUDP PCB
//
// RT_xxx are for socket, RCT_xxx are for channel
//
#define RT_KEEP 0
#define RT_2MSL 1
#define RT_CNT 2
#define RCT_PERSIST 0
#define RCT_REXMT 1
#define RCT_CNT 2
#define RUDPT_RANGESET(tv, value, tvmin, tvmax) { \
(tv) = (value); \
if ((tv) < (tvmin)) \
(tv) = (tvmin); \
else if ((tv) > (tvmax)) \
(tv) = (tvmax); \
}
#define RTV_KEEP_INIT 15
#define RTV_REXMTMIN 2
#define RTV_REXMTMAX 128
#define RTV_PERSMIN 10
#define RTV_PERSMAX 120
#define RTV_KEEP_CLOSE 5
//----------------------------------------------
#define SEQ_LT(a,b) ((int)((a) - (b)) < 0)
#define SEQ_LE(a,b) ((int)((a) - (b)) <= 0)
#define SEQ_GT(a,b) ((int)((a) - (b)) > 0)
#define SEQ_GE(a,b) ((int)((a) - (b)) >= 0)
/* Buffer size of RUDP.
*
* One have to respect to the UDP buffer
* size (SO_SNDBUF, SO_RCVBUF)
*/
#define DEFAULT_SNDBUF_SIZE 128
#define DEFAULT_RCVBUF_SIZE 128
struct sndbuf {
uint32_t seqno;
int max_pkts; //OPT_RCVBUF
int n_pkt; /*packets in queue*/
int n_unacked;
struct rudp_pkt *first, *last;
struct rudp_pkt *not_sent; //first unsent packet
struct rudp_pkt *rexmt; //fast retransmit
int rawnd; //receiver's advertised window in ack
int rwnd; //keeping counted receiver's window, updated as packet is sent or ack is received
int rlost; //receiver reports how many packets are expected to be re-transmitted
/* counter for continuously duplicated acks,
* fast-retransmission starts when reach 3
*/
int dup_ack;
uint32_t fastretr_end_seq; //fast re-transmission stop untill this seqno
// RTT measurement
int stop_rttm; //stop rtt measurement
struct rudp_pkt *pkt_rttm_start; //rtt measurement resumes from pkt_rttm_start after any re-transmissions
};
struct rcvbuf {
uint32_t first_seq; //first seq in queue. this seq is pointed by "head"
uint32_t expected_seqno; //expected seqno
uint32_t acked_seqno; //ACK is sent when delay-time(DELAYED_MS) passed, or at most N(=3?) packets(or N*MSS bytes) received.
int should_ack; //new packet arrived, should send ack
int n_lost; //size of first gap(probably lost)
int q_size; //OPT_SNBUF
struct rudp_pkt **pkt_q; //size = q_size. A cycle buffer traced by head/tail
int head; //first packet or first lost packet in buffer
int loss; //first lost packet, or "tail"
int tail; //one after the packet with max seqno
int win; //receiver's window (q_size + head - tail - 1) % q_size, send in every output packet and ACK
/* queue for channels */
};
struct rudp_channel {
int timer[RCT_CNT];
int congested;
struct sndbuf sbuf;
struct rcvbuf rbuf;
};
#define MAX_PHY_CHANNELS 2
#define MAX_LOG_CHANNELS 128
struct rudp_pcb {
struct sockaddr_in local;
struct sockaddr_in peer;
/* Congestion Control */
/* ca_cnt: congestion avoidance counter.
* In the progress of congestion avoidance, plus 1
* when each ACK arrives, when "ca_cnt" reach "cwnd",
* reset "ca_cnt" and increase "cwnd" by one.
*/
int ca_cnt;
int cwnd; //congestion window
int ssthresh; //slow start threshold
/* RTO */
int srtt; //smoothed RTT
int sdev; //smoothed deviation, or "rttvar"
int rto; //retransmission timeout
int rwin_size; //receiver's win size. keep unchanged after connection is established
int rtw_size; //receiver's realtime win size
struct rudp_channel channel[MAX_PHY_CHANNELS];
int retr_cnt; // Count of SYN or SYN&ACK sent when connection establishment
};
struct rudp_socket;
typedef void (*_NONRUDPPACKETCB)(const uint8_t *buff, int len, void *p_user);
#define RUDP_SOCKET_TAG 0x50445552 //'RUDP'
#define RF_ADHOC 0x00000001
#define RF_NBLK 0x00000002
struct rudp_socket {
unsigned int tag; //'RUDP'
/* rudp_socket created by RUDPSocket/RUDPBindUdpSocket are
* linked with the inst_list chain(pointed by a global list header)
*/
struct list_head inst_list;
/* rudp_socket return by RUDPAccept are linked to the listening socket's accepted_list.
*
* If the listening socket is closed, the first accepted socket take place of
* the listening socket(move into the inst_list chain).
*
* "udp_sock" is shared by the sockets in the accepted_list chain, it is closed
* only when accepted_list is empty.
*/
struct list_head accepted_list;
/* sockets not accepted by RUDPAccept(...) are placed in a seperated chain,
* it's easy to be found when accepted and when the listening socket is closing
*/
struct list_head listen_queue;
int udp_sock;
BOOL connected; //called connect() on udp socket(client socket only)
int state; //RUDPSTATE, refer to TCP's FSM
int timer[RT_CNT];
struct rudp_pcb *pcb; //for
PA_MUTEX mutex_r, mutex_w;
#ifdef WIN32
HANDLE event_r, event_w;
#else
pthread_cond_t event_r, event_w;
#endif
int flags;
int rcvbuf_sz; //size of recv buffer, change before connection. OPT_RUDP_RCVBUF
int err;
//------------
_NONRUDPPACKETCB non_rudp_pkt_cb;
void *p_user;
};
#endif