~ubuntu-branches/debian/stretch/assaultcube-data/stretch

« back to all changes in this revision

Viewing changes to source/enet/host.c

  • Committer: Bazaar Package Importer
  • Author(s): Gonéri Le Bouder, Ansgar Burchardt, Gonéri Le Bouder
  • Date: 2010-04-02 23:37:55 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20100402233755-kf74fxwlu634o6vg
Tags: 1.0.4+repack1-1
[ Ansgar Burchardt ]
* debian/control: fix typo in short description

[ Gonéri Le Bouder ]
* Upgrade to 1.0.4
* bump standards-version to 3.8.4
* Add Depends: ${misc:Depends} just to avoid a lintian warning
* Add a debian/source/format file for the same reason

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/** 
 
2
 @file host.c
 
3
 @brief ENet host management functions
 
4
*/
 
5
#define ENET_BUILDING_LIB 1
 
6
#include <string.h>
 
7
#include "enet/enet.h"
 
8
 
 
9
/** @defgroup host ENet host functions
 
10
    @{
 
11
*/
 
12
 
 
13
/** Creates a host for communicating to peers.  
 
14
 
 
15
    @param address   the address at which other peers may connect to this host.  If NULL, then no peers may connect to the host.
 
16
    @param peerCount the maximum number of peers that should be allocated for the host.
 
17
    @param incomingBandwidth downstream bandwidth of the host in bytes/second; if 0, ENet will assume unlimited bandwidth.
 
18
    @param outgoingBandwidth upstream bandwidth of the host in bytes/second; if 0, ENet will assume unlimited bandwidth.
 
19
 
 
20
    @returns the host on success and NULL on failure
 
21
 
 
22
    @remarks ENet will strategically drop packets on specific sides of a connection between hosts
 
23
    to ensure the host's bandwidth is not overwhelmed.  The bandwidth parameters also determine
 
24
    the window size of a connection which limits the amount of reliable packets that may be in transit
 
25
    at any given time.
 
26
*/
 
27
ENetHost *
 
28
enet_host_create (const ENetAddress * address, size_t peerCount, enet_uint32 incomingBandwidth, enet_uint32 outgoingBandwidth)
 
29
{
 
30
    ENetHost * host = (ENetHost *) enet_malloc (sizeof (ENetHost));
 
31
    ENetPeer * currentPeer;
 
32
 
 
33
    if (peerCount > ENET_PROTOCOL_MAXIMUM_PEER_ID)
 
34
      return NULL;
 
35
 
 
36
    host -> peers = (ENetPeer *) enet_malloc (peerCount * sizeof (ENetPeer));
 
37
    memset (host -> peers, 0, peerCount * sizeof (ENetPeer));
 
38
 
 
39
    host -> socket = enet_socket_create (ENET_SOCKET_TYPE_DATAGRAM);
 
40
    if (host -> socket == ENET_SOCKET_NULL || (address != NULL && enet_socket_bind (host -> socket, address) < 0))
 
41
    {
 
42
       if (host -> socket != ENET_SOCKET_NULL)
 
43
         enet_socket_destroy (host -> socket);
 
44
 
 
45
       enet_free (host -> peers);
 
46
       enet_free (host);
 
47
 
 
48
       return NULL;
 
49
    }
 
50
 
 
51
    enet_socket_set_option (host -> socket, ENET_SOCKOPT_NONBLOCK, 1);
 
52
    enet_socket_set_option (host -> socket, ENET_SOCKOPT_BROADCAST, 1);
 
53
    enet_socket_set_option (host -> socket, ENET_SOCKOPT_RCVBUF, ENET_HOST_RECEIVE_BUFFER_SIZE);
 
54
    enet_socket_set_option (host -> socket, ENET_SOCKOPT_SNDBUF, ENET_HOST_SEND_BUFFER_SIZE);
 
55
 
 
56
    if (address != NULL)
 
57
      host -> address = * address;
 
58
 
 
59
    host -> incomingBandwidth = incomingBandwidth;
 
60
    host -> outgoingBandwidth = outgoingBandwidth;
 
61
    host -> bandwidthThrottleEpoch = 0;
 
62
    host -> recalculateBandwidthLimits = 0;
 
63
    host -> mtu = ENET_HOST_DEFAULT_MTU;
 
64
    host -> peerCount = peerCount;
 
65
    host -> lastServicedPeer = host -> peers;
 
66
    host -> commandCount = 0;
 
67
    host -> bufferCount = 0;
 
68
    host -> receivedAddress.host = ENET_HOST_ANY;
 
69
    host -> receivedAddress.port = 0;
 
70
    host -> receivedDataLength = 0;
 
71
     
 
72
    for (currentPeer = host -> peers;
 
73
         currentPeer < & host -> peers [host -> peerCount];
 
74
         ++ currentPeer)
 
75
    {
 
76
       currentPeer -> host = host;
 
77
       currentPeer -> incomingPeerID = currentPeer - host -> peers;
 
78
       currentPeer -> data = NULL;
 
79
 
 
80
       enet_list_clear (& currentPeer -> acknowledgements);
 
81
       enet_list_clear (& currentPeer -> sentReliableCommands);
 
82
       enet_list_clear (& currentPeer -> sentUnreliableCommands);
 
83
       enet_list_clear (& currentPeer -> outgoingReliableCommands);
 
84
       enet_list_clear (& currentPeer -> outgoingUnreliableCommands);
 
85
 
 
86
       enet_peer_reset (currentPeer);
 
87
    }
 
88
 
 
89
    return host;
 
90
}
 
91
 
 
92
/** Destroys the host and all resources associated with it.
 
93
    @param host pointer to the host to destroy
 
94
*/
 
95
void
 
96
enet_host_destroy (ENetHost * host)
 
97
{
 
98
    ENetPeer * currentPeer;
 
99
 
 
100
    enet_socket_destroy (host -> socket);
 
101
 
 
102
    for (currentPeer = host -> peers;
 
103
         currentPeer < & host -> peers [host -> peerCount];
 
104
         ++ currentPeer)
 
105
    {
 
106
       enet_peer_reset (currentPeer);
 
107
    }
 
108
 
 
109
    enet_free (host -> peers);
 
110
    enet_free (host);
 
111
}
 
112
 
 
113
/** Initiates a connection to a foreign host.
 
114
    @param host host seeking the connection
 
115
    @param address destination for the connection
 
116
    @param channelCount number of channels to allocate
 
117
    @returns a peer representing the foreign host on success, NULL on failure
 
118
    @remarks The peer returned will have not completed the connection until enet_host_service()
 
119
    notifies of an ENET_EVENT_TYPE_CONNECT event for the peer.
 
120
*/
 
121
ENetPeer *
 
122
enet_host_connect (ENetHost * host, const ENetAddress * address, size_t channelCount)
 
123
{
 
124
    ENetPeer * currentPeer;
 
125
    ENetChannel * channel;
 
126
    ENetProtocol command;
 
127
 
 
128
    if (channelCount < ENET_PROTOCOL_MINIMUM_CHANNEL_COUNT)
 
129
      channelCount = ENET_PROTOCOL_MINIMUM_CHANNEL_COUNT;
 
130
    else
 
131
    if (channelCount > ENET_PROTOCOL_MAXIMUM_CHANNEL_COUNT)
 
132
      channelCount = ENET_PROTOCOL_MAXIMUM_CHANNEL_COUNT;
 
133
 
 
134
    for (currentPeer = host -> peers;
 
135
         currentPeer < & host -> peers [host -> peerCount];
 
136
         ++ currentPeer)
 
137
    {
 
138
       if (currentPeer -> state == ENET_PEER_STATE_DISCONNECTED)
 
139
         break;
 
140
    }
 
141
 
 
142
    if (currentPeer >= & host -> peers [host -> peerCount])
 
143
      return NULL;
 
144
 
 
145
    currentPeer -> state = ENET_PEER_STATE_CONNECTING;
 
146
    currentPeer -> address = * address;
 
147
    currentPeer -> channels = (ENetChannel *) enet_malloc (channelCount * sizeof (ENetChannel));
 
148
    currentPeer -> channelCount = channelCount;
 
149
    currentPeer -> sessionID = (enet_uint32) enet_rand ();
 
150
 
 
151
    if (host -> outgoingBandwidth == 0)
 
152
      currentPeer -> windowSize = ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE;
 
153
    else
 
154
      currentPeer -> windowSize = (host -> outgoingBandwidth /
 
155
                                    ENET_PEER_WINDOW_SIZE_SCALE) * 
 
156
                                      ENET_PROTOCOL_MINIMUM_WINDOW_SIZE;
 
157
 
 
158
    if (currentPeer -> windowSize < ENET_PROTOCOL_MINIMUM_WINDOW_SIZE)
 
159
      currentPeer -> windowSize = ENET_PROTOCOL_MINIMUM_WINDOW_SIZE;
 
160
    else
 
161
    if (currentPeer -> windowSize > ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE)
 
162
      currentPeer -> windowSize = ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE;
 
163
         
 
164
    for (channel = currentPeer -> channels;
 
165
         channel < & currentPeer -> channels [channelCount];
 
166
         ++ channel)
 
167
    {
 
168
        channel -> outgoingReliableSequenceNumber = 0;
 
169
        channel -> outgoingUnreliableSequenceNumber = 0;
 
170
        channel -> incomingReliableSequenceNumber = 0;
 
171
 
 
172
        enet_list_clear (& channel -> incomingReliableCommands);
 
173
        enet_list_clear (& channel -> incomingUnreliableCommands);
 
174
 
 
175
        channel -> usedReliableWindows = 0;
 
176
        memset (channel -> reliableWindows, 0, sizeof (channel -> reliableWindows));
 
177
    }
 
178
        
 
179
    command.header.command = ENET_PROTOCOL_COMMAND_CONNECT | ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE;
 
180
    command.header.channelID = 0xFF;
 
181
    command.connect.outgoingPeerID = ENET_HOST_TO_NET_16 (currentPeer -> incomingPeerID);
 
182
    command.connect.mtu = ENET_HOST_TO_NET_16 (currentPeer -> mtu);
 
183
    command.connect.windowSize = ENET_HOST_TO_NET_32 (currentPeer -> windowSize);
 
184
    command.connect.channelCount = ENET_HOST_TO_NET_32 (channelCount);
 
185
    command.connect.incomingBandwidth = ENET_HOST_TO_NET_32 (host -> incomingBandwidth);
 
186
    command.connect.outgoingBandwidth = ENET_HOST_TO_NET_32 (host -> outgoingBandwidth);
 
187
    command.connect.packetThrottleInterval = ENET_HOST_TO_NET_32 (currentPeer -> packetThrottleInterval);
 
188
    command.connect.packetThrottleAcceleration = ENET_HOST_TO_NET_32 (currentPeer -> packetThrottleAcceleration);
 
189
    command.connect.packetThrottleDeceleration = ENET_HOST_TO_NET_32 (currentPeer -> packetThrottleDeceleration);
 
190
    command.connect.sessionID = currentPeer -> sessionID;
 
191
    
 
192
    enet_peer_queue_outgoing_command (currentPeer, & command, NULL, 0, 0);
 
193
 
 
194
    return currentPeer;
 
195
}
 
196
 
 
197
/** Queues a packet to be sent to all peers associated with the host.
 
198
    @param host host on which to broadcast the packet
 
199
    @param channelID channel on which to broadcast
 
200
    @param packet packet to broadcast
 
201
*/
 
202
void
 
203
enet_host_broadcast (ENetHost * host, enet_uint8 channelID, ENetPacket * packet)
 
204
{
 
205
    ENetPeer * currentPeer;
 
206
 
 
207
    for (currentPeer = host -> peers;
 
208
         currentPeer < & host -> peers [host -> peerCount];
 
209
         ++ currentPeer)
 
210
    {
 
211
       if (currentPeer -> state != ENET_PEER_STATE_CONNECTED)
 
212
         continue;
 
213
 
 
214
       enet_peer_send (currentPeer, channelID, packet);
 
215
    }
 
216
 
 
217
    if (packet -> referenceCount == 0)
 
218
      enet_packet_destroy (packet);
 
219
}
 
220
 
 
221
/** Adjusts the bandwidth limits of a host.
 
222
    @param host host to adjust
 
223
    @param incomingBandwidth new incoming bandwidth
 
224
    @param outgoingBandwidth new outgoing bandwidth
 
225
    @remarks the incoming and outgoing bandwidth parameters are identical in function to those
 
226
    specified in enet_host_create().
 
227
*/
 
228
void
 
229
enet_host_bandwidth_limit (ENetHost * host, enet_uint32 incomingBandwidth, enet_uint32 outgoingBandwidth)
 
230
{
 
231
    host -> incomingBandwidth = incomingBandwidth;
 
232
    host -> outgoingBandwidth = outgoingBandwidth;
 
233
    host -> recalculateBandwidthLimits = 1;
 
234
}
 
235
 
 
236
void
 
237
enet_host_bandwidth_throttle (ENetHost * host)
 
238
{
 
239
    enet_uint32 timeCurrent = enet_time_get (),
 
240
           elapsedTime = timeCurrent - host -> bandwidthThrottleEpoch,
 
241
           peersTotal = 0,
 
242
           dataTotal = 0,
 
243
           peersRemaining,
 
244
           bandwidth,
 
245
           throttle = 0,
 
246
           bandwidthLimit = 0;
 
247
    int needsAdjustment;
 
248
    ENetPeer * peer;
 
249
    ENetProtocol command;
 
250
 
 
251
    if (elapsedTime < ENET_HOST_BANDWIDTH_THROTTLE_INTERVAL)
 
252
      return;
 
253
 
 
254
    for (peer = host -> peers;
 
255
         peer < & host -> peers [host -> peerCount];
 
256
         ++ peer)
 
257
    {
 
258
        if (peer -> state != ENET_PEER_STATE_CONNECTED && peer -> state != ENET_PEER_STATE_DISCONNECT_LATER)
 
259
          continue;
 
260
 
 
261
        ++ peersTotal;
 
262
        dataTotal += peer -> outgoingDataTotal;
 
263
    }
 
264
 
 
265
    if (peersTotal == 0)
 
266
      return;
 
267
 
 
268
    peersRemaining = peersTotal;
 
269
    needsAdjustment = 1;
 
270
 
 
271
    if (host -> outgoingBandwidth == 0)
 
272
      bandwidth = ~0;
 
273
    else
 
274
      bandwidth = (host -> outgoingBandwidth * elapsedTime) / 1000;
 
275
 
 
276
    while (peersRemaining > 0 && needsAdjustment != 0)
 
277
    {
 
278
        needsAdjustment = 0;
 
279
        
 
280
        if (dataTotal < bandwidth)
 
281
          throttle = ENET_PEER_PACKET_THROTTLE_SCALE;
 
282
        else
 
283
          throttle = (bandwidth * ENET_PEER_PACKET_THROTTLE_SCALE) / dataTotal;
 
284
 
 
285
        for (peer = host -> peers;
 
286
             peer < & host -> peers [host -> peerCount];
 
287
             ++ peer)
 
288
        {
 
289
            enet_uint32 peerBandwidth;
 
290
            
 
291
            if ((peer -> state != ENET_PEER_STATE_CONNECTED && peer -> state != ENET_PEER_STATE_DISCONNECT_LATER) ||
 
292
                peer -> incomingBandwidth == 0 ||
 
293
                peer -> outgoingBandwidthThrottleEpoch == timeCurrent)
 
294
              continue;
 
295
 
 
296
            peerBandwidth = (peer -> incomingBandwidth * elapsedTime) / 1000;
 
297
            if ((throttle * peer -> outgoingDataTotal) / ENET_PEER_PACKET_THROTTLE_SCALE <= peerBandwidth)
 
298
              continue;
 
299
 
 
300
            peer -> packetThrottleLimit = (peerBandwidth * 
 
301
                                            ENET_PEER_PACKET_THROTTLE_SCALE) / peer -> outgoingDataTotal;
 
302
            
 
303
            if (peer -> packetThrottleLimit == 0)
 
304
              peer -> packetThrottleLimit = 1;
 
305
            
 
306
            if (peer -> packetThrottle > peer -> packetThrottleLimit)
 
307
              peer -> packetThrottle = peer -> packetThrottleLimit;
 
308
 
 
309
            peer -> outgoingBandwidthThrottleEpoch = timeCurrent;
 
310
 
 
311
            
 
312
            needsAdjustment = 1;
 
313
            -- peersRemaining;
 
314
            bandwidth -= peerBandwidth;
 
315
            dataTotal -= peerBandwidth;
 
316
        }
 
317
    }
 
318
 
 
319
    if (peersRemaining > 0)
 
320
    for (peer = host -> peers;
 
321
         peer < & host -> peers [host -> peerCount];
 
322
         ++ peer)
 
323
    {
 
324
        if ((peer -> state != ENET_PEER_STATE_CONNECTED && peer -> state != ENET_PEER_STATE_DISCONNECT_LATER) ||
 
325
            peer -> outgoingBandwidthThrottleEpoch == timeCurrent)
 
326
          continue;
 
327
 
 
328
        peer -> packetThrottleLimit = throttle;
 
329
 
 
330
        if (peer -> packetThrottle > peer -> packetThrottleLimit)
 
331
          peer -> packetThrottle = peer -> packetThrottleLimit;
 
332
    }
 
333
    
 
334
    if (host -> recalculateBandwidthLimits)
 
335
    {
 
336
       host -> recalculateBandwidthLimits = 0;
 
337
 
 
338
       peersRemaining = peersTotal;
 
339
       bandwidth = host -> incomingBandwidth;
 
340
       needsAdjustment = 1;
 
341
 
 
342
       if (bandwidth == 0)
 
343
         bandwidthLimit = 0;
 
344
       else
 
345
       while (peersRemaining > 0 && needsAdjustment != 0)
 
346
       {
 
347
           needsAdjustment = 0;
 
348
           bandwidthLimit = bandwidth / peersRemaining;
 
349
 
 
350
           for (peer = host -> peers;
 
351
                peer < & host -> peers [host -> peerCount];
 
352
                ++ peer)
 
353
           {
 
354
               if ((peer -> state != ENET_PEER_STATE_CONNECTED && peer -> state != ENET_PEER_STATE_DISCONNECT_LATER) ||
 
355
                   peer -> incomingBandwidthThrottleEpoch == timeCurrent)
 
356
                 continue;
 
357
 
 
358
               if (peer -> outgoingBandwidth > 0 &&
 
359
                   peer -> outgoingBandwidth >= bandwidthLimit)
 
360
                 continue;
 
361
 
 
362
               peer -> incomingBandwidthThrottleEpoch = timeCurrent;
 
363
 
 
364
               needsAdjustment = 1;
 
365
               -- peersRemaining;
 
366
               bandwidth -= peer -> outgoingBandwidth;
 
367
           }
 
368
       }
 
369
 
 
370
       for (peer = host -> peers;
 
371
            peer < & host -> peers [host -> peerCount];
 
372
            ++ peer)
 
373
       {
 
374
           if (peer -> state != ENET_PEER_STATE_CONNECTED && peer -> state != ENET_PEER_STATE_DISCONNECT_LATER)
 
375
             continue;
 
376
 
 
377
           command.header.command = ENET_PROTOCOL_COMMAND_BANDWIDTH_LIMIT | ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE;
 
378
           command.header.channelID = 0xFF;
 
379
           command.bandwidthLimit.outgoingBandwidth = ENET_HOST_TO_NET_32 (host -> outgoingBandwidth);
 
380
 
 
381
           if (peer -> incomingBandwidthThrottleEpoch == timeCurrent)
 
382
             command.bandwidthLimit.incomingBandwidth = ENET_HOST_TO_NET_32 (peer -> outgoingBandwidth);
 
383
           else
 
384
             command.bandwidthLimit.incomingBandwidth = ENET_HOST_TO_NET_32 (bandwidthLimit);
 
385
 
 
386
           enet_peer_queue_outgoing_command (peer, & command, NULL, 0, 0);
 
387
       } 
 
388
    }
 
389
 
 
390
    host -> bandwidthThrottleEpoch = timeCurrent;
 
391
 
 
392
    for (peer = host -> peers;
 
393
         peer < & host -> peers [host -> peerCount];
 
394
         ++ peer)
 
395
    {
 
396
        peer -> incomingDataTotal = 0;
 
397
        peer -> outgoingDataTotal = 0;
 
398
    }
 
399
}
 
400
    
 
401
/** @} */