Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/ipv6/src/external/enet/patches/0002-basic-IPv6-support-on-Linux-systems.patch @ 7330

Last change on this file since 7330 was 7330, checked in by adrfried, 15 years ago

patch libenet to support ipv6

This is only done for Linux so far.

File size: 12.5 KB
RevLine 
[7330]1From 85c3be6ab21fd875baa57ea119ed58d5c54f0115 Mon Sep 17 00:00:00 2001
2From: Adrian Friedli <adi@koalatux.ch>
3Date: Thu, 2 Sep 2010 14:27:07 +0200
4Subject: [PATCH 2/2] basic IPv6 support on Linux systems
5
6---
7 host.c              |    2 +
8 include/enet/enet.h |   29 ++++++++++++----
9 protocol.c          |   17 ++++++----
10 unix.c              |   90 ++++++++++++++++++++++++++++++--------------------
11 4 files changed, 88 insertions(+), 50 deletions(-)
12
13diff --git a/host.c b/host.c
14index 8bb2433..5a18a59 100644
15--- a/host.c
16+++ b/host.c
17@@ -49,6 +49,8 @@ enet_host_create (const ENetAddress * address, size_t peerCount, size_t channelL
18     memset (host -> peers, 0, peerCount * sizeof (ENetPeer));
19 
20     host -> socket = enet_socket_create (ENET_SOCKET_TYPE_DATAGRAM);
21+    enet_socket_set_option (host -> socket, ENET_SOCKOPT_V6ONLY, 0); // Needs to be set before bind.
22+
23     if (host -> socket == ENET_SOCKET_NULL || (address != NULL && enet_socket_bind (host -> socket, address) < 0))
24     {
25        if (host -> socket != ENET_SOCKET_NULL)
26diff --git a/include/enet/enet.h b/include/enet/enet.h
27index 2f656d6..a9f0759 100644
28--- a/include/enet/enet.h
29+++ b/include/enet/enet.h
30@@ -50,16 +50,18 @@ typedef enum _ENetSocketOption
31    ENET_SOCKOPT_BROADCAST = 2,
32    ENET_SOCKOPT_RCVBUF    = 3,
33    ENET_SOCKOPT_SNDBUF    = 4,
34-   ENET_SOCKOPT_REUSEADDR = 5
35+   ENET_SOCKOPT_REUSEADDR = 5,
36+   ENET_SOCKOPT_V6ONLY = 6
37 } ENetSocketOption;
38 
39-enum
40+typedef struct _ENetHostAddress
41 {
42-   ENET_HOST_ANY       = 0,            /**< specifies the default server host */
43-   ENET_HOST_BROADCAST = 0xFFFFFFFF,   /**< specifies a subnet-wide broadcast */
44+   enet_uint8 addr[16];
45+} ENetHostAddress;
46 
47-   ENET_PORT_ANY       = 0             /**< specifies that a port should be automatically chosen */
48-};
49+extern const ENetHostAddress ENET_HOST_ANY;       /**< specifies the default server host */
50+extern const ENetHostAddress ENET_HOST_BROADCAST; /**< specifies a IPv4 subnet-wide broadcast */
51+#define ENET_PORT_ANY 0                           /**< specifies that a port should be automatically chosen */
52 
53 /**
54  * Portable internet address structure.
55@@ -73,7 +75,8 @@ enum
56  */
57 typedef struct _ENetAddress
58 {
59-   enet_uint32 host;
60+   ENetHostAddress host;
61+   enet_uint32 scopeID; //FIXME: this is of different size on Windows
62    enet_uint16 port;
63 } ENetAddress;
64 
65@@ -488,6 +491,18 @@ ENET_API int enet_address_get_host_ip (const ENetAddress * address, char * hostN
66 */
67 ENET_API int enet_address_get_host (const ENetAddress * address, char * hostName, size_t nameLength);
68 
69+/** Maps an IPv4 Address to an IPv6 address.
70+    @param address IPv4 address in network byte order
71+    @returns the IPv4-mapped IPv6 address in network byte order
72+*/
73+static inline ENetHostAddress enet_address_map4 (enet_uint32 address)
74+{
75+   ENetHostAddress addr = ENET_HOST_ANY;
76+   ((enet_uint16 *)addr.addr)[5] = 0xffff;
77+   ((enet_uint32 *)addr.addr)[3] = address;
78+   return addr;
79+}
80+
81 /** @} */
82 
83 ENET_API ENetPacket * enet_packet_create (const void *, size_t, enet_uint32);
84diff --git a/protocol.c b/protocol.c
85index 8e26dfb..318a2c7 100644
86--- a/protocol.c
87+++ b/protocol.c
88@@ -9,6 +9,9 @@
89 #include "enet/time.h"
90 #include "enet/enet.h"
91 
92+const ENetHostAddress ENET_HOST_ANY = { { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } };
93+const ENetHostAddress ENET_HOST_BROADCAST = { { 0,0,0,0,0,0,0,0,0,0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff } };
94+
95 static size_t commandSizes [ENET_PROTOCOL_COMMAND_COUNT] =
96 {
97     0,
98@@ -262,9 +265,9 @@ enet_protocol_handle_connect (ENetHost * host, ENetProtocolHeader * header, ENet
99          ++ currentPeer)
100     {
101         if (currentPeer -> state != ENET_PEER_STATE_DISCONNECTED &&
102-            currentPeer -> address.host == host -> receivedAddress.host &&
103             currentPeer -> address.port == host -> receivedAddress.port &&
104-            currentPeer -> connectID == command -> connect.connectID)
105+            currentPeer -> connectID == command -> connect.connectID &&
106+            !memcmp(& currentPeer -> address.host, & host -> receivedAddress.host, sizeof (ENetHostAddress)))
107           return NULL;
108     }
109 
110@@ -848,10 +851,11 @@ enet_protocol_handle_incoming_commands (ENetHost * host, ENetEvent * event)
111 
112        if (peer -> state == ENET_PEER_STATE_DISCONNECTED ||
113            peer -> state == ENET_PEER_STATE_ZOMBIE ||
114-           (host -> receivedAddress.host != peer -> address.host &&
115-             peer -> address.host != ENET_HOST_BROADCAST) ||
116            (peer -> outgoingPeerID < ENET_PROTOCOL_MAXIMUM_PEER_ID &&
117-            sessionID != peer -> incomingSessionID))
118+            sessionID != peer -> incomingSessionID) ||
119+           ( memcmp(& peer -> address.host, & host -> receivedAddress.host, sizeof (ENetHostAddress)) &&
120+             memcmp(& peer -> address.host, & ENET_HOST_BROADCAST, sizeof (ENetHostAddress)) &&
121+             peer -> address.host.addr[0] != 0xff ) )
122          return 0;
123     }
124 
125@@ -891,8 +895,7 @@ enet_protocol_handle_incoming_commands (ENetHost * host, ENetEvent * event)
126       
127     if (peer != NULL)
128     {
129-       peer -> address.host = host -> receivedAddress.host;
130-       peer -> address.port = host -> receivedAddress.port;
131+       peer -> address = host -> receivedAddress;
132        peer -> incomingDataTotal += host -> receivedDataLength;
133     }
134     
135diff --git a/unix.c b/unix.c
136index 7329e8d..49fbace 100644
137--- a/unix.c
138+++ b/unix.c
139@@ -79,8 +79,8 @@ enet_address_set_host (ENetAddress * address, const char * name)
140     struct addrinfo * res;
141 
142     memset(& hints, 0, sizeof (hints));
143-    hints.ai_flags = AI_NUMERICSERV;
144-    hints.ai_family = AF_INET;
145+    hints.ai_flags = AI_NUMERICSERV | AI_ADDRCONFIG;
146+    hints.ai_family = AF_UNSPEC;
147 
148     if ( getaddrinfo(name, NULL, &hints, &result) )
149     {
150@@ -91,7 +91,14 @@ enet_address_set_host (ENetAddress * address, const char * name)
151     {
152         if (res -> ai_family == AF_INET)
153         {
154-            address -> host = ((struct sockaddr_in *) res -> ai_addr ) -> sin_addr.s_addr;
155+            address -> host = enet_address_map4( ((struct sockaddr_in *) res -> ai_addr ) -> sin_addr.s_addr );
156+            address -> scopeID = 0;
157+            break;
158+        }
159+        if (res -> ai_family == AF_INET6)
160+        {
161+            address -> host = * (ENetHostAddress *) & ((struct sockaddr_in6 *) res -> ai_addr ) -> sin6_addr;
162+            address -> scopeID = ((struct sockaddr_in6 *) res -> ai_addr ) -> sin6_scope_id;
163             break;
164         }
165     }
166@@ -104,12 +111,13 @@ enet_address_set_host (ENetAddress * address, const char * name)
167 static int
168 enet_address_get_host_x (const ENetAddress * address, char * name, size_t nameLength, int flags)
169 {
170-    struct sockaddr_in sin;
171+    struct sockaddr_in6 sin;
172 
173-    memset (& sin, 0, sizeof (struct sockaddr_in));
174+    memset (& sin, 0, sizeof (struct sockaddr_in6));
175 
176-    sin.sin_family = AF_INET;
177-    sin.sin_addr = * (struct in_addr *) & address -> host;
178+    sin.sin6_family = AF_INET6;
179+    sin.sin6_addr = * (struct in6_addr *) & address -> host;
180+    sin.sin6_scope_id = address -> scopeID;
181 
182     if ( getnameinfo((struct sockaddr *) & sin, sizeof(sin), name, nameLength, NULL, 0, flags))
183     {
184@@ -134,26 +142,28 @@ enet_address_get_host (const ENetAddress * address, char * name, size_t nameLeng
185 int
186 enet_socket_bind (ENetSocket socket, const ENetAddress * address)
187 {
188-    struct sockaddr_in sin;
189+    struct sockaddr_in6 sin;
190 
191-    memset (& sin, 0, sizeof (struct sockaddr_in));
192+    memset (& sin, 0, sizeof (struct sockaddr_in6));
193 
194-    sin.sin_family = AF_INET;
195+    sin.sin6_family = AF_INET6;
196 
197     if (address != NULL)
198     {
199-       sin.sin_port = ENET_HOST_TO_NET_16 (address -> port);
200-       sin.sin_addr.s_addr = address -> host;
201+       sin.sin6_port = ENET_HOST_TO_NET_16 (address -> port);
202+       sin.sin6_addr = * (struct in6_addr *) & address -> host;
203+       sin.sin6_scope_id = address -> scopeID;
204     }
205     else
206     {
207-       sin.sin_port = 0;
208-       sin.sin_addr.s_addr = INADDR_ANY;
209+       sin.sin6_port = 0;
210+       sin.sin6_addr = in6addr_any;
211+       sin.sin6_scope_id = 0;
212     }
213 
214     return bind (socket,
215                  (struct sockaddr *) & sin,
216-                 sizeof (struct sockaddr_in));
217+                 sizeof (struct sockaddr_in6));
218 }
219 
220 int
221@@ -165,7 +175,7 @@ enet_socket_listen (ENetSocket socket, int backlog)
222 ENetSocket
223 enet_socket_create (ENetSocketType type)
224 {
225-    return socket (PF_INET, type == ENET_SOCKET_TYPE_DATAGRAM ? SOCK_DGRAM : SOCK_STREAM, 0);
226+    return socket (AF_INET6, type == ENET_SOCKET_TYPE_DATAGRAM ? SOCK_DGRAM : SOCK_STREAM, 0);
227 }
228 
229 int
230@@ -198,6 +208,10 @@ enet_socket_set_option (ENetSocket socket, ENetSocketOption option, int value)
231             result = setsockopt (socket, SOL_SOCKET, SO_SNDBUF, (char *) & value, sizeof (int));
232             break;
233 
234+        case ENET_SOCKOPT_V6ONLY:
235+            result = setsockopt (socket, IPPROTO_IPV6, IPV6_V6ONLY, (char *) & value, sizeof (int));
236+            break;
237+
238         default:
239             break;
240     }
241@@ -207,23 +221,24 @@ enet_socket_set_option (ENetSocket socket, ENetSocketOption option, int value)
242 int
243 enet_socket_connect (ENetSocket socket, const ENetAddress * address)
244 {
245-    struct sockaddr_in sin;
246+    struct sockaddr_in6 sin;
247 
248-    memset (& sin, 0, sizeof (struct sockaddr_in));
249+    memset (& sin, 0, sizeof (struct sockaddr_in6));
250 
251-    sin.sin_family = AF_INET;
252-    sin.sin_port = ENET_HOST_TO_NET_16 (address -> port);
253-    sin.sin_addr.s_addr = address -> host;
254+    sin.sin6_family = AF_INET6;
255+    sin.sin6_port = ENET_HOST_TO_NET_16 (address -> port);
256+    sin.sin6_addr = * (struct in6_addr *) & address -> host;
257+    sin.sin6_scope_id = address -> scopeID;
258 
259-    return connect (socket, (struct sockaddr *) & sin, sizeof (struct sockaddr_in));
260+    return connect (socket, (struct sockaddr *) & sin, sizeof (struct sockaddr_in6));
261 }
262 
263 ENetSocket
264 enet_socket_accept (ENetSocket socket, ENetAddress * address)
265 {
266     int result;
267-    struct sockaddr_in sin;
268-    socklen_t sinLength = sizeof (struct sockaddr_in);
269+    struct sockaddr_in6 sin;
270+    socklen_t sinLength = sizeof (struct sockaddr_in6);
271 
272     result = accept (socket,
273                      address != NULL ? (struct sockaddr *) & sin : NULL,
274@@ -234,8 +249,9 @@ enet_socket_accept (ENetSocket socket, ENetAddress * address)
275 
276     if (address != NULL)
277     {
278-        address -> host = (enet_uint32) sin.sin_addr.s_addr;
279-        address -> port = ENET_NET_TO_HOST_16 (sin.sin_port);
280+        address -> host = * (ENetHostAddress *) & sin.sin6_addr;
281+        address -> scopeID = sin.sin6_scope_id;
282+        address -> port = ENET_NET_TO_HOST_16 (sin.sin6_port);
283     }
284 
285     return result;
286@@ -254,21 +270,22 @@ enet_socket_send (ENetSocket socket,
287                   size_t bufferCount)
288 {
289     struct msghdr msgHdr;
290-    struct sockaddr_in sin;
291+    struct sockaddr_in6 sin;
292     int sentLength;
293 
294     memset (& msgHdr, 0, sizeof (struct msghdr));
295 
296     if (address != NULL)
297     {
298-        memset (& sin, 0, sizeof (struct sockaddr_in));
299+        memset (& sin, 0, sizeof (struct sockaddr_in6));
300 
301-        sin.sin_family = AF_INET;
302-        sin.sin_port = ENET_HOST_TO_NET_16 (address -> port);
303-        sin.sin_addr.s_addr = address -> host;
304+        sin.sin6_family = AF_INET6;
305+        sin.sin6_port = ENET_HOST_TO_NET_16 (address -> port);
306+        sin.sin6_addr = * (struct in6_addr *) & address -> host;
307+        sin.sin6_scope_id = address -> scopeID;
308 
309         msgHdr.msg_name = & sin;
310-        msgHdr.msg_namelen = sizeof (struct sockaddr_in);
311+        msgHdr.msg_namelen = sizeof (struct sockaddr_in6);
312     }
313 
314     msgHdr.msg_iov = (struct iovec *) buffers;
315@@ -294,7 +311,7 @@ enet_socket_receive (ENetSocket socket,
316                      size_t bufferCount)
317 {
318     struct msghdr msgHdr;
319-    struct sockaddr_in sin;
320+    struct sockaddr_in6 sin;
321     int recvLength;
322 
323     memset (& msgHdr, 0, sizeof (struct msghdr));
324@@ -302,7 +319,7 @@ enet_socket_receive (ENetSocket socket,
325     if (address != NULL)
326     {
327         msgHdr.msg_name = & sin;
328-        msgHdr.msg_namelen = sizeof (struct sockaddr_in);
329+        msgHdr.msg_namelen = sizeof (struct sockaddr_in6);
330     }
331 
332     msgHdr.msg_iov = (struct iovec *) buffers;
333@@ -325,8 +342,9 @@ enet_socket_receive (ENetSocket socket,
334 
335     if (address != NULL)
336     {
337-        address -> host = (enet_uint32) sin.sin_addr.s_addr;
338-        address -> port = ENET_NET_TO_HOST_16 (sin.sin_port);
339+        address -> host = * (ENetHostAddress *) & sin.sin6_addr;
340+        address -> scopeID = sin.sin6_scope_id;
341+        address -> port = ENET_NET_TO_HOST_16 (sin.sin6_port);
342     }
343 
344     return recvLength;
345--
3461.7.1
347
Note: See TracBrowser for help on using the repository browser.