Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 7394 was 7390, checked in by adrfried, 14 years ago

IPv6 for Windows

I have not tested this, please test this and report issues to me.

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