renet 0.1.14 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/README +6 -16
- data/ext/renet/callbacks.c +53 -0
- data/ext/renet/compress.c +654 -0
- data/ext/renet/enet/callbacks.h +27 -0
- data/ext/renet/enet/enet.h +592 -0
- data/ext/renet/enet/list.h +43 -0
- data/ext/renet/enet/protocol.h +198 -0
- data/ext/renet/enet/time.h +18 -0
- data/ext/renet/enet/types.h +13 -0
- data/ext/renet/enet/unix.h +47 -0
- data/ext/renet/enet/utility.h +12 -0
- data/ext/renet/enet/win32.h +57 -0
- data/ext/renet/extconf.rb +5 -16
- data/ext/renet/host.c +492 -0
- data/ext/renet/list.c +75 -0
- data/ext/renet/packet.c +165 -0
- data/ext/renet/peer.c +1004 -0
- data/ext/renet/protocol.c +1913 -0
- data/ext/renet/renet.c +1 -0
- data/ext/renet/renet_connection.c +383 -208
- data/ext/renet/renet_connection.h +3 -3
- data/ext/renet/renet_server.c +263 -159
- data/ext/renet/renet_server.h +5 -5
- data/ext/renet/unix.c +557 -0
- data/ext/renet/win32.c +478 -0
- data/lib/renet.rb +1 -16
- metadata +33 -16
@@ -0,0 +1,43 @@
|
|
1
|
+
/**
|
2
|
+
@file list.h
|
3
|
+
@brief ENet list management
|
4
|
+
*/
|
5
|
+
#ifndef __ENET_LIST_H__
|
6
|
+
#define __ENET_LIST_H__
|
7
|
+
|
8
|
+
#include <stdlib.h>
|
9
|
+
|
10
|
+
typedef struct _ENetListNode
|
11
|
+
{
|
12
|
+
struct _ENetListNode * next;
|
13
|
+
struct _ENetListNode * previous;
|
14
|
+
} ENetListNode;
|
15
|
+
|
16
|
+
typedef ENetListNode * ENetListIterator;
|
17
|
+
|
18
|
+
typedef struct _ENetList
|
19
|
+
{
|
20
|
+
ENetListNode sentinel;
|
21
|
+
} ENetList;
|
22
|
+
|
23
|
+
extern void enet_list_clear (ENetList *);
|
24
|
+
|
25
|
+
extern ENetListIterator enet_list_insert (ENetListIterator, void *);
|
26
|
+
extern void * enet_list_remove (ENetListIterator);
|
27
|
+
extern ENetListIterator enet_list_move (ENetListIterator, void *, void *);
|
28
|
+
|
29
|
+
extern size_t enet_list_size (ENetList *);
|
30
|
+
|
31
|
+
#define enet_list_begin(list) ((list) -> sentinel.next)
|
32
|
+
#define enet_list_end(list) (& (list) -> sentinel)
|
33
|
+
|
34
|
+
#define enet_list_empty(list) (enet_list_begin (list) == enet_list_end (list))
|
35
|
+
|
36
|
+
#define enet_list_next(iterator) ((iterator) -> next)
|
37
|
+
#define enet_list_previous(iterator) ((iterator) -> previous)
|
38
|
+
|
39
|
+
#define enet_list_front(list) ((void *) (list) -> sentinel.next)
|
40
|
+
#define enet_list_back(list) ((void *) (list) -> sentinel.previous)
|
41
|
+
|
42
|
+
#endif /* __ENET_LIST_H__ */
|
43
|
+
|
@@ -0,0 +1,198 @@
|
|
1
|
+
/**
|
2
|
+
@file protocol.h
|
3
|
+
@brief ENet protocol
|
4
|
+
*/
|
5
|
+
#ifndef __ENET_PROTOCOL_H__
|
6
|
+
#define __ENET_PROTOCOL_H__
|
7
|
+
|
8
|
+
#include "enet/types.h"
|
9
|
+
|
10
|
+
enum
|
11
|
+
{
|
12
|
+
ENET_PROTOCOL_MINIMUM_MTU = 576,
|
13
|
+
ENET_PROTOCOL_MAXIMUM_MTU = 4096,
|
14
|
+
ENET_PROTOCOL_MAXIMUM_PACKET_COMMANDS = 32,
|
15
|
+
ENET_PROTOCOL_MINIMUM_WINDOW_SIZE = 4096,
|
16
|
+
ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE = 65536,
|
17
|
+
ENET_PROTOCOL_MINIMUM_CHANNEL_COUNT = 1,
|
18
|
+
ENET_PROTOCOL_MAXIMUM_CHANNEL_COUNT = 255,
|
19
|
+
ENET_PROTOCOL_MAXIMUM_PEER_ID = 0xFFF,
|
20
|
+
ENET_PROTOCOL_MAXIMUM_FRAGMENT_COUNT = 1024 * 1024
|
21
|
+
};
|
22
|
+
|
23
|
+
typedef enum _ENetProtocolCommand
|
24
|
+
{
|
25
|
+
ENET_PROTOCOL_COMMAND_NONE = 0,
|
26
|
+
ENET_PROTOCOL_COMMAND_ACKNOWLEDGE = 1,
|
27
|
+
ENET_PROTOCOL_COMMAND_CONNECT = 2,
|
28
|
+
ENET_PROTOCOL_COMMAND_VERIFY_CONNECT = 3,
|
29
|
+
ENET_PROTOCOL_COMMAND_DISCONNECT = 4,
|
30
|
+
ENET_PROTOCOL_COMMAND_PING = 5,
|
31
|
+
ENET_PROTOCOL_COMMAND_SEND_RELIABLE = 6,
|
32
|
+
ENET_PROTOCOL_COMMAND_SEND_UNRELIABLE = 7,
|
33
|
+
ENET_PROTOCOL_COMMAND_SEND_FRAGMENT = 8,
|
34
|
+
ENET_PROTOCOL_COMMAND_SEND_UNSEQUENCED = 9,
|
35
|
+
ENET_PROTOCOL_COMMAND_BANDWIDTH_LIMIT = 10,
|
36
|
+
ENET_PROTOCOL_COMMAND_THROTTLE_CONFIGURE = 11,
|
37
|
+
ENET_PROTOCOL_COMMAND_SEND_UNRELIABLE_FRAGMENT = 12,
|
38
|
+
ENET_PROTOCOL_COMMAND_COUNT = 13,
|
39
|
+
|
40
|
+
ENET_PROTOCOL_COMMAND_MASK = 0x0F
|
41
|
+
} ENetProtocolCommand;
|
42
|
+
|
43
|
+
typedef enum _ENetProtocolFlag
|
44
|
+
{
|
45
|
+
ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE = (1 << 7),
|
46
|
+
ENET_PROTOCOL_COMMAND_FLAG_UNSEQUENCED = (1 << 6),
|
47
|
+
|
48
|
+
ENET_PROTOCOL_HEADER_FLAG_COMPRESSED = (1 << 14),
|
49
|
+
ENET_PROTOCOL_HEADER_FLAG_SENT_TIME = (1 << 15),
|
50
|
+
ENET_PROTOCOL_HEADER_FLAG_MASK = ENET_PROTOCOL_HEADER_FLAG_COMPRESSED | ENET_PROTOCOL_HEADER_FLAG_SENT_TIME,
|
51
|
+
|
52
|
+
ENET_PROTOCOL_HEADER_SESSION_MASK = (3 << 12),
|
53
|
+
ENET_PROTOCOL_HEADER_SESSION_SHIFT = 12
|
54
|
+
} ENetProtocolFlag;
|
55
|
+
|
56
|
+
#ifdef _MSC_VER
|
57
|
+
#pragma pack(push, 1)
|
58
|
+
#define ENET_PACKED
|
59
|
+
#elif defined(__GNUC__) || defined(__clang__)
|
60
|
+
#define ENET_PACKED __attribute__ ((packed))
|
61
|
+
#else
|
62
|
+
#define ENET_PACKED
|
63
|
+
#endif
|
64
|
+
|
65
|
+
typedef struct _ENetProtocolHeader
|
66
|
+
{
|
67
|
+
enet_uint16 peerID;
|
68
|
+
enet_uint16 sentTime;
|
69
|
+
} ENET_PACKED ENetProtocolHeader;
|
70
|
+
|
71
|
+
typedef struct _ENetProtocolCommandHeader
|
72
|
+
{
|
73
|
+
enet_uint8 command;
|
74
|
+
enet_uint8 channelID;
|
75
|
+
enet_uint16 reliableSequenceNumber;
|
76
|
+
} ENET_PACKED ENetProtocolCommandHeader;
|
77
|
+
|
78
|
+
typedef struct _ENetProtocolAcknowledge
|
79
|
+
{
|
80
|
+
ENetProtocolCommandHeader header;
|
81
|
+
enet_uint16 receivedReliableSequenceNumber;
|
82
|
+
enet_uint16 receivedSentTime;
|
83
|
+
} ENET_PACKED ENetProtocolAcknowledge;
|
84
|
+
|
85
|
+
typedef struct _ENetProtocolConnect
|
86
|
+
{
|
87
|
+
ENetProtocolCommandHeader header;
|
88
|
+
enet_uint16 outgoingPeerID;
|
89
|
+
enet_uint8 incomingSessionID;
|
90
|
+
enet_uint8 outgoingSessionID;
|
91
|
+
enet_uint32 mtu;
|
92
|
+
enet_uint32 windowSize;
|
93
|
+
enet_uint32 channelCount;
|
94
|
+
enet_uint32 incomingBandwidth;
|
95
|
+
enet_uint32 outgoingBandwidth;
|
96
|
+
enet_uint32 packetThrottleInterval;
|
97
|
+
enet_uint32 packetThrottleAcceleration;
|
98
|
+
enet_uint32 packetThrottleDeceleration;
|
99
|
+
enet_uint32 connectID;
|
100
|
+
enet_uint32 data;
|
101
|
+
} ENET_PACKED ENetProtocolConnect;
|
102
|
+
|
103
|
+
typedef struct _ENetProtocolVerifyConnect
|
104
|
+
{
|
105
|
+
ENetProtocolCommandHeader header;
|
106
|
+
enet_uint16 outgoingPeerID;
|
107
|
+
enet_uint8 incomingSessionID;
|
108
|
+
enet_uint8 outgoingSessionID;
|
109
|
+
enet_uint32 mtu;
|
110
|
+
enet_uint32 windowSize;
|
111
|
+
enet_uint32 channelCount;
|
112
|
+
enet_uint32 incomingBandwidth;
|
113
|
+
enet_uint32 outgoingBandwidth;
|
114
|
+
enet_uint32 packetThrottleInterval;
|
115
|
+
enet_uint32 packetThrottleAcceleration;
|
116
|
+
enet_uint32 packetThrottleDeceleration;
|
117
|
+
enet_uint32 connectID;
|
118
|
+
} ENET_PACKED ENetProtocolVerifyConnect;
|
119
|
+
|
120
|
+
typedef struct _ENetProtocolBandwidthLimit
|
121
|
+
{
|
122
|
+
ENetProtocolCommandHeader header;
|
123
|
+
enet_uint32 incomingBandwidth;
|
124
|
+
enet_uint32 outgoingBandwidth;
|
125
|
+
} ENET_PACKED ENetProtocolBandwidthLimit;
|
126
|
+
|
127
|
+
typedef struct _ENetProtocolThrottleConfigure
|
128
|
+
{
|
129
|
+
ENetProtocolCommandHeader header;
|
130
|
+
enet_uint32 packetThrottleInterval;
|
131
|
+
enet_uint32 packetThrottleAcceleration;
|
132
|
+
enet_uint32 packetThrottleDeceleration;
|
133
|
+
} ENET_PACKED ENetProtocolThrottleConfigure;
|
134
|
+
|
135
|
+
typedef struct _ENetProtocolDisconnect
|
136
|
+
{
|
137
|
+
ENetProtocolCommandHeader header;
|
138
|
+
enet_uint32 data;
|
139
|
+
} ENET_PACKED ENetProtocolDisconnect;
|
140
|
+
|
141
|
+
typedef struct _ENetProtocolPing
|
142
|
+
{
|
143
|
+
ENetProtocolCommandHeader header;
|
144
|
+
} ENET_PACKED ENetProtocolPing;
|
145
|
+
|
146
|
+
typedef struct _ENetProtocolSendReliable
|
147
|
+
{
|
148
|
+
ENetProtocolCommandHeader header;
|
149
|
+
enet_uint16 dataLength;
|
150
|
+
} ENET_PACKED ENetProtocolSendReliable;
|
151
|
+
|
152
|
+
typedef struct _ENetProtocolSendUnreliable
|
153
|
+
{
|
154
|
+
ENetProtocolCommandHeader header;
|
155
|
+
enet_uint16 unreliableSequenceNumber;
|
156
|
+
enet_uint16 dataLength;
|
157
|
+
} ENET_PACKED ENetProtocolSendUnreliable;
|
158
|
+
|
159
|
+
typedef struct _ENetProtocolSendUnsequenced
|
160
|
+
{
|
161
|
+
ENetProtocolCommandHeader header;
|
162
|
+
enet_uint16 unsequencedGroup;
|
163
|
+
enet_uint16 dataLength;
|
164
|
+
} ENET_PACKED ENetProtocolSendUnsequenced;
|
165
|
+
|
166
|
+
typedef struct _ENetProtocolSendFragment
|
167
|
+
{
|
168
|
+
ENetProtocolCommandHeader header;
|
169
|
+
enet_uint16 startSequenceNumber;
|
170
|
+
enet_uint16 dataLength;
|
171
|
+
enet_uint32 fragmentCount;
|
172
|
+
enet_uint32 fragmentNumber;
|
173
|
+
enet_uint32 totalLength;
|
174
|
+
enet_uint32 fragmentOffset;
|
175
|
+
} ENET_PACKED ENetProtocolSendFragment;
|
176
|
+
|
177
|
+
typedef union _ENetProtocol
|
178
|
+
{
|
179
|
+
ENetProtocolCommandHeader header;
|
180
|
+
ENetProtocolAcknowledge acknowledge;
|
181
|
+
ENetProtocolConnect connect;
|
182
|
+
ENetProtocolVerifyConnect verifyConnect;
|
183
|
+
ENetProtocolDisconnect disconnect;
|
184
|
+
ENetProtocolPing ping;
|
185
|
+
ENetProtocolSendReliable sendReliable;
|
186
|
+
ENetProtocolSendUnreliable sendUnreliable;
|
187
|
+
ENetProtocolSendUnsequenced sendUnsequenced;
|
188
|
+
ENetProtocolSendFragment sendFragment;
|
189
|
+
ENetProtocolBandwidthLimit bandwidthLimit;
|
190
|
+
ENetProtocolThrottleConfigure throttleConfigure;
|
191
|
+
} ENET_PACKED ENetProtocol;
|
192
|
+
|
193
|
+
#ifdef _MSC_VER
|
194
|
+
#pragma pack(pop)
|
195
|
+
#endif
|
196
|
+
|
197
|
+
#endif /* __ENET_PROTOCOL_H__ */
|
198
|
+
|
@@ -0,0 +1,18 @@
|
|
1
|
+
/**
|
2
|
+
@file time.h
|
3
|
+
@brief ENet time constants and macros
|
4
|
+
*/
|
5
|
+
#ifndef __ENET_TIME_H__
|
6
|
+
#define __ENET_TIME_H__
|
7
|
+
|
8
|
+
#define ENET_TIME_OVERFLOW 86400000
|
9
|
+
|
10
|
+
#define ENET_TIME_LESS(a, b) ((a) - (b) >= ENET_TIME_OVERFLOW)
|
11
|
+
#define ENET_TIME_GREATER(a, b) ((b) - (a) >= ENET_TIME_OVERFLOW)
|
12
|
+
#define ENET_TIME_LESS_EQUAL(a, b) (! ENET_TIME_GREATER (a, b))
|
13
|
+
#define ENET_TIME_GREATER_EQUAL(a, b) (! ENET_TIME_LESS (a, b))
|
14
|
+
|
15
|
+
#define ENET_TIME_DIFFERENCE(a, b) ((a) - (b) >= ENET_TIME_OVERFLOW ? (b) - (a) : (a) - (b))
|
16
|
+
|
17
|
+
#endif /* __ENET_TIME_H__ */
|
18
|
+
|
@@ -0,0 +1,13 @@
|
|
1
|
+
/**
|
2
|
+
@file types.h
|
3
|
+
@brief type definitions for ENet
|
4
|
+
*/
|
5
|
+
#ifndef __ENET_TYPES_H__
|
6
|
+
#define __ENET_TYPES_H__
|
7
|
+
|
8
|
+
typedef unsigned char enet_uint8; /**< unsigned 8-bit type */
|
9
|
+
typedef unsigned short enet_uint16; /**< unsigned 16-bit type */
|
10
|
+
typedef unsigned int enet_uint32; /**< unsigned 32-bit type */
|
11
|
+
|
12
|
+
#endif /* __ENET_TYPES_H__ */
|
13
|
+
|
@@ -0,0 +1,47 @@
|
|
1
|
+
/**
|
2
|
+
@file unix.h
|
3
|
+
@brief ENet Unix header
|
4
|
+
*/
|
5
|
+
#ifndef __ENET_UNIX_H__
|
6
|
+
#define __ENET_UNIX_H__
|
7
|
+
|
8
|
+
#include <stdlib.h>
|
9
|
+
#include <sys/time.h>
|
10
|
+
#include <sys/types.h>
|
11
|
+
#include <sys/socket.h>
|
12
|
+
#include <netinet/in.h>
|
13
|
+
#include <unistd.h>
|
14
|
+
|
15
|
+
#ifdef MSG_MAXIOVLEN
|
16
|
+
#define ENET_BUFFER_MAXIMUM MSG_MAXIOVLEN
|
17
|
+
#endif
|
18
|
+
|
19
|
+
typedef int ENetSocket;
|
20
|
+
|
21
|
+
#define ENET_SOCKET_NULL -1
|
22
|
+
|
23
|
+
#define ENET_HOST_TO_NET_16(value) (htons (value)) /**< macro that converts host to net byte-order of a 16-bit value */
|
24
|
+
#define ENET_HOST_TO_NET_32(value) (htonl (value)) /**< macro that converts host to net byte-order of a 32-bit value */
|
25
|
+
|
26
|
+
#define ENET_NET_TO_HOST_16(value) (ntohs (value)) /**< macro that converts net to host byte-order of a 16-bit value */
|
27
|
+
#define ENET_NET_TO_HOST_32(value) (ntohl (value)) /**< macro that converts net to host byte-order of a 32-bit value */
|
28
|
+
|
29
|
+
typedef struct
|
30
|
+
{
|
31
|
+
void * data;
|
32
|
+
size_t dataLength;
|
33
|
+
} ENetBuffer;
|
34
|
+
|
35
|
+
#define ENET_CALLBACK
|
36
|
+
|
37
|
+
#define ENET_API extern
|
38
|
+
|
39
|
+
typedef fd_set ENetSocketSet;
|
40
|
+
|
41
|
+
#define ENET_SOCKETSET_EMPTY(sockset) FD_ZERO (& (sockset))
|
42
|
+
#define ENET_SOCKETSET_ADD(sockset, socket) FD_SET (socket, & (sockset))
|
43
|
+
#define ENET_SOCKETSET_REMOVE(sockset, socket) FD_CLR (socket, & (sockset))
|
44
|
+
#define ENET_SOCKETSET_CHECK(sockset, socket) FD_ISSET (socket, & (sockset))
|
45
|
+
|
46
|
+
#endif /* __ENET_UNIX_H__ */
|
47
|
+
|
@@ -0,0 +1,57 @@
|
|
1
|
+
/**
|
2
|
+
@file win32.h
|
3
|
+
@brief ENet Win32 header
|
4
|
+
*/
|
5
|
+
#ifndef __ENET_WIN32_H__
|
6
|
+
#define __ENET_WIN32_H__
|
7
|
+
|
8
|
+
#ifdef _MSC_VER
|
9
|
+
#ifdef ENET_BUILDING_LIB
|
10
|
+
#pragma warning (disable: 4267) // size_t to int conversion
|
11
|
+
#pragma warning (disable: 4244) // 64bit to 32bit int
|
12
|
+
#pragma warning (disable: 4018) // signed/unsigned mismatch
|
13
|
+
#pragma warning (disable: 4146) // unary minus operator applied to unsigned type
|
14
|
+
#endif
|
15
|
+
#endif
|
16
|
+
|
17
|
+
#include <stdlib.h>
|
18
|
+
#include <winsock2.h>
|
19
|
+
|
20
|
+
typedef SOCKET ENetSocket;
|
21
|
+
|
22
|
+
#define ENET_SOCKET_NULL INVALID_SOCKET
|
23
|
+
|
24
|
+
#define ENET_HOST_TO_NET_16(value) (htons (value))
|
25
|
+
#define ENET_HOST_TO_NET_32(value) (htonl (value))
|
26
|
+
|
27
|
+
#define ENET_NET_TO_HOST_16(value) (ntohs (value))
|
28
|
+
#define ENET_NET_TO_HOST_32(value) (ntohl (value))
|
29
|
+
|
30
|
+
typedef struct
|
31
|
+
{
|
32
|
+
size_t dataLength;
|
33
|
+
void * data;
|
34
|
+
} ENetBuffer;
|
35
|
+
|
36
|
+
#define ENET_CALLBACK __cdecl
|
37
|
+
|
38
|
+
#ifdef ENET_DLL
|
39
|
+
#ifdef ENET_BUILDING_LIB
|
40
|
+
#define ENET_API __declspec( dllexport )
|
41
|
+
#else
|
42
|
+
#define ENET_API __declspec( dllimport )
|
43
|
+
#endif /* ENET_BUILDING_LIB */
|
44
|
+
#else /* !ENET_DLL */
|
45
|
+
#define ENET_API extern
|
46
|
+
#endif /* ENET_DLL */
|
47
|
+
|
48
|
+
typedef fd_set ENetSocketSet;
|
49
|
+
|
50
|
+
#define ENET_SOCKETSET_EMPTY(sockset) FD_ZERO (& (sockset))
|
51
|
+
#define ENET_SOCKETSET_ADD(sockset, socket) FD_SET (socket, & (sockset))
|
52
|
+
#define ENET_SOCKETSET_REMOVE(sockset, socket) FD_CLR (socket, & (sockset))
|
53
|
+
#define ENET_SOCKETSET_CHECK(sockset, socket) FD_ISSET (socket, & (sockset))
|
54
|
+
|
55
|
+
#endif /* __ENET_WIN32_H__ */
|
56
|
+
|
57
|
+
|
data/ext/renet/extconf.rb
CHANGED
@@ -1,18 +1,7 @@
|
|
1
1
|
require 'mkmf'
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
puts "ENet library required to build the gem, please install it"
|
2
|
+
# $CFLAGS += ' -Wall -Werror -Wno-declaration-after-statement'
|
3
|
+
case RUBY_PLATFORM
|
4
|
+
when /(mingw|mswin|windows)/i
|
5
|
+
$LDFLAGS += ' -lwinmm '
|
7
6
|
end
|
8
|
-
|
9
|
-
dir_config('enet', '/usr/include/enet', 'usr/lib')
|
10
|
-
create_makefile(extension_name)
|
11
|
-
|
12
|
-
system("make")
|
13
|
-
|
14
|
-
#if `uname`.chomp == 'Darwin'
|
15
|
-
# `ln -s renet.bundle ../../lib/renet.bundle`
|
16
|
-
#else
|
17
|
-
# `ln -s renet.so ../../lib/renet.so`
|
18
|
-
#end
|
7
|
+
create_makefile('renet/renet')
|
data/ext/renet/host.c
ADDED
@@ -0,0 +1,492 @@
|
|
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 channelLimit the maximum number of channels allowed; if 0, then this is equivalent to ENET_PROTOCOL_MAXIMUM_CHANNEL_COUNT
|
18
|
+
@param incomingBandwidth downstream bandwidth of the host in bytes/second; if 0, ENet will assume unlimited bandwidth.
|
19
|
+
@param outgoingBandwidth upstream bandwidth of the host in bytes/second; if 0, ENet will assume unlimited bandwidth.
|
20
|
+
|
21
|
+
@returns the host on success and NULL on failure
|
22
|
+
|
23
|
+
@remarks ENet will strategically drop packets on specific sides of a connection between hosts
|
24
|
+
to ensure the host's bandwidth is not overwhelmed. The bandwidth parameters also determine
|
25
|
+
the window size of a connection which limits the amount of reliable packets that may be in transit
|
26
|
+
at any given time.
|
27
|
+
*/
|
28
|
+
ENetHost *
|
29
|
+
enet_host_create (const ENetAddress * address, size_t peerCount, size_t channelLimit, enet_uint32 incomingBandwidth, enet_uint32 outgoingBandwidth)
|
30
|
+
{
|
31
|
+
ENetHost * host;
|
32
|
+
ENetPeer * currentPeer;
|
33
|
+
|
34
|
+
if (peerCount > ENET_PROTOCOL_MAXIMUM_PEER_ID)
|
35
|
+
return NULL;
|
36
|
+
|
37
|
+
host = (ENetHost *) enet_malloc (sizeof (ENetHost));
|
38
|
+
if (host == NULL)
|
39
|
+
return NULL;
|
40
|
+
memset (host, 0, sizeof (ENetHost));
|
41
|
+
|
42
|
+
host -> peers = (ENetPeer *) enet_malloc (peerCount * sizeof (ENetPeer));
|
43
|
+
if (host -> peers == NULL)
|
44
|
+
{
|
45
|
+
enet_free (host);
|
46
|
+
|
47
|
+
return NULL;
|
48
|
+
}
|
49
|
+
memset (host -> peers, 0, peerCount * sizeof (ENetPeer));
|
50
|
+
|
51
|
+
host -> socket = enet_socket_create (ENET_SOCKET_TYPE_DATAGRAM);
|
52
|
+
if (host -> socket == ENET_SOCKET_NULL || (address != NULL && enet_socket_bind (host -> socket, address) < 0))
|
53
|
+
{
|
54
|
+
if (host -> socket != ENET_SOCKET_NULL)
|
55
|
+
enet_socket_destroy (host -> socket);
|
56
|
+
|
57
|
+
enet_free (host -> peers);
|
58
|
+
enet_free (host);
|
59
|
+
|
60
|
+
return NULL;
|
61
|
+
}
|
62
|
+
|
63
|
+
enet_socket_set_option (host -> socket, ENET_SOCKOPT_NONBLOCK, 1);
|
64
|
+
enet_socket_set_option (host -> socket, ENET_SOCKOPT_BROADCAST, 1);
|
65
|
+
enet_socket_set_option (host -> socket, ENET_SOCKOPT_RCVBUF, ENET_HOST_RECEIVE_BUFFER_SIZE);
|
66
|
+
enet_socket_set_option (host -> socket, ENET_SOCKOPT_SNDBUF, ENET_HOST_SEND_BUFFER_SIZE);
|
67
|
+
|
68
|
+
if (address != NULL && enet_socket_get_address (host -> socket, & host -> address) < 0)
|
69
|
+
host -> address = * address;
|
70
|
+
|
71
|
+
if (! channelLimit || channelLimit > ENET_PROTOCOL_MAXIMUM_CHANNEL_COUNT)
|
72
|
+
channelLimit = ENET_PROTOCOL_MAXIMUM_CHANNEL_COUNT;
|
73
|
+
else
|
74
|
+
if (channelLimit < ENET_PROTOCOL_MINIMUM_CHANNEL_COUNT)
|
75
|
+
channelLimit = ENET_PROTOCOL_MINIMUM_CHANNEL_COUNT;
|
76
|
+
|
77
|
+
host -> randomSeed = (enet_uint32) (size_t) host;
|
78
|
+
host -> randomSeed += enet_host_random_seed ();
|
79
|
+
host -> randomSeed = (host -> randomSeed << 16) | (host -> randomSeed >> 16);
|
80
|
+
host -> channelLimit = channelLimit;
|
81
|
+
host -> incomingBandwidth = incomingBandwidth;
|
82
|
+
host -> outgoingBandwidth = outgoingBandwidth;
|
83
|
+
host -> bandwidthThrottleEpoch = 0;
|
84
|
+
host -> recalculateBandwidthLimits = 0;
|
85
|
+
host -> mtu = ENET_HOST_DEFAULT_MTU;
|
86
|
+
host -> peerCount = peerCount;
|
87
|
+
host -> commandCount = 0;
|
88
|
+
host -> bufferCount = 0;
|
89
|
+
host -> checksum = NULL;
|
90
|
+
host -> receivedAddress.host = ENET_HOST_ANY;
|
91
|
+
host -> receivedAddress.port = 0;
|
92
|
+
host -> receivedData = NULL;
|
93
|
+
host -> receivedDataLength = 0;
|
94
|
+
|
95
|
+
host -> totalSentData = 0;
|
96
|
+
host -> totalSentPackets = 0;
|
97
|
+
host -> totalReceivedData = 0;
|
98
|
+
host -> totalReceivedPackets = 0;
|
99
|
+
|
100
|
+
host -> connectedPeers = 0;
|
101
|
+
host -> bandwidthLimitedPeers = 0;
|
102
|
+
host -> duplicatePeers = ENET_PROTOCOL_MAXIMUM_PEER_ID;
|
103
|
+
host -> maximumPacketSize = ENET_HOST_DEFAULT_MAXIMUM_PACKET_SIZE;
|
104
|
+
host -> maximumWaitingData = ENET_HOST_DEFAULT_MAXIMUM_WAITING_DATA;
|
105
|
+
|
106
|
+
host -> compressor.context = NULL;
|
107
|
+
host -> compressor.compress = NULL;
|
108
|
+
host -> compressor.decompress = NULL;
|
109
|
+
host -> compressor.destroy = NULL;
|
110
|
+
|
111
|
+
host -> intercept = NULL;
|
112
|
+
|
113
|
+
enet_list_clear (& host -> dispatchQueue);
|
114
|
+
|
115
|
+
for (currentPeer = host -> peers;
|
116
|
+
currentPeer < & host -> peers [host -> peerCount];
|
117
|
+
++ currentPeer)
|
118
|
+
{
|
119
|
+
currentPeer -> host = host;
|
120
|
+
currentPeer -> incomingPeerID = currentPeer - host -> peers;
|
121
|
+
currentPeer -> outgoingSessionID = currentPeer -> incomingSessionID = 0xFF;
|
122
|
+
currentPeer -> data = NULL;
|
123
|
+
|
124
|
+
enet_list_clear (& currentPeer -> acknowledgements);
|
125
|
+
enet_list_clear (& currentPeer -> sentReliableCommands);
|
126
|
+
enet_list_clear (& currentPeer -> sentUnreliableCommands);
|
127
|
+
enet_list_clear (& currentPeer -> outgoingReliableCommands);
|
128
|
+
enet_list_clear (& currentPeer -> outgoingUnreliableCommands);
|
129
|
+
enet_list_clear (& currentPeer -> dispatchedCommands);
|
130
|
+
|
131
|
+
enet_peer_reset (currentPeer);
|
132
|
+
}
|
133
|
+
|
134
|
+
return host;
|
135
|
+
}
|
136
|
+
|
137
|
+
/** Destroys the host and all resources associated with it.
|
138
|
+
@param host pointer to the host to destroy
|
139
|
+
*/
|
140
|
+
void
|
141
|
+
enet_host_destroy (ENetHost * host)
|
142
|
+
{
|
143
|
+
ENetPeer * currentPeer;
|
144
|
+
|
145
|
+
if (host == NULL)
|
146
|
+
return;
|
147
|
+
|
148
|
+
enet_socket_destroy (host -> socket);
|
149
|
+
|
150
|
+
for (currentPeer = host -> peers;
|
151
|
+
currentPeer < & host -> peers [host -> peerCount];
|
152
|
+
++ currentPeer)
|
153
|
+
{
|
154
|
+
enet_peer_reset (currentPeer);
|
155
|
+
}
|
156
|
+
|
157
|
+
if (host -> compressor.context != NULL && host -> compressor.destroy)
|
158
|
+
(* host -> compressor.destroy) (host -> compressor.context);
|
159
|
+
|
160
|
+
enet_free (host -> peers);
|
161
|
+
enet_free (host);
|
162
|
+
}
|
163
|
+
|
164
|
+
/** Initiates a connection to a foreign host.
|
165
|
+
@param host host seeking the connection
|
166
|
+
@param address destination for the connection
|
167
|
+
@param channelCount number of channels to allocate
|
168
|
+
@param data user data supplied to the receiving host
|
169
|
+
@returns a peer representing the foreign host on success, NULL on failure
|
170
|
+
@remarks The peer returned will have not completed the connection until enet_host_service()
|
171
|
+
notifies of an ENET_EVENT_TYPE_CONNECT event for the peer.
|
172
|
+
*/
|
173
|
+
ENetPeer *
|
174
|
+
enet_host_connect (ENetHost * host, const ENetAddress * address, size_t channelCount, enet_uint32 data)
|
175
|
+
{
|
176
|
+
ENetPeer * currentPeer;
|
177
|
+
ENetChannel * channel;
|
178
|
+
ENetProtocol command;
|
179
|
+
|
180
|
+
if (channelCount < ENET_PROTOCOL_MINIMUM_CHANNEL_COUNT)
|
181
|
+
channelCount = ENET_PROTOCOL_MINIMUM_CHANNEL_COUNT;
|
182
|
+
else
|
183
|
+
if (channelCount > ENET_PROTOCOL_MAXIMUM_CHANNEL_COUNT)
|
184
|
+
channelCount = ENET_PROTOCOL_MAXIMUM_CHANNEL_COUNT;
|
185
|
+
|
186
|
+
for (currentPeer = host -> peers;
|
187
|
+
currentPeer < & host -> peers [host -> peerCount];
|
188
|
+
++ currentPeer)
|
189
|
+
{
|
190
|
+
if (currentPeer -> state == ENET_PEER_STATE_DISCONNECTED)
|
191
|
+
break;
|
192
|
+
}
|
193
|
+
|
194
|
+
if (currentPeer >= & host -> peers [host -> peerCount])
|
195
|
+
return NULL;
|
196
|
+
|
197
|
+
currentPeer -> channels = (ENetChannel *) enet_malloc (channelCount * sizeof (ENetChannel));
|
198
|
+
if (currentPeer -> channels == NULL)
|
199
|
+
return NULL;
|
200
|
+
currentPeer -> channelCount = channelCount;
|
201
|
+
currentPeer -> state = ENET_PEER_STATE_CONNECTING;
|
202
|
+
currentPeer -> address = * address;
|
203
|
+
currentPeer -> connectID = ++ host -> randomSeed;
|
204
|
+
|
205
|
+
if (host -> outgoingBandwidth == 0)
|
206
|
+
currentPeer -> windowSize = ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE;
|
207
|
+
else
|
208
|
+
currentPeer -> windowSize = (host -> outgoingBandwidth /
|
209
|
+
ENET_PEER_WINDOW_SIZE_SCALE) *
|
210
|
+
ENET_PROTOCOL_MINIMUM_WINDOW_SIZE;
|
211
|
+
|
212
|
+
if (currentPeer -> windowSize < ENET_PROTOCOL_MINIMUM_WINDOW_SIZE)
|
213
|
+
currentPeer -> windowSize = ENET_PROTOCOL_MINIMUM_WINDOW_SIZE;
|
214
|
+
else
|
215
|
+
if (currentPeer -> windowSize > ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE)
|
216
|
+
currentPeer -> windowSize = ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE;
|
217
|
+
|
218
|
+
for (channel = currentPeer -> channels;
|
219
|
+
channel < & currentPeer -> channels [channelCount];
|
220
|
+
++ channel)
|
221
|
+
{
|
222
|
+
channel -> outgoingReliableSequenceNumber = 0;
|
223
|
+
channel -> outgoingUnreliableSequenceNumber = 0;
|
224
|
+
channel -> incomingReliableSequenceNumber = 0;
|
225
|
+
channel -> incomingUnreliableSequenceNumber = 0;
|
226
|
+
|
227
|
+
enet_list_clear (& channel -> incomingReliableCommands);
|
228
|
+
enet_list_clear (& channel -> incomingUnreliableCommands);
|
229
|
+
|
230
|
+
channel -> usedReliableWindows = 0;
|
231
|
+
memset (channel -> reliableWindows, 0, sizeof (channel -> reliableWindows));
|
232
|
+
}
|
233
|
+
|
234
|
+
command.header.command = ENET_PROTOCOL_COMMAND_CONNECT | ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE;
|
235
|
+
command.header.channelID = 0xFF;
|
236
|
+
command.connect.outgoingPeerID = ENET_HOST_TO_NET_16 (currentPeer -> incomingPeerID);
|
237
|
+
command.connect.incomingSessionID = currentPeer -> incomingSessionID;
|
238
|
+
command.connect.outgoingSessionID = currentPeer -> outgoingSessionID;
|
239
|
+
command.connect.mtu = ENET_HOST_TO_NET_32 (currentPeer -> mtu);
|
240
|
+
command.connect.windowSize = ENET_HOST_TO_NET_32 (currentPeer -> windowSize);
|
241
|
+
command.connect.channelCount = ENET_HOST_TO_NET_32 (channelCount);
|
242
|
+
command.connect.incomingBandwidth = ENET_HOST_TO_NET_32 (host -> incomingBandwidth);
|
243
|
+
command.connect.outgoingBandwidth = ENET_HOST_TO_NET_32 (host -> outgoingBandwidth);
|
244
|
+
command.connect.packetThrottleInterval = ENET_HOST_TO_NET_32 (currentPeer -> packetThrottleInterval);
|
245
|
+
command.connect.packetThrottleAcceleration = ENET_HOST_TO_NET_32 (currentPeer -> packetThrottleAcceleration);
|
246
|
+
command.connect.packetThrottleDeceleration = ENET_HOST_TO_NET_32 (currentPeer -> packetThrottleDeceleration);
|
247
|
+
command.connect.connectID = currentPeer -> connectID;
|
248
|
+
command.connect.data = ENET_HOST_TO_NET_32 (data);
|
249
|
+
|
250
|
+
enet_peer_queue_outgoing_command (currentPeer, & command, NULL, 0, 0);
|
251
|
+
|
252
|
+
return currentPeer;
|
253
|
+
}
|
254
|
+
|
255
|
+
/** Queues a packet to be sent to all peers associated with the host.
|
256
|
+
@param host host on which to broadcast the packet
|
257
|
+
@param channelID channel on which to broadcast
|
258
|
+
@param packet packet to broadcast
|
259
|
+
*/
|
260
|
+
void
|
261
|
+
enet_host_broadcast (ENetHost * host, enet_uint8 channelID, ENetPacket * packet)
|
262
|
+
{
|
263
|
+
ENetPeer * currentPeer;
|
264
|
+
|
265
|
+
for (currentPeer = host -> peers;
|
266
|
+
currentPeer < & host -> peers [host -> peerCount];
|
267
|
+
++ currentPeer)
|
268
|
+
{
|
269
|
+
if (currentPeer -> state != ENET_PEER_STATE_CONNECTED)
|
270
|
+
continue;
|
271
|
+
|
272
|
+
enet_peer_send (currentPeer, channelID, packet);
|
273
|
+
}
|
274
|
+
|
275
|
+
if (packet -> referenceCount == 0)
|
276
|
+
enet_packet_destroy (packet);
|
277
|
+
}
|
278
|
+
|
279
|
+
/** Sets the packet compressor the host should use to compress and decompress packets.
|
280
|
+
@param host host to enable or disable compression for
|
281
|
+
@param compressor callbacks for for the packet compressor; if NULL, then compression is disabled
|
282
|
+
*/
|
283
|
+
void
|
284
|
+
enet_host_compress (ENetHost * host, const ENetCompressor * compressor)
|
285
|
+
{
|
286
|
+
if (host -> compressor.context != NULL && host -> compressor.destroy)
|
287
|
+
(* host -> compressor.destroy) (host -> compressor.context);
|
288
|
+
|
289
|
+
if (compressor)
|
290
|
+
host -> compressor = * compressor;
|
291
|
+
else
|
292
|
+
host -> compressor.context = NULL;
|
293
|
+
}
|
294
|
+
|
295
|
+
/** Limits the maximum allowed channels of future incoming connections.
|
296
|
+
@param host host to limit
|
297
|
+
@param channelLimit the maximum number of channels allowed; if 0, then this is equivalent to ENET_PROTOCOL_MAXIMUM_CHANNEL_COUNT
|
298
|
+
*/
|
299
|
+
void
|
300
|
+
enet_host_channel_limit (ENetHost * host, size_t channelLimit)
|
301
|
+
{
|
302
|
+
if (! channelLimit || channelLimit > ENET_PROTOCOL_MAXIMUM_CHANNEL_COUNT)
|
303
|
+
channelLimit = ENET_PROTOCOL_MAXIMUM_CHANNEL_COUNT;
|
304
|
+
else
|
305
|
+
if (channelLimit < ENET_PROTOCOL_MINIMUM_CHANNEL_COUNT)
|
306
|
+
channelLimit = ENET_PROTOCOL_MINIMUM_CHANNEL_COUNT;
|
307
|
+
|
308
|
+
host -> channelLimit = channelLimit;
|
309
|
+
}
|
310
|
+
|
311
|
+
|
312
|
+
/** Adjusts the bandwidth limits of a host.
|
313
|
+
@param host host to adjust
|
314
|
+
@param incomingBandwidth new incoming bandwidth
|
315
|
+
@param outgoingBandwidth new outgoing bandwidth
|
316
|
+
@remarks the incoming and outgoing bandwidth parameters are identical in function to those
|
317
|
+
specified in enet_host_create().
|
318
|
+
*/
|
319
|
+
void
|
320
|
+
enet_host_bandwidth_limit (ENetHost * host, enet_uint32 incomingBandwidth, enet_uint32 outgoingBandwidth)
|
321
|
+
{
|
322
|
+
host -> incomingBandwidth = incomingBandwidth;
|
323
|
+
host -> outgoingBandwidth = outgoingBandwidth;
|
324
|
+
host -> recalculateBandwidthLimits = 1;
|
325
|
+
}
|
326
|
+
|
327
|
+
void
|
328
|
+
enet_host_bandwidth_throttle (ENetHost * host)
|
329
|
+
{
|
330
|
+
enet_uint32 timeCurrent = enet_time_get (),
|
331
|
+
elapsedTime = timeCurrent - host -> bandwidthThrottleEpoch,
|
332
|
+
peersRemaining = (enet_uint32) host -> connectedPeers,
|
333
|
+
dataTotal = ~0,
|
334
|
+
bandwidth = ~0,
|
335
|
+
throttle = 0,
|
336
|
+
bandwidthLimit = 0;
|
337
|
+
int needsAdjustment = host -> bandwidthLimitedPeers > 0 ? 1 : 0;
|
338
|
+
ENetPeer * peer;
|
339
|
+
ENetProtocol command;
|
340
|
+
|
341
|
+
if (elapsedTime < ENET_HOST_BANDWIDTH_THROTTLE_INTERVAL)
|
342
|
+
return;
|
343
|
+
|
344
|
+
host -> bandwidthThrottleEpoch = timeCurrent;
|
345
|
+
|
346
|
+
if (peersRemaining == 0)
|
347
|
+
return;
|
348
|
+
|
349
|
+
if (host -> outgoingBandwidth != 0)
|
350
|
+
{
|
351
|
+
dataTotal = 0;
|
352
|
+
bandwidth = (host -> outgoingBandwidth * elapsedTime) / 1000;
|
353
|
+
|
354
|
+
for (peer = host -> peers;
|
355
|
+
peer < & host -> peers [host -> peerCount];
|
356
|
+
++ peer)
|
357
|
+
{
|
358
|
+
if (peer -> state != ENET_PEER_STATE_CONNECTED && peer -> state != ENET_PEER_STATE_DISCONNECT_LATER)
|
359
|
+
continue;
|
360
|
+
|
361
|
+
dataTotal += peer -> outgoingDataTotal;
|
362
|
+
}
|
363
|
+
}
|
364
|
+
|
365
|
+
while (peersRemaining > 0 && needsAdjustment != 0)
|
366
|
+
{
|
367
|
+
needsAdjustment = 0;
|
368
|
+
|
369
|
+
if (dataTotal <= bandwidth)
|
370
|
+
throttle = ENET_PEER_PACKET_THROTTLE_SCALE;
|
371
|
+
else
|
372
|
+
throttle = (bandwidth * ENET_PEER_PACKET_THROTTLE_SCALE) / dataTotal;
|
373
|
+
|
374
|
+
for (peer = host -> peers;
|
375
|
+
peer < & host -> peers [host -> peerCount];
|
376
|
+
++ peer)
|
377
|
+
{
|
378
|
+
enet_uint32 peerBandwidth;
|
379
|
+
|
380
|
+
if ((peer -> state != ENET_PEER_STATE_CONNECTED && peer -> state != ENET_PEER_STATE_DISCONNECT_LATER) ||
|
381
|
+
peer -> incomingBandwidth == 0 ||
|
382
|
+
peer -> outgoingBandwidthThrottleEpoch == timeCurrent)
|
383
|
+
continue;
|
384
|
+
|
385
|
+
peerBandwidth = (peer -> incomingBandwidth * elapsedTime) / 1000;
|
386
|
+
if ((throttle * peer -> outgoingDataTotal) / ENET_PEER_PACKET_THROTTLE_SCALE <= peerBandwidth)
|
387
|
+
continue;
|
388
|
+
|
389
|
+
peer -> packetThrottleLimit = (peerBandwidth *
|
390
|
+
ENET_PEER_PACKET_THROTTLE_SCALE) / peer -> outgoingDataTotal;
|
391
|
+
|
392
|
+
if (peer -> packetThrottleLimit == 0)
|
393
|
+
peer -> packetThrottleLimit = 1;
|
394
|
+
|
395
|
+
if (peer -> packetThrottle > peer -> packetThrottleLimit)
|
396
|
+
peer -> packetThrottle = peer -> packetThrottleLimit;
|
397
|
+
|
398
|
+
peer -> outgoingBandwidthThrottleEpoch = timeCurrent;
|
399
|
+
|
400
|
+
peer -> incomingDataTotal = 0;
|
401
|
+
peer -> outgoingDataTotal = 0;
|
402
|
+
|
403
|
+
needsAdjustment = 1;
|
404
|
+
-- peersRemaining;
|
405
|
+
bandwidth -= peerBandwidth;
|
406
|
+
dataTotal -= peerBandwidth;
|
407
|
+
}
|
408
|
+
}
|
409
|
+
|
410
|
+
if (peersRemaining > 0)
|
411
|
+
{
|
412
|
+
if (dataTotal <= bandwidth)
|
413
|
+
throttle = ENET_PEER_PACKET_THROTTLE_SCALE;
|
414
|
+
else
|
415
|
+
throttle = (bandwidth * ENET_PEER_PACKET_THROTTLE_SCALE) / dataTotal;
|
416
|
+
|
417
|
+
for (peer = host -> peers;
|
418
|
+
peer < & host -> peers [host -> peerCount];
|
419
|
+
++ peer)
|
420
|
+
{
|
421
|
+
if ((peer -> state != ENET_PEER_STATE_CONNECTED && peer -> state != ENET_PEER_STATE_DISCONNECT_LATER) ||
|
422
|
+
peer -> outgoingBandwidthThrottleEpoch == timeCurrent)
|
423
|
+
continue;
|
424
|
+
|
425
|
+
peer -> packetThrottleLimit = throttle;
|
426
|
+
|
427
|
+
if (peer -> packetThrottle > peer -> packetThrottleLimit)
|
428
|
+
peer -> packetThrottle = peer -> packetThrottleLimit;
|
429
|
+
|
430
|
+
peer -> incomingDataTotal = 0;
|
431
|
+
peer -> outgoingDataTotal = 0;
|
432
|
+
}
|
433
|
+
}
|
434
|
+
|
435
|
+
if (host -> recalculateBandwidthLimits)
|
436
|
+
{
|
437
|
+
host -> recalculateBandwidthLimits = 0;
|
438
|
+
|
439
|
+
peersRemaining = (enet_uint32) host -> connectedPeers;
|
440
|
+
bandwidth = host -> incomingBandwidth;
|
441
|
+
needsAdjustment = 1;
|
442
|
+
|
443
|
+
if (bandwidth == 0)
|
444
|
+
bandwidthLimit = 0;
|
445
|
+
else
|
446
|
+
while (peersRemaining > 0 && needsAdjustment != 0)
|
447
|
+
{
|
448
|
+
needsAdjustment = 0;
|
449
|
+
bandwidthLimit = bandwidth / peersRemaining;
|
450
|
+
|
451
|
+
for (peer = host -> peers;
|
452
|
+
peer < & host -> peers [host -> peerCount];
|
453
|
+
++ peer)
|
454
|
+
{
|
455
|
+
if ((peer -> state != ENET_PEER_STATE_CONNECTED && peer -> state != ENET_PEER_STATE_DISCONNECT_LATER) ||
|
456
|
+
peer -> incomingBandwidthThrottleEpoch == timeCurrent)
|
457
|
+
continue;
|
458
|
+
|
459
|
+
if (peer -> outgoingBandwidth > 0 &&
|
460
|
+
peer -> outgoingBandwidth >= bandwidthLimit)
|
461
|
+
continue;
|
462
|
+
|
463
|
+
peer -> incomingBandwidthThrottleEpoch = timeCurrent;
|
464
|
+
|
465
|
+
needsAdjustment = 1;
|
466
|
+
-- peersRemaining;
|
467
|
+
bandwidth -= peer -> outgoingBandwidth;
|
468
|
+
}
|
469
|
+
}
|
470
|
+
|
471
|
+
for (peer = host -> peers;
|
472
|
+
peer < & host -> peers [host -> peerCount];
|
473
|
+
++ peer)
|
474
|
+
{
|
475
|
+
if (peer -> state != ENET_PEER_STATE_CONNECTED && peer -> state != ENET_PEER_STATE_DISCONNECT_LATER)
|
476
|
+
continue;
|
477
|
+
|
478
|
+
command.header.command = ENET_PROTOCOL_COMMAND_BANDWIDTH_LIMIT | ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE;
|
479
|
+
command.header.channelID = 0xFF;
|
480
|
+
command.bandwidthLimit.outgoingBandwidth = ENET_HOST_TO_NET_32 (host -> outgoingBandwidth);
|
481
|
+
|
482
|
+
if (peer -> incomingBandwidthThrottleEpoch == timeCurrent)
|
483
|
+
command.bandwidthLimit.incomingBandwidth = ENET_HOST_TO_NET_32 (peer -> outgoingBandwidth);
|
484
|
+
else
|
485
|
+
command.bandwidthLimit.incomingBandwidth = ENET_HOST_TO_NET_32 (bandwidthLimit);
|
486
|
+
|
487
|
+
enet_peer_queue_outgoing_command (peer, & command, NULL, 0, 0);
|
488
|
+
}
|
489
|
+
}
|
490
|
+
}
|
491
|
+
|
492
|
+
/** @} */
|