renet 0.1.14 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,75 @@
1
+ /**
2
+ @file list.c
3
+ @brief ENet linked list functions
4
+ */
5
+ #define ENET_BUILDING_LIB 1
6
+ #include "enet/enet.h"
7
+
8
+ /**
9
+ @defgroup list ENet linked list utility functions
10
+ @ingroup private
11
+ @{
12
+ */
13
+ void
14
+ enet_list_clear (ENetList * list)
15
+ {
16
+ list -> sentinel.next = & list -> sentinel;
17
+ list -> sentinel.previous = & list -> sentinel;
18
+ }
19
+
20
+ ENetListIterator
21
+ enet_list_insert (ENetListIterator position, void * data)
22
+ {
23
+ ENetListIterator result = (ENetListIterator) data;
24
+
25
+ result -> previous = position -> previous;
26
+ result -> next = position;
27
+
28
+ result -> previous -> next = result;
29
+ position -> previous = result;
30
+
31
+ return result;
32
+ }
33
+
34
+ void *
35
+ enet_list_remove (ENetListIterator position)
36
+ {
37
+ position -> previous -> next = position -> next;
38
+ position -> next -> previous = position -> previous;
39
+
40
+ return position;
41
+ }
42
+
43
+ ENetListIterator
44
+ enet_list_move (ENetListIterator position, void * dataFirst, void * dataLast)
45
+ {
46
+ ENetListIterator first = (ENetListIterator) dataFirst,
47
+ last = (ENetListIterator) dataLast;
48
+
49
+ first -> previous -> next = last -> next;
50
+ last -> next -> previous = first -> previous;
51
+
52
+ first -> previous = position -> previous;
53
+ last -> next = position;
54
+
55
+ first -> previous -> next = first;
56
+ position -> previous = last;
57
+
58
+ return first;
59
+ }
60
+
61
+ size_t
62
+ enet_list_size (ENetList * list)
63
+ {
64
+ size_t size = 0;
65
+ ENetListIterator position;
66
+
67
+ for (position = enet_list_begin (list);
68
+ position != enet_list_end (list);
69
+ position = enet_list_next (position))
70
+ ++ size;
71
+
72
+ return size;
73
+ }
74
+
75
+ /** @} */
@@ -0,0 +1,165 @@
1
+ /**
2
+ @file packet.c
3
+ @brief ENet packet management functions
4
+ */
5
+ #include <string.h>
6
+ #define ENET_BUILDING_LIB 1
7
+ #include "enet/enet.h"
8
+
9
+ /** @defgroup Packet ENet packet functions
10
+ @{
11
+ */
12
+
13
+ /** Creates a packet that may be sent to a peer.
14
+ @param data initial contents of the packet's data; the packet's data will remain uninitialized if data is NULL.
15
+ @param dataLength size of the data allocated for this packet
16
+ @param flags flags for this packet as described for the ENetPacket structure.
17
+ @returns the packet on success, NULL on failure
18
+ */
19
+ ENetPacket *
20
+ enet_packet_create (const void * data, size_t dataLength, enet_uint32 flags)
21
+ {
22
+ ENetPacket * packet = (ENetPacket *) enet_malloc (sizeof (ENetPacket));
23
+ if (packet == NULL)
24
+ return NULL;
25
+
26
+ if (flags & ENET_PACKET_FLAG_NO_ALLOCATE)
27
+ packet -> data = (enet_uint8 *) data;
28
+ else
29
+ if (dataLength <= 0)
30
+ packet -> data = NULL;
31
+ else
32
+ {
33
+ packet -> data = (enet_uint8 *) enet_malloc (dataLength);
34
+ if (packet -> data == NULL)
35
+ {
36
+ enet_free (packet);
37
+ return NULL;
38
+ }
39
+
40
+ if (data != NULL)
41
+ memcpy (packet -> data, data, dataLength);
42
+ }
43
+
44
+ packet -> referenceCount = 0;
45
+ packet -> flags = flags;
46
+ packet -> dataLength = dataLength;
47
+ packet -> freeCallback = NULL;
48
+ packet -> userData = NULL;
49
+
50
+ return packet;
51
+ }
52
+
53
+ /** Destroys the packet and deallocates its data.
54
+ @param packet packet to be destroyed
55
+ */
56
+ void
57
+ enet_packet_destroy (ENetPacket * packet)
58
+ {
59
+ if (packet == NULL)
60
+ return;
61
+
62
+ if (packet -> freeCallback != NULL)
63
+ (* packet -> freeCallback) (packet);
64
+ if (! (packet -> flags & ENET_PACKET_FLAG_NO_ALLOCATE) &&
65
+ packet -> data != NULL)
66
+ enet_free (packet -> data);
67
+ enet_free (packet);
68
+ }
69
+
70
+ /** Attempts to resize the data in the packet to length specified in the
71
+ dataLength parameter
72
+ @param packet packet to resize
73
+ @param dataLength new size for the packet data
74
+ @returns 0 on success, < 0 on failure
75
+ */
76
+ int
77
+ enet_packet_resize (ENetPacket * packet, size_t dataLength)
78
+ {
79
+ enet_uint8 * newData;
80
+
81
+ if (dataLength <= packet -> dataLength || (packet -> flags & ENET_PACKET_FLAG_NO_ALLOCATE))
82
+ {
83
+ packet -> dataLength = dataLength;
84
+
85
+ return 0;
86
+ }
87
+
88
+ newData = (enet_uint8 *) enet_malloc (dataLength);
89
+ if (newData == NULL)
90
+ return -1;
91
+
92
+ memcpy (newData, packet -> data, packet -> dataLength);
93
+ enet_free (packet -> data);
94
+
95
+ packet -> data = newData;
96
+ packet -> dataLength = dataLength;
97
+
98
+ return 0;
99
+ }
100
+
101
+ static int initializedCRC32 = 0;
102
+ static enet_uint32 crcTable [256];
103
+
104
+ static enet_uint32
105
+ reflect_crc (int val, int bits)
106
+ {
107
+ int result = 0, bit;
108
+
109
+ for (bit = 0; bit < bits; bit ++)
110
+ {
111
+ if(val & 1) result |= 1 << (bits - 1 - bit);
112
+ val >>= 1;
113
+ }
114
+
115
+ return result;
116
+ }
117
+
118
+ static void
119
+ initialize_crc32 (void)
120
+ {
121
+ int byte;
122
+
123
+ for (byte = 0; byte < 256; ++ byte)
124
+ {
125
+ enet_uint32 crc = reflect_crc (byte, 8) << 24;
126
+ int offset;
127
+
128
+ for(offset = 0; offset < 8; ++ offset)
129
+ {
130
+ if (crc & 0x80000000)
131
+ crc = (crc << 1) ^ 0x04c11db7;
132
+ else
133
+ crc <<= 1;
134
+ }
135
+
136
+ crcTable [byte] = reflect_crc (crc, 32);
137
+ }
138
+
139
+ initializedCRC32 = 1;
140
+ }
141
+
142
+ enet_uint32
143
+ enet_crc32 (const ENetBuffer * buffers, size_t bufferCount)
144
+ {
145
+ enet_uint32 crc = 0xFFFFFFFF;
146
+
147
+ if (! initializedCRC32) initialize_crc32 ();
148
+
149
+ while (bufferCount -- > 0)
150
+ {
151
+ const enet_uint8 * data = (const enet_uint8 *) buffers -> data,
152
+ * dataEnd = & data [buffers -> dataLength];
153
+
154
+ while (data < dataEnd)
155
+ {
156
+ crc = (crc >> 8) ^ crcTable [(crc & 0xFF) ^ *data++];
157
+ }
158
+
159
+ ++ buffers;
160
+ }
161
+
162
+ return ENET_HOST_TO_NET_32 (~ crc);
163
+ }
164
+
165
+ /** @} */
@@ -0,0 +1,1004 @@
1
+ /**
2
+ @file peer.c
3
+ @brief ENet peer management functions
4
+ */
5
+ #include <string.h>
6
+ #define ENET_BUILDING_LIB 1
7
+ #include "enet/enet.h"
8
+
9
+ /** @defgroup peer ENet peer functions
10
+ @{
11
+ */
12
+
13
+ /** Configures throttle parameter for a peer.
14
+
15
+ Unreliable packets are dropped by ENet in response to the varying conditions
16
+ of the Internet connection to the peer. The throttle represents a probability
17
+ that an unreliable packet should not be dropped and thus sent by ENet to the peer.
18
+ The lowest mean round trip time from the sending of a reliable packet to the
19
+ receipt of its acknowledgement is measured over an amount of time specified by
20
+ the interval parameter in milliseconds. If a measured round trip time happens to
21
+ be significantly less than the mean round trip time measured over the interval,
22
+ then the throttle probability is increased to allow more traffic by an amount
23
+ specified in the acceleration parameter, which is a ratio to the ENET_PEER_PACKET_THROTTLE_SCALE
24
+ constant. If a measured round trip time happens to be significantly greater than
25
+ the mean round trip time measured over the interval, then the throttle probability
26
+ is decreased to limit traffic by an amount specified in the deceleration parameter, which
27
+ is a ratio to the ENET_PEER_PACKET_THROTTLE_SCALE constant. When the throttle has
28
+ a value of ENET_PEER_PACKET_THROTTLE_SCALE, no unreliable packets are dropped by
29
+ ENet, and so 100% of all unreliable packets will be sent. When the throttle has a
30
+ value of 0, all unreliable packets are dropped by ENet, and so 0% of all unreliable
31
+ packets will be sent. Intermediate values for the throttle represent intermediate
32
+ probabilities between 0% and 100% of unreliable packets being sent. The bandwidth
33
+ limits of the local and foreign hosts are taken into account to determine a
34
+ sensible limit for the throttle probability above which it should not raise even in
35
+ the best of conditions.
36
+
37
+ @param peer peer to configure
38
+ @param interval interval, in milliseconds, over which to measure lowest mean RTT; the default value is ENET_PEER_PACKET_THROTTLE_INTERVAL.
39
+ @param acceleration rate at which to increase the throttle probability as mean RTT declines
40
+ @param deceleration rate at which to decrease the throttle probability as mean RTT increases
41
+ */
42
+ void
43
+ enet_peer_throttle_configure (ENetPeer * peer, enet_uint32 interval, enet_uint32 acceleration, enet_uint32 deceleration)
44
+ {
45
+ ENetProtocol command;
46
+
47
+ peer -> packetThrottleInterval = interval;
48
+ peer -> packetThrottleAcceleration = acceleration;
49
+ peer -> packetThrottleDeceleration = deceleration;
50
+
51
+ command.header.command = ENET_PROTOCOL_COMMAND_THROTTLE_CONFIGURE | ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE;
52
+ command.header.channelID = 0xFF;
53
+
54
+ command.throttleConfigure.packetThrottleInterval = ENET_HOST_TO_NET_32 (interval);
55
+ command.throttleConfigure.packetThrottleAcceleration = ENET_HOST_TO_NET_32 (acceleration);
56
+ command.throttleConfigure.packetThrottleDeceleration = ENET_HOST_TO_NET_32 (deceleration);
57
+
58
+ enet_peer_queue_outgoing_command (peer, & command, NULL, 0, 0);
59
+ }
60
+
61
+ int
62
+ enet_peer_throttle (ENetPeer * peer, enet_uint32 rtt)
63
+ {
64
+ if (peer -> lastRoundTripTime <= peer -> lastRoundTripTimeVariance)
65
+ {
66
+ peer -> packetThrottle = peer -> packetThrottleLimit;
67
+ }
68
+ else
69
+ if (rtt < peer -> lastRoundTripTime)
70
+ {
71
+ peer -> packetThrottle += peer -> packetThrottleAcceleration;
72
+
73
+ if (peer -> packetThrottle > peer -> packetThrottleLimit)
74
+ peer -> packetThrottle = peer -> packetThrottleLimit;
75
+
76
+ return 1;
77
+ }
78
+ else
79
+ if (rtt > peer -> lastRoundTripTime + 2 * peer -> lastRoundTripTimeVariance)
80
+ {
81
+ if (peer -> packetThrottle > peer -> packetThrottleDeceleration)
82
+ peer -> packetThrottle -= peer -> packetThrottleDeceleration;
83
+ else
84
+ peer -> packetThrottle = 0;
85
+
86
+ return -1;
87
+ }
88
+
89
+ return 0;
90
+ }
91
+
92
+ /** Queues a packet to be sent.
93
+ @param peer destination for the packet
94
+ @param channelID channel on which to send
95
+ @param packet packet to send
96
+ @retval 0 on success
97
+ @retval < 0 on failure
98
+ */
99
+ int
100
+ enet_peer_send (ENetPeer * peer, enet_uint8 channelID, ENetPacket * packet)
101
+ {
102
+ ENetChannel * channel = & peer -> channels [channelID];
103
+ ENetProtocol command;
104
+ size_t fragmentLength;
105
+
106
+ if (peer -> state != ENET_PEER_STATE_CONNECTED ||
107
+ channelID >= peer -> channelCount ||
108
+ packet -> dataLength > peer -> host -> maximumPacketSize)
109
+ return -1;
110
+
111
+ fragmentLength = peer -> mtu - sizeof (ENetProtocolHeader) - sizeof (ENetProtocolSendFragment);
112
+ if (peer -> host -> checksum != NULL)
113
+ fragmentLength -= sizeof(enet_uint32);
114
+
115
+ if (packet -> dataLength > fragmentLength)
116
+ {
117
+ enet_uint32 fragmentCount = (packet -> dataLength + fragmentLength - 1) / fragmentLength,
118
+ fragmentNumber,
119
+ fragmentOffset;
120
+ enet_uint8 commandNumber;
121
+ enet_uint16 startSequenceNumber;
122
+ ENetList fragments;
123
+ ENetOutgoingCommand * fragment;
124
+
125
+ if (fragmentCount > ENET_PROTOCOL_MAXIMUM_FRAGMENT_COUNT)
126
+ return -1;
127
+
128
+ if ((packet -> flags & (ENET_PACKET_FLAG_RELIABLE | ENET_PACKET_FLAG_UNRELIABLE_FRAGMENT)) == ENET_PACKET_FLAG_UNRELIABLE_FRAGMENT &&
129
+ channel -> outgoingUnreliableSequenceNumber < 0xFFFF)
130
+ {
131
+ commandNumber = ENET_PROTOCOL_COMMAND_SEND_UNRELIABLE_FRAGMENT;
132
+ startSequenceNumber = ENET_HOST_TO_NET_16 (channel -> outgoingUnreliableSequenceNumber + 1);
133
+ }
134
+ else
135
+ {
136
+ commandNumber = ENET_PROTOCOL_COMMAND_SEND_FRAGMENT | ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE;
137
+ startSequenceNumber = ENET_HOST_TO_NET_16 (channel -> outgoingReliableSequenceNumber + 1);
138
+ }
139
+
140
+ enet_list_clear (& fragments);
141
+
142
+ for (fragmentNumber = 0,
143
+ fragmentOffset = 0;
144
+ fragmentOffset < packet -> dataLength;
145
+ ++ fragmentNumber,
146
+ fragmentOffset += fragmentLength)
147
+ {
148
+ if (packet -> dataLength - fragmentOffset < fragmentLength)
149
+ fragmentLength = packet -> dataLength - fragmentOffset;
150
+
151
+ fragment = (ENetOutgoingCommand *) enet_malloc (sizeof (ENetOutgoingCommand));
152
+ if (fragment == NULL)
153
+ {
154
+ while (! enet_list_empty (& fragments))
155
+ {
156
+ fragment = (ENetOutgoingCommand *) enet_list_remove (enet_list_begin (& fragments));
157
+
158
+ enet_free (fragment);
159
+ }
160
+
161
+ return -1;
162
+ }
163
+
164
+ fragment -> fragmentOffset = fragmentOffset;
165
+ fragment -> fragmentLength = fragmentLength;
166
+ fragment -> packet = packet;
167
+ fragment -> command.header.command = commandNumber;
168
+ fragment -> command.header.channelID = channelID;
169
+ fragment -> command.sendFragment.startSequenceNumber = startSequenceNumber;
170
+ fragment -> command.sendFragment.dataLength = ENET_HOST_TO_NET_16 (fragmentLength);
171
+ fragment -> command.sendFragment.fragmentCount = ENET_HOST_TO_NET_32 (fragmentCount);
172
+ fragment -> command.sendFragment.fragmentNumber = ENET_HOST_TO_NET_32 (fragmentNumber);
173
+ fragment -> command.sendFragment.totalLength = ENET_HOST_TO_NET_32 (packet -> dataLength);
174
+ fragment -> command.sendFragment.fragmentOffset = ENET_NET_TO_HOST_32 (fragmentOffset);
175
+
176
+ enet_list_insert (enet_list_end (& fragments), fragment);
177
+ }
178
+
179
+ packet -> referenceCount += fragmentNumber;
180
+
181
+ while (! enet_list_empty (& fragments))
182
+ {
183
+ fragment = (ENetOutgoingCommand *) enet_list_remove (enet_list_begin (& fragments));
184
+
185
+ enet_peer_setup_outgoing_command (peer, fragment);
186
+ }
187
+
188
+ return 0;
189
+ }
190
+
191
+ command.header.channelID = channelID;
192
+
193
+ if ((packet -> flags & (ENET_PACKET_FLAG_RELIABLE | ENET_PACKET_FLAG_UNSEQUENCED)) == ENET_PACKET_FLAG_UNSEQUENCED)
194
+ {
195
+ command.header.command = ENET_PROTOCOL_COMMAND_SEND_UNSEQUENCED | ENET_PROTOCOL_COMMAND_FLAG_UNSEQUENCED;
196
+ command.sendUnsequenced.dataLength = ENET_HOST_TO_NET_16 (packet -> dataLength);
197
+ }
198
+ else
199
+ if (packet -> flags & ENET_PACKET_FLAG_RELIABLE || channel -> outgoingUnreliableSequenceNumber >= 0xFFFF)
200
+ {
201
+ command.header.command = ENET_PROTOCOL_COMMAND_SEND_RELIABLE | ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE;
202
+ command.sendReliable.dataLength = ENET_HOST_TO_NET_16 (packet -> dataLength);
203
+ }
204
+ else
205
+ {
206
+ command.header.command = ENET_PROTOCOL_COMMAND_SEND_UNRELIABLE;
207
+ command.sendUnreliable.dataLength = ENET_HOST_TO_NET_16 (packet -> dataLength);
208
+ }
209
+
210
+ if (enet_peer_queue_outgoing_command (peer, & command, packet, 0, packet -> dataLength) == NULL)
211
+ return -1;
212
+
213
+ return 0;
214
+ }
215
+
216
+ /** Attempts to dequeue any incoming queued packet.
217
+ @param peer peer to dequeue packets from
218
+ @param channelID holds the channel ID of the channel the packet was received on success
219
+ @returns a pointer to the packet, or NULL if there are no available incoming queued packets
220
+ */
221
+ ENetPacket *
222
+ enet_peer_receive (ENetPeer * peer, enet_uint8 * channelID)
223
+ {
224
+ ENetIncomingCommand * incomingCommand;
225
+ ENetPacket * packet;
226
+
227
+ if (enet_list_empty (& peer -> dispatchedCommands))
228
+ return NULL;
229
+
230
+ incomingCommand = (ENetIncomingCommand *) enet_list_remove (enet_list_begin (& peer -> dispatchedCommands));
231
+
232
+ if (channelID != NULL)
233
+ * channelID = incomingCommand -> command.header.channelID;
234
+
235
+ packet = incomingCommand -> packet;
236
+
237
+ -- packet -> referenceCount;
238
+
239
+ if (incomingCommand -> fragments != NULL)
240
+ enet_free (incomingCommand -> fragments);
241
+
242
+ enet_free (incomingCommand);
243
+
244
+ peer -> totalWaitingData -= packet -> dataLength;
245
+
246
+ return packet;
247
+ }
248
+
249
+ static void
250
+ enet_peer_reset_outgoing_commands (ENetList * queue)
251
+ {
252
+ ENetOutgoingCommand * outgoingCommand;
253
+
254
+ while (! enet_list_empty (queue))
255
+ {
256
+ outgoingCommand = (ENetOutgoingCommand *) enet_list_remove (enet_list_begin (queue));
257
+
258
+ if (outgoingCommand -> packet != NULL)
259
+ {
260
+ -- outgoingCommand -> packet -> referenceCount;
261
+
262
+ if (outgoingCommand -> packet -> referenceCount == 0)
263
+ enet_packet_destroy (outgoingCommand -> packet);
264
+ }
265
+
266
+ enet_free (outgoingCommand);
267
+ }
268
+ }
269
+
270
+ static void
271
+ enet_peer_remove_incoming_commands (ENetList * queue, ENetListIterator startCommand, ENetListIterator endCommand)
272
+ {
273
+ ENetListIterator currentCommand;
274
+
275
+ for (currentCommand = startCommand; currentCommand != endCommand; )
276
+ {
277
+ ENetIncomingCommand * incomingCommand = (ENetIncomingCommand *) currentCommand;
278
+
279
+ currentCommand = enet_list_next (currentCommand);
280
+
281
+ enet_list_remove (& incomingCommand -> incomingCommandList);
282
+
283
+ if (incomingCommand -> packet != NULL)
284
+ {
285
+ -- incomingCommand -> packet -> referenceCount;
286
+
287
+ if (incomingCommand -> packet -> referenceCount == 0)
288
+ enet_packet_destroy (incomingCommand -> packet);
289
+ }
290
+
291
+ if (incomingCommand -> fragments != NULL)
292
+ enet_free (incomingCommand -> fragments);
293
+
294
+ enet_free (incomingCommand);
295
+ }
296
+ }
297
+
298
+ static void
299
+ enet_peer_reset_incoming_commands (ENetList * queue)
300
+ {
301
+ enet_peer_remove_incoming_commands(queue, enet_list_begin (queue), enet_list_end (queue));
302
+ }
303
+
304
+ void
305
+ enet_peer_reset_queues (ENetPeer * peer)
306
+ {
307
+ ENetChannel * channel;
308
+
309
+ if (peer -> needsDispatch)
310
+ {
311
+ enet_list_remove (& peer -> dispatchList);
312
+
313
+ peer -> needsDispatch = 0;
314
+ }
315
+
316
+ while (! enet_list_empty (& peer -> acknowledgements))
317
+ enet_free (enet_list_remove (enet_list_begin (& peer -> acknowledgements)));
318
+
319
+ enet_peer_reset_outgoing_commands (& peer -> sentReliableCommands);
320
+ enet_peer_reset_outgoing_commands (& peer -> sentUnreliableCommands);
321
+ enet_peer_reset_outgoing_commands (& peer -> outgoingReliableCommands);
322
+ enet_peer_reset_outgoing_commands (& peer -> outgoingUnreliableCommands);
323
+ enet_peer_reset_incoming_commands (& peer -> dispatchedCommands);
324
+
325
+ if (peer -> channels != NULL && peer -> channelCount > 0)
326
+ {
327
+ for (channel = peer -> channels;
328
+ channel < & peer -> channels [peer -> channelCount];
329
+ ++ channel)
330
+ {
331
+ enet_peer_reset_incoming_commands (& channel -> incomingReliableCommands);
332
+ enet_peer_reset_incoming_commands (& channel -> incomingUnreliableCommands);
333
+ }
334
+
335
+ enet_free (peer -> channels);
336
+ }
337
+
338
+ peer -> channels = NULL;
339
+ peer -> channelCount = 0;
340
+ }
341
+
342
+ void
343
+ enet_peer_on_connect (ENetPeer * peer)
344
+ {
345
+ if (peer -> state != ENET_PEER_STATE_CONNECTED && peer -> state != ENET_PEER_STATE_DISCONNECT_LATER)
346
+ {
347
+ if (peer -> incomingBandwidth != 0)
348
+ ++ peer -> host -> bandwidthLimitedPeers;
349
+
350
+ ++ peer -> host -> connectedPeers;
351
+ }
352
+ }
353
+
354
+ void
355
+ enet_peer_on_disconnect (ENetPeer * peer)
356
+ {
357
+ if (peer -> state == ENET_PEER_STATE_CONNECTED || peer -> state == ENET_PEER_STATE_DISCONNECT_LATER)
358
+ {
359
+ if (peer -> incomingBandwidth != 0)
360
+ -- peer -> host -> bandwidthLimitedPeers;
361
+
362
+ -- peer -> host -> connectedPeers;
363
+ }
364
+ }
365
+
366
+ /** Forcefully disconnects a peer.
367
+ @param peer peer to forcefully disconnect
368
+ @remarks The foreign host represented by the peer is not notified of the disconnection and will timeout
369
+ on its connection to the local host.
370
+ */
371
+ void
372
+ enet_peer_reset (ENetPeer * peer)
373
+ {
374
+ enet_peer_on_disconnect (peer);
375
+
376
+ peer -> outgoingPeerID = ENET_PROTOCOL_MAXIMUM_PEER_ID;
377
+ peer -> connectID = 0;
378
+
379
+ peer -> state = ENET_PEER_STATE_DISCONNECTED;
380
+
381
+ peer -> incomingBandwidth = 0;
382
+ peer -> outgoingBandwidth = 0;
383
+ peer -> incomingBandwidthThrottleEpoch = 0;
384
+ peer -> outgoingBandwidthThrottleEpoch = 0;
385
+ peer -> incomingDataTotal = 0;
386
+ peer -> outgoingDataTotal = 0;
387
+ peer -> lastSendTime = 0;
388
+ peer -> lastReceiveTime = 0;
389
+ peer -> nextTimeout = 0;
390
+ peer -> earliestTimeout = 0;
391
+ peer -> packetLossEpoch = 0;
392
+ peer -> packetsSent = 0;
393
+ peer -> packetsLost = 0;
394
+ peer -> packetLoss = 0;
395
+ peer -> packetLossVariance = 0;
396
+ peer -> packetThrottle = ENET_PEER_DEFAULT_PACKET_THROTTLE;
397
+ peer -> packetThrottleLimit = ENET_PEER_PACKET_THROTTLE_SCALE;
398
+ peer -> packetThrottleCounter = 0;
399
+ peer -> packetThrottleEpoch = 0;
400
+ peer -> packetThrottleAcceleration = ENET_PEER_PACKET_THROTTLE_ACCELERATION;
401
+ peer -> packetThrottleDeceleration = ENET_PEER_PACKET_THROTTLE_DECELERATION;
402
+ peer -> packetThrottleInterval = ENET_PEER_PACKET_THROTTLE_INTERVAL;
403
+ peer -> pingInterval = ENET_PEER_PING_INTERVAL;
404
+ peer -> timeoutLimit = ENET_PEER_TIMEOUT_LIMIT;
405
+ peer -> timeoutMinimum = ENET_PEER_TIMEOUT_MINIMUM;
406
+ peer -> timeoutMaximum = ENET_PEER_TIMEOUT_MAXIMUM;
407
+ peer -> lastRoundTripTime = ENET_PEER_DEFAULT_ROUND_TRIP_TIME;
408
+ peer -> lowestRoundTripTime = ENET_PEER_DEFAULT_ROUND_TRIP_TIME;
409
+ peer -> lastRoundTripTimeVariance = 0;
410
+ peer -> highestRoundTripTimeVariance = 0;
411
+ peer -> roundTripTime = ENET_PEER_DEFAULT_ROUND_TRIP_TIME;
412
+ peer -> roundTripTimeVariance = 0;
413
+ peer -> mtu = peer -> host -> mtu;
414
+ peer -> reliableDataInTransit = 0;
415
+ peer -> outgoingReliableSequenceNumber = 0;
416
+ peer -> windowSize = ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE;
417
+ peer -> incomingUnsequencedGroup = 0;
418
+ peer -> outgoingUnsequencedGroup = 0;
419
+ peer -> eventData = 0;
420
+ peer -> totalWaitingData = 0;
421
+
422
+ memset (peer -> unsequencedWindow, 0, sizeof (peer -> unsequencedWindow));
423
+
424
+ enet_peer_reset_queues (peer);
425
+ }
426
+
427
+ /** Sends a ping request to a peer.
428
+ @param peer destination for the ping request
429
+ @remarks ping requests factor into the mean round trip time as designated by the
430
+ roundTripTime field in the ENetPeer structure. ENet automatically pings all connected
431
+ peers at regular intervals, however, this function may be called to ensure more
432
+ frequent ping requests.
433
+ */
434
+ void
435
+ enet_peer_ping (ENetPeer * peer)
436
+ {
437
+ ENetProtocol command;
438
+
439
+ if (peer -> state != ENET_PEER_STATE_CONNECTED)
440
+ return;
441
+
442
+ command.header.command = ENET_PROTOCOL_COMMAND_PING | ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE;
443
+ command.header.channelID = 0xFF;
444
+
445
+ enet_peer_queue_outgoing_command (peer, & command, NULL, 0, 0);
446
+ }
447
+
448
+ /** Sets the interval at which pings will be sent to a peer.
449
+
450
+ Pings are used both to monitor the liveness of the connection and also to dynamically
451
+ adjust the throttle during periods of low traffic so that the throttle has reasonable
452
+ responsiveness during traffic spikes.
453
+
454
+ @param peer the peer to adjust
455
+ @param pingInterval the interval at which to send pings; defaults to ENET_PEER_PING_INTERVAL if 0
456
+ */
457
+ void
458
+ enet_peer_ping_interval (ENetPeer * peer, enet_uint32 pingInterval)
459
+ {
460
+ peer -> pingInterval = pingInterval ? pingInterval : ENET_PEER_PING_INTERVAL;
461
+ }
462
+
463
+ /** Sets the timeout parameters for a peer.
464
+
465
+ The timeout parameter control how and when a peer will timeout from a failure to acknowledge
466
+ reliable traffic. Timeout values use an exponential backoff mechanism, where if a reliable
467
+ packet is not acknowledge within some multiple of the average RTT plus a variance tolerance,
468
+ the timeout will be doubled until it reaches a set limit. If the timeout is thus at this
469
+ limit and reliable packets have been sent but not acknowledged within a certain minimum time
470
+ period, the peer will be disconnected. Alternatively, if reliable packets have been sent
471
+ but not acknowledged for a certain maximum time period, the peer will be disconnected regardless
472
+ of the current timeout limit value.
473
+
474
+ @param peer the peer to adjust
475
+ @param timeoutLimit the timeout limit; defaults to ENET_PEER_TIMEOUT_LIMIT if 0
476
+ @param timeoutMinimum the timeout minimum; defaults to ENET_PEER_TIMEOUT_MINIMUM if 0
477
+ @param timeoutMaximum the timeout maximum; defaults to ENET_PEER_TIMEOUT_MAXIMUM if 0
478
+ */
479
+
480
+ void
481
+ enet_peer_timeout (ENetPeer * peer, enet_uint32 timeoutLimit, enet_uint32 timeoutMinimum, enet_uint32 timeoutMaximum)
482
+ {
483
+ peer -> timeoutLimit = timeoutLimit ? timeoutLimit : ENET_PEER_TIMEOUT_LIMIT;
484
+ peer -> timeoutMinimum = timeoutMinimum ? timeoutMinimum : ENET_PEER_TIMEOUT_MINIMUM;
485
+ peer -> timeoutMaximum = timeoutMaximum ? timeoutMaximum : ENET_PEER_TIMEOUT_MAXIMUM;
486
+ }
487
+
488
+ /** Force an immediate disconnection from a peer.
489
+ @param peer peer to disconnect
490
+ @param data data describing the disconnection
491
+ @remarks No ENET_EVENT_DISCONNECT event will be generated. The foreign peer is not
492
+ guaranteed to receive the disconnect notification, and is reset immediately upon
493
+ return from this function.
494
+ */
495
+ void
496
+ enet_peer_disconnect_now (ENetPeer * peer, enet_uint32 data)
497
+ {
498
+ ENetProtocol command;
499
+
500
+ if (peer -> state == ENET_PEER_STATE_DISCONNECTED)
501
+ return;
502
+
503
+ if (peer -> state != ENET_PEER_STATE_ZOMBIE &&
504
+ peer -> state != ENET_PEER_STATE_DISCONNECTING)
505
+ {
506
+ enet_peer_reset_queues (peer);
507
+
508
+ command.header.command = ENET_PROTOCOL_COMMAND_DISCONNECT | ENET_PROTOCOL_COMMAND_FLAG_UNSEQUENCED;
509
+ command.header.channelID = 0xFF;
510
+ command.disconnect.data = ENET_HOST_TO_NET_32 (data);
511
+
512
+ enet_peer_queue_outgoing_command (peer, & command, NULL, 0, 0);
513
+
514
+ enet_host_flush (peer -> host);
515
+ }
516
+
517
+ enet_peer_reset (peer);
518
+ }
519
+
520
+ /** Request a disconnection from a peer.
521
+ @param peer peer to request a disconnection
522
+ @param data data describing the disconnection
523
+ @remarks An ENET_EVENT_DISCONNECT event will be generated by enet_host_service()
524
+ once the disconnection is complete.
525
+ */
526
+ void
527
+ enet_peer_disconnect (ENetPeer * peer, enet_uint32 data)
528
+ {
529
+ ENetProtocol command;
530
+
531
+ if (peer -> state == ENET_PEER_STATE_DISCONNECTING ||
532
+ peer -> state == ENET_PEER_STATE_DISCONNECTED ||
533
+ peer -> state == ENET_PEER_STATE_ACKNOWLEDGING_DISCONNECT ||
534
+ peer -> state == ENET_PEER_STATE_ZOMBIE)
535
+ return;
536
+
537
+ enet_peer_reset_queues (peer);
538
+
539
+ command.header.command = ENET_PROTOCOL_COMMAND_DISCONNECT;
540
+ command.header.channelID = 0xFF;
541
+ command.disconnect.data = ENET_HOST_TO_NET_32 (data);
542
+
543
+ if (peer -> state == ENET_PEER_STATE_CONNECTED || peer -> state == ENET_PEER_STATE_DISCONNECT_LATER)
544
+ command.header.command |= ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE;
545
+ else
546
+ command.header.command |= ENET_PROTOCOL_COMMAND_FLAG_UNSEQUENCED;
547
+
548
+ enet_peer_queue_outgoing_command (peer, & command, NULL, 0, 0);
549
+
550
+ if (peer -> state == ENET_PEER_STATE_CONNECTED || peer -> state == ENET_PEER_STATE_DISCONNECT_LATER)
551
+ {
552
+ enet_peer_on_disconnect (peer);
553
+
554
+ peer -> state = ENET_PEER_STATE_DISCONNECTING;
555
+ }
556
+ else
557
+ {
558
+ enet_host_flush (peer -> host);
559
+ enet_peer_reset (peer);
560
+ }
561
+ }
562
+
563
+ /** Request a disconnection from a peer, but only after all queued outgoing packets are sent.
564
+ @param peer peer to request a disconnection
565
+ @param data data describing the disconnection
566
+ @remarks An ENET_EVENT_DISCONNECT event will be generated by enet_host_service()
567
+ once the disconnection is complete.
568
+ */
569
+ void
570
+ enet_peer_disconnect_later (ENetPeer * peer, enet_uint32 data)
571
+ {
572
+ if ((peer -> state == ENET_PEER_STATE_CONNECTED || peer -> state == ENET_PEER_STATE_DISCONNECT_LATER) &&
573
+ ! (enet_list_empty (& peer -> outgoingReliableCommands) &&
574
+ enet_list_empty (& peer -> outgoingUnreliableCommands) &&
575
+ enet_list_empty (& peer -> sentReliableCommands)))
576
+ {
577
+ peer -> state = ENET_PEER_STATE_DISCONNECT_LATER;
578
+ peer -> eventData = data;
579
+ }
580
+ else
581
+ enet_peer_disconnect (peer, data);
582
+ }
583
+
584
+ ENetAcknowledgement *
585
+ enet_peer_queue_acknowledgement (ENetPeer * peer, const ENetProtocol * command, enet_uint16 sentTime)
586
+ {
587
+ ENetAcknowledgement * acknowledgement;
588
+
589
+ if (command -> header.channelID < peer -> channelCount)
590
+ {
591
+ ENetChannel * channel = & peer -> channels [command -> header.channelID];
592
+ enet_uint16 reliableWindow = command -> header.reliableSequenceNumber / ENET_PEER_RELIABLE_WINDOW_SIZE,
593
+ currentWindow = channel -> incomingReliableSequenceNumber / ENET_PEER_RELIABLE_WINDOW_SIZE;
594
+
595
+ if (command -> header.reliableSequenceNumber < channel -> incomingReliableSequenceNumber)
596
+ reliableWindow += ENET_PEER_RELIABLE_WINDOWS;
597
+
598
+ if (reliableWindow >= currentWindow + ENET_PEER_FREE_RELIABLE_WINDOWS - 1 && reliableWindow <= currentWindow + ENET_PEER_FREE_RELIABLE_WINDOWS)
599
+ return NULL;
600
+ }
601
+
602
+ acknowledgement = (ENetAcknowledgement *) enet_malloc (sizeof (ENetAcknowledgement));
603
+ if (acknowledgement == NULL)
604
+ return NULL;
605
+
606
+ peer -> outgoingDataTotal += sizeof (ENetProtocolAcknowledge);
607
+
608
+ acknowledgement -> sentTime = sentTime;
609
+ acknowledgement -> command = * command;
610
+
611
+ enet_list_insert (enet_list_end (& peer -> acknowledgements), acknowledgement);
612
+
613
+ return acknowledgement;
614
+ }
615
+
616
+ void
617
+ enet_peer_setup_outgoing_command (ENetPeer * peer, ENetOutgoingCommand * outgoingCommand)
618
+ {
619
+ ENetChannel * channel = & peer -> channels [outgoingCommand -> command.header.channelID];
620
+
621
+ peer -> outgoingDataTotal += enet_protocol_command_size (outgoingCommand -> command.header.command) + outgoingCommand -> fragmentLength;
622
+
623
+ if (outgoingCommand -> command.header.channelID == 0xFF)
624
+ {
625
+ ++ peer -> outgoingReliableSequenceNumber;
626
+
627
+ outgoingCommand -> reliableSequenceNumber = peer -> outgoingReliableSequenceNumber;
628
+ outgoingCommand -> unreliableSequenceNumber = 0;
629
+ }
630
+ else
631
+ if (outgoingCommand -> command.header.command & ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE)
632
+ {
633
+ ++ channel -> outgoingReliableSequenceNumber;
634
+ channel -> outgoingUnreliableSequenceNumber = 0;
635
+
636
+ outgoingCommand -> reliableSequenceNumber = channel -> outgoingReliableSequenceNumber;
637
+ outgoingCommand -> unreliableSequenceNumber = 0;
638
+ }
639
+ else
640
+ if (outgoingCommand -> command.header.command & ENET_PROTOCOL_COMMAND_FLAG_UNSEQUENCED)
641
+ {
642
+ ++ peer -> outgoingUnsequencedGroup;
643
+
644
+ outgoingCommand -> reliableSequenceNumber = 0;
645
+ outgoingCommand -> unreliableSequenceNumber = 0;
646
+ }
647
+ else
648
+ {
649
+ if (outgoingCommand -> fragmentOffset == 0)
650
+ ++ channel -> outgoingUnreliableSequenceNumber;
651
+
652
+ outgoingCommand -> reliableSequenceNumber = channel -> outgoingReliableSequenceNumber;
653
+ outgoingCommand -> unreliableSequenceNumber = channel -> outgoingUnreliableSequenceNumber;
654
+ }
655
+
656
+ outgoingCommand -> sendAttempts = 0;
657
+ outgoingCommand -> sentTime = 0;
658
+ outgoingCommand -> roundTripTimeout = 0;
659
+ outgoingCommand -> roundTripTimeoutLimit = 0;
660
+ outgoingCommand -> command.header.reliableSequenceNumber = ENET_HOST_TO_NET_16 (outgoingCommand -> reliableSequenceNumber);
661
+
662
+ switch (outgoingCommand -> command.header.command & ENET_PROTOCOL_COMMAND_MASK)
663
+ {
664
+ case ENET_PROTOCOL_COMMAND_SEND_UNRELIABLE:
665
+ outgoingCommand -> command.sendUnreliable.unreliableSequenceNumber = ENET_HOST_TO_NET_16 (outgoingCommand -> unreliableSequenceNumber);
666
+ break;
667
+
668
+ case ENET_PROTOCOL_COMMAND_SEND_UNSEQUENCED:
669
+ outgoingCommand -> command.sendUnsequenced.unsequencedGroup = ENET_HOST_TO_NET_16 (peer -> outgoingUnsequencedGroup);
670
+ break;
671
+
672
+ default:
673
+ break;
674
+ }
675
+
676
+ if (outgoingCommand -> command.header.command & ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE)
677
+ enet_list_insert (enet_list_end (& peer -> outgoingReliableCommands), outgoingCommand);
678
+ else
679
+ enet_list_insert (enet_list_end (& peer -> outgoingUnreliableCommands), outgoingCommand);
680
+ }
681
+
682
+ ENetOutgoingCommand *
683
+ enet_peer_queue_outgoing_command (ENetPeer * peer, const ENetProtocol * command, ENetPacket * packet, enet_uint32 offset, enet_uint16 length)
684
+ {
685
+ ENetOutgoingCommand * outgoingCommand = (ENetOutgoingCommand *) enet_malloc (sizeof (ENetOutgoingCommand));
686
+ if (outgoingCommand == NULL)
687
+ return NULL;
688
+
689
+ outgoingCommand -> command = * command;
690
+ outgoingCommand -> fragmentOffset = offset;
691
+ outgoingCommand -> fragmentLength = length;
692
+ outgoingCommand -> packet = packet;
693
+ if (packet != NULL)
694
+ ++ packet -> referenceCount;
695
+
696
+ enet_peer_setup_outgoing_command (peer, outgoingCommand);
697
+
698
+ return outgoingCommand;
699
+ }
700
+
701
+ void
702
+ enet_peer_dispatch_incoming_unreliable_commands (ENetPeer * peer, ENetChannel * channel)
703
+ {
704
+ ENetListIterator droppedCommand, startCommand, currentCommand;
705
+
706
+ for (droppedCommand = startCommand = currentCommand = enet_list_begin (& channel -> incomingUnreliableCommands);
707
+ currentCommand != enet_list_end (& channel -> incomingUnreliableCommands);
708
+ currentCommand = enet_list_next (currentCommand))
709
+ {
710
+ ENetIncomingCommand * incomingCommand = (ENetIncomingCommand *) currentCommand;
711
+
712
+ if ((incomingCommand -> command.header.command & ENET_PROTOCOL_COMMAND_MASK) == ENET_PROTOCOL_COMMAND_SEND_UNSEQUENCED)
713
+ continue;
714
+
715
+ if (incomingCommand -> reliableSequenceNumber == channel -> incomingReliableSequenceNumber)
716
+ {
717
+ if (incomingCommand -> fragmentsRemaining <= 0)
718
+ {
719
+ channel -> incomingUnreliableSequenceNumber = incomingCommand -> unreliableSequenceNumber;
720
+ continue;
721
+ }
722
+
723
+ if (startCommand != currentCommand)
724
+ {
725
+ enet_list_move (enet_list_end (& peer -> dispatchedCommands), startCommand, enet_list_previous (currentCommand));
726
+
727
+ if (! peer -> needsDispatch)
728
+ {
729
+ enet_list_insert (enet_list_end (& peer -> host -> dispatchQueue), & peer -> dispatchList);
730
+
731
+ peer -> needsDispatch = 1;
732
+ }
733
+
734
+ droppedCommand = currentCommand;
735
+ }
736
+ else
737
+ if (droppedCommand != currentCommand)
738
+ droppedCommand = enet_list_previous (currentCommand);
739
+ }
740
+ else
741
+ {
742
+ enet_uint16 reliableWindow = incomingCommand -> reliableSequenceNumber / ENET_PEER_RELIABLE_WINDOW_SIZE,
743
+ currentWindow = channel -> incomingReliableSequenceNumber / ENET_PEER_RELIABLE_WINDOW_SIZE;
744
+ if (incomingCommand -> reliableSequenceNumber < channel -> incomingReliableSequenceNumber)
745
+ reliableWindow += ENET_PEER_RELIABLE_WINDOWS;
746
+ if (reliableWindow >= currentWindow && reliableWindow < currentWindow + ENET_PEER_FREE_RELIABLE_WINDOWS - 1)
747
+ break;
748
+
749
+ droppedCommand = enet_list_next (currentCommand);
750
+
751
+ if (startCommand != currentCommand)
752
+ {
753
+ enet_list_move (enet_list_end (& peer -> dispatchedCommands), startCommand, enet_list_previous (currentCommand));
754
+
755
+ if (! peer -> needsDispatch)
756
+ {
757
+ enet_list_insert (enet_list_end (& peer -> host -> dispatchQueue), & peer -> dispatchList);
758
+
759
+ peer -> needsDispatch = 1;
760
+ }
761
+ }
762
+ }
763
+
764
+ startCommand = enet_list_next (currentCommand);
765
+ }
766
+
767
+ if (startCommand != currentCommand)
768
+ {
769
+ enet_list_move (enet_list_end (& peer -> dispatchedCommands), startCommand, enet_list_previous (currentCommand));
770
+
771
+ if (! peer -> needsDispatch)
772
+ {
773
+ enet_list_insert (enet_list_end (& peer -> host -> dispatchQueue), & peer -> dispatchList);
774
+
775
+ peer -> needsDispatch = 1;
776
+ }
777
+
778
+ droppedCommand = currentCommand;
779
+ }
780
+
781
+ enet_peer_remove_incoming_commands (& channel -> incomingUnreliableCommands, enet_list_begin (& channel -> incomingUnreliableCommands), droppedCommand);
782
+ }
783
+
784
+ void
785
+ enet_peer_dispatch_incoming_reliable_commands (ENetPeer * peer, ENetChannel * channel)
786
+ {
787
+ ENetListIterator currentCommand;
788
+
789
+ for (currentCommand = enet_list_begin (& channel -> incomingReliableCommands);
790
+ currentCommand != enet_list_end (& channel -> incomingReliableCommands);
791
+ currentCommand = enet_list_next (currentCommand))
792
+ {
793
+ ENetIncomingCommand * incomingCommand = (ENetIncomingCommand *) currentCommand;
794
+
795
+ if (incomingCommand -> fragmentsRemaining > 0 ||
796
+ incomingCommand -> reliableSequenceNumber != (enet_uint16) (channel -> incomingReliableSequenceNumber + 1))
797
+ break;
798
+
799
+ channel -> incomingReliableSequenceNumber = incomingCommand -> reliableSequenceNumber;
800
+
801
+ if (incomingCommand -> fragmentCount > 0)
802
+ channel -> incomingReliableSequenceNumber += incomingCommand -> fragmentCount - 1;
803
+ }
804
+
805
+ if (currentCommand == enet_list_begin (& channel -> incomingReliableCommands))
806
+ return;
807
+
808
+ channel -> incomingUnreliableSequenceNumber = 0;
809
+
810
+ enet_list_move (enet_list_end (& peer -> dispatchedCommands), enet_list_begin (& channel -> incomingReliableCommands), enet_list_previous (currentCommand));
811
+
812
+ if (! peer -> needsDispatch)
813
+ {
814
+ enet_list_insert (enet_list_end (& peer -> host -> dispatchQueue), & peer -> dispatchList);
815
+
816
+ peer -> needsDispatch = 1;
817
+ }
818
+
819
+ if (! enet_list_empty (& channel -> incomingUnreliableCommands))
820
+ enet_peer_dispatch_incoming_unreliable_commands (peer, channel);
821
+ }
822
+
823
+ ENetIncomingCommand *
824
+ enet_peer_queue_incoming_command (ENetPeer * peer, const ENetProtocol * command, const void * data, size_t dataLength, enet_uint32 flags, enet_uint32 fragmentCount)
825
+ {
826
+ static ENetIncomingCommand dummyCommand;
827
+
828
+ ENetChannel * channel = & peer -> channels [command -> header.channelID];
829
+ enet_uint32 unreliableSequenceNumber = 0, reliableSequenceNumber = 0;
830
+ enet_uint16 reliableWindow, currentWindow;
831
+ ENetIncomingCommand * incomingCommand;
832
+ ENetListIterator currentCommand;
833
+ ENetPacket * packet = NULL;
834
+
835
+ if (peer -> state == ENET_PEER_STATE_DISCONNECT_LATER)
836
+ goto discardCommand;
837
+
838
+ if ((command -> header.command & ENET_PROTOCOL_COMMAND_MASK) != ENET_PROTOCOL_COMMAND_SEND_UNSEQUENCED)
839
+ {
840
+ reliableSequenceNumber = command -> header.reliableSequenceNumber;
841
+ reliableWindow = reliableSequenceNumber / ENET_PEER_RELIABLE_WINDOW_SIZE;
842
+ currentWindow = channel -> incomingReliableSequenceNumber / ENET_PEER_RELIABLE_WINDOW_SIZE;
843
+
844
+ if (reliableSequenceNumber < channel -> incomingReliableSequenceNumber)
845
+ reliableWindow += ENET_PEER_RELIABLE_WINDOWS;
846
+
847
+ if (reliableWindow < currentWindow || reliableWindow >= currentWindow + ENET_PEER_FREE_RELIABLE_WINDOWS - 1)
848
+ goto discardCommand;
849
+ }
850
+
851
+ switch (command -> header.command & ENET_PROTOCOL_COMMAND_MASK)
852
+ {
853
+ case ENET_PROTOCOL_COMMAND_SEND_FRAGMENT:
854
+ case ENET_PROTOCOL_COMMAND_SEND_RELIABLE:
855
+ if (reliableSequenceNumber == channel -> incomingReliableSequenceNumber)
856
+ goto discardCommand;
857
+
858
+ for (currentCommand = enet_list_previous (enet_list_end (& channel -> incomingReliableCommands));
859
+ currentCommand != enet_list_end (& channel -> incomingReliableCommands);
860
+ currentCommand = enet_list_previous (currentCommand))
861
+ {
862
+ incomingCommand = (ENetIncomingCommand *) currentCommand;
863
+
864
+ if (reliableSequenceNumber >= channel -> incomingReliableSequenceNumber)
865
+ {
866
+ if (incomingCommand -> reliableSequenceNumber < channel -> incomingReliableSequenceNumber)
867
+ continue;
868
+ }
869
+ else
870
+ if (incomingCommand -> reliableSequenceNumber >= channel -> incomingReliableSequenceNumber)
871
+ break;
872
+
873
+ if (incomingCommand -> reliableSequenceNumber <= reliableSequenceNumber)
874
+ {
875
+ if (incomingCommand -> reliableSequenceNumber < reliableSequenceNumber)
876
+ break;
877
+
878
+ goto discardCommand;
879
+ }
880
+ }
881
+ break;
882
+
883
+ case ENET_PROTOCOL_COMMAND_SEND_UNRELIABLE:
884
+ case ENET_PROTOCOL_COMMAND_SEND_UNRELIABLE_FRAGMENT:
885
+ unreliableSequenceNumber = ENET_NET_TO_HOST_16 (command -> sendUnreliable.unreliableSequenceNumber);
886
+
887
+ if (reliableSequenceNumber == channel -> incomingReliableSequenceNumber &&
888
+ unreliableSequenceNumber <= channel -> incomingUnreliableSequenceNumber)
889
+ goto discardCommand;
890
+
891
+ for (currentCommand = enet_list_previous (enet_list_end (& channel -> incomingUnreliableCommands));
892
+ currentCommand != enet_list_end (& channel -> incomingUnreliableCommands);
893
+ currentCommand = enet_list_previous (currentCommand))
894
+ {
895
+ incomingCommand = (ENetIncomingCommand *) currentCommand;
896
+
897
+ if ((command -> header.command & ENET_PROTOCOL_COMMAND_MASK) == ENET_PROTOCOL_COMMAND_SEND_UNSEQUENCED)
898
+ continue;
899
+
900
+ if (reliableSequenceNumber >= channel -> incomingReliableSequenceNumber)
901
+ {
902
+ if (incomingCommand -> reliableSequenceNumber < channel -> incomingReliableSequenceNumber)
903
+ continue;
904
+ }
905
+ else
906
+ if (incomingCommand -> reliableSequenceNumber >= channel -> incomingReliableSequenceNumber)
907
+ break;
908
+
909
+ if (incomingCommand -> reliableSequenceNumber < reliableSequenceNumber)
910
+ break;
911
+
912
+ if (incomingCommand -> reliableSequenceNumber > reliableSequenceNumber)
913
+ continue;
914
+
915
+ if (incomingCommand -> unreliableSequenceNumber <= unreliableSequenceNumber)
916
+ {
917
+ if (incomingCommand -> unreliableSequenceNumber < unreliableSequenceNumber)
918
+ break;
919
+
920
+ goto discardCommand;
921
+ }
922
+ }
923
+ break;
924
+
925
+ case ENET_PROTOCOL_COMMAND_SEND_UNSEQUENCED:
926
+ currentCommand = enet_list_end (& channel -> incomingUnreliableCommands);
927
+ break;
928
+
929
+ default:
930
+ goto discardCommand;
931
+ }
932
+
933
+ if (peer -> totalWaitingData >= peer -> host -> maximumWaitingData)
934
+ goto notifyError;
935
+
936
+ packet = enet_packet_create (data, dataLength, flags);
937
+ if (packet == NULL)
938
+ goto notifyError;
939
+
940
+ incomingCommand = (ENetIncomingCommand *) enet_malloc (sizeof (ENetIncomingCommand));
941
+ if (incomingCommand == NULL)
942
+ goto notifyError;
943
+
944
+ incomingCommand -> reliableSequenceNumber = command -> header.reliableSequenceNumber;
945
+ incomingCommand -> unreliableSequenceNumber = unreliableSequenceNumber & 0xFFFF;
946
+ incomingCommand -> command = * command;
947
+ incomingCommand -> fragmentCount = fragmentCount;
948
+ incomingCommand -> fragmentsRemaining = fragmentCount;
949
+ incomingCommand -> packet = packet;
950
+ incomingCommand -> fragments = NULL;
951
+
952
+ if (fragmentCount > 0)
953
+ {
954
+ if (fragmentCount <= ENET_PROTOCOL_MAXIMUM_FRAGMENT_COUNT)
955
+ incomingCommand -> fragments = (enet_uint32 *) enet_malloc ((fragmentCount + 31) / 32 * sizeof (enet_uint32));
956
+ if (incomingCommand -> fragments == NULL)
957
+ {
958
+ enet_free (incomingCommand);
959
+
960
+ goto notifyError;
961
+ }
962
+ memset (incomingCommand -> fragments, 0, (fragmentCount + 31) / 32 * sizeof (enet_uint32));
963
+ }
964
+
965
+ if (packet != NULL)
966
+ {
967
+ ++ packet -> referenceCount;
968
+
969
+ peer -> totalWaitingData += packet -> dataLength;
970
+ }
971
+
972
+ enet_list_insert (enet_list_next (currentCommand), incomingCommand);
973
+
974
+ switch (command -> header.command & ENET_PROTOCOL_COMMAND_MASK)
975
+ {
976
+ case ENET_PROTOCOL_COMMAND_SEND_FRAGMENT:
977
+ case ENET_PROTOCOL_COMMAND_SEND_RELIABLE:
978
+ enet_peer_dispatch_incoming_reliable_commands (peer, channel);
979
+ break;
980
+
981
+ default:
982
+ enet_peer_dispatch_incoming_unreliable_commands (peer, channel);
983
+ break;
984
+ }
985
+
986
+ return incomingCommand;
987
+
988
+ discardCommand:
989
+ if (fragmentCount > 0)
990
+ goto notifyError;
991
+
992
+ if (packet != NULL && packet -> referenceCount == 0)
993
+ enet_packet_destroy (packet);
994
+
995
+ return & dummyCommand;
996
+
997
+ notifyError:
998
+ if (packet != NULL && packet -> referenceCount == 0)
999
+ enet_packet_destroy (packet);
1000
+
1001
+ return NULL;
1002
+ }
1003
+
1004
+ /** @} */