aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFlorian Zeitz <florob@babelmonkeys.de>2011-06-14 01:17:07 +0200
committerSam Roberts <vieuxtech@gmail.com>2012-04-11 13:33:34 -0700
commit923eef192925cae29223974dbf1addd59b4b0f28 (patch)
treefa8a9daf1b6acd5a7b9d0b6528d0aba8147ac8d0
parent5c33ef99977587dd9ae4e013d2d43aa8bf493ad1 (diff)
downloadluasocket-923eef192925cae29223974dbf1addd59b4b0f28.tar.gz
luasocket-923eef192925cae29223974dbf1addd59b4b0f28.tar.bz2
luasocket-923eef192925cae29223974dbf1addd59b4b0f28.zip
Rework binding IPv6 sockets by harmonizing it with the IPv4 variant
-rw-r--r--src/inet.c58
-rw-r--r--src/inet.h6
-rw-r--r--src/tcp.c111
-rw-r--r--src/tcp.h1
-rw-r--r--src/udp.c27
-rw-r--r--src/udp.h1
6 files changed, 80 insertions, 124 deletions
diff --git a/src/inet.c b/src/inet.c
index 21a97c9..95b7af3 100644
--- a/src/inet.c
+++ b/src/inet.c
@@ -56,7 +56,7 @@ static int inet_gethost(const char *address, struct hostent **hp) {
56 struct in_addr addr; 56 struct in_addr addr;
57 if (inet_aton(address, &addr)) 57 if (inet_aton(address, &addr))
58 return socket_gethostbyaddr((char *) &addr, sizeof(addr), hp); 58 return socket_gethostbyaddr((char *) &addr, sizeof(addr), hp);
59 else 59 else
60 return socket_gethostbyname(address, hp); 60 return socket_gethostbyname(address, hp);
61} 61}
62 62
@@ -66,7 +66,7 @@ static int inet_gethost(const char *address, struct hostent **hp) {
66\*-------------------------------------------------------------------------*/ 66\*-------------------------------------------------------------------------*/
67static int inet_global_tohostname(lua_State *L) { 67static int inet_global_tohostname(lua_State *L) {
68 const char *address = luaL_checkstring(L, 1); 68 const char *address = luaL_checkstring(L, 1);
69 struct hostent *hp = NULL; 69 struct hostent *hp = NULL;
70 int err = inet_gethost(address, &hp); 70 int err = inet_gethost(address, &hp);
71 if (err != IO_DONE) { 71 if (err != IO_DONE) {
72 lua_pushnil(L); 72 lua_pushnil(L);
@@ -85,7 +85,7 @@ static int inet_global_tohostname(lua_State *L) {
85static int inet_global_toip(lua_State *L) 85static int inet_global_toip(lua_State *L)
86{ 86{
87 const char *address = luaL_checkstring(L, 1); 87 const char *address = luaL_checkstring(L, 1);
88 struct hostent *hp = NULL; 88 struct hostent *hp = NULL;
89 int err = inet_gethost(address, &hp); 89 int err = inet_gethost(address, &hp);
90 if (err != IO_DONE) { 90 if (err != IO_DONE) {
91 lua_pushnil(L); 91 lua_pushnil(L);
@@ -136,7 +136,7 @@ static int inet_global_toip6(lua_State *L)
136 lua_settable(L, -3); 136 lua_settable(L, -3);
137 lua_settable(L, -3); 137 lua_settable(L, -3);
138 i++; 138 i++;
139 } 139 }
140 freeaddrinfo(resolved); 140 freeaddrinfo(resolved);
141 return 1; 141 return 1;
142} 142}
@@ -244,14 +244,14 @@ static void inet_pushresolved(lua_State *L, struct hostent *hp)
244/*-------------------------------------------------------------------------*\ 244/*-------------------------------------------------------------------------*\
245* Tries to create a new inet socket 245* Tries to create a new inet socket
246\*-------------------------------------------------------------------------*/ 246\*-------------------------------------------------------------------------*/
247const char *inet_trycreate(p_socket ps, int type) { 247const char *inet_trycreate(p_socket ps, int domain, int type) {
248 return socket_strerror(socket_create(ps, AF_INET, type, 0)); 248 return socket_strerror(socket_create(ps, domain, type, 0));
249} 249}
250 250
251/*-------------------------------------------------------------------------*\ 251/*-------------------------------------------------------------------------*\
252* Tries to connect to remote address (address, port) 252* Tries to connect to remote address (address, port)
253\*-------------------------------------------------------------------------*/ 253\*-------------------------------------------------------------------------*/
254const char *inet_tryconnect(p_socket ps, const char *address, 254const char *inet_tryconnect(p_socket ps, const char *address,
255 unsigned short port, p_timeout tm) 255 unsigned short port, p_timeout tm)
256{ 256{
257 struct sockaddr_in remote; 257 struct sockaddr_in remote;
@@ -276,25 +276,35 @@ const char *inet_tryconnect(p_socket ps, const char *address,
276/*-------------------------------------------------------------------------*\ 276/*-------------------------------------------------------------------------*\
277* Tries to bind socket to (address, port) 277* Tries to bind socket to (address, port)
278\*-------------------------------------------------------------------------*/ 278\*-------------------------------------------------------------------------*/
279const char *inet_trybind(p_socket ps, const char *address, unsigned short port) 279const char *inet_trybind(p_socket ps, const char *address, const char *serv,
280 struct addrinfo *bindhints)
280{ 281{
281 struct sockaddr_in local; 282 struct addrinfo *iterator = NULL, *resolved = NULL;
282 int err; 283 const char *err = NULL;
283 memset(&local, 0, sizeof(local)); 284 /* translate luasocket special values to C */
284 /* address is either wildcard or a valid ip address */ 285 if (strcmp(address, "*") == 0) address = NULL;
285 local.sin_addr.s_addr = htonl(INADDR_ANY); 286 if (!serv) serv = "0";
286 local.sin_port = htons(port); 287 /* try resolving */
287 local.sin_family = AF_INET; 288 err = socket_gaistrerror(getaddrinfo(address, serv,
288 if (strcmp(address, "*") && !inet_aton(address, &local.sin_addr)) { 289 bindhints, &resolved));
289 struct hostent *hp = NULL; 290 if (err) {
290 struct in_addr **addr; 291 if (resolved) freeaddrinfo(resolved);
291 err = socket_gethostbyname(address, &hp); 292 return err;
292 if (err != IO_DONE) return socket_hoststrerror(err);
293 addr = (struct in_addr **) hp->h_addr_list;
294 memcpy(&local.sin_addr, *addr, sizeof(struct in_addr));
295 } 293 }
296 err = socket_bind(ps, (SA *) &local, sizeof(local)); 294 /* iterate over resolved addresses until one is good */
297 return socket_strerror(err); 295 for (iterator = resolved; iterator; iterator = iterator->ai_next) {
296 /* try binding to local address */
297 err = socket_strerror(socket_bind(ps,
298 (SA *) iterator->ai_addr,
299 iterator->ai_addrlen));
300 /* if faiiled, we try the next one */
301 if (err != NULL) socket_destroy(ps);
302 /* if success, we abort loop */
303 else break;
304 }
305 /* cleanup and return error */
306 freeaddrinfo(resolved);
307 return err;
298} 308}
299 309
300/*-------------------------------------------------------------------------*\ 310/*-------------------------------------------------------------------------*\
diff --git a/src/inet.h b/src/inet.h
index dbc160c..e008844 100644
--- a/src/inet.h
+++ b/src/inet.h
@@ -24,11 +24,11 @@
24 24
25int inet_open(lua_State *L); 25int inet_open(lua_State *L);
26 26
27const char *inet_trycreate(p_socket ps, int type); 27const char *inet_trycreate(p_socket ps, int domain, int type);
28const char *inet_tryconnect(p_socket ps, const char *address, 28const char *inet_tryconnect(p_socket ps, const char *address,
29 unsigned short port, p_timeout tm); 29 unsigned short port, p_timeout tm);
30const char *inet_trybind(p_socket ps, const char *address, 30const char *inet_trybind(p_socket ps, const char *address, const char *serv,
31 unsigned short port); 31 struct addrinfo *bindhints);
32 32
33int inet_meth_getpeername(lua_State *L, p_socket ps); 33int inet_meth_getpeername(lua_State *L, p_socket ps);
34int inet_meth_getsockname(lua_State *L, p_socket ps); 34int inet_meth_getsockname(lua_State *L, p_socket ps);
diff --git a/src/tcp.c b/src/tcp.c
index 658f255..155f3bf 100644
--- a/src/tcp.c
+++ b/src/tcp.c
@@ -19,8 +19,8 @@
19* Internal function prototypes 19* Internal function prototypes
20\*=========================================================================*/ 20\*=========================================================================*/
21static int global_create(lua_State *L); 21static int global_create(lua_State *L);
22static int global_create6(lua_State *L);
22static int global_connect6(lua_State *L); 23static int global_connect6(lua_State *L);
23static int global_bind6(lua_State *L);
24static int meth_connect(lua_State *L); 24static int meth_connect(lua_State *L);
25static int meth_listen(lua_State *L); 25static int meth_listen(lua_State *L);
26static int meth_bind(lua_State *L); 26static int meth_bind(lua_State *L);
@@ -77,8 +77,8 @@ static t_opt optset[] = {
77/* functions in library namespace */ 77/* functions in library namespace */
78static luaL_reg func[] = { 78static luaL_reg func[] = {
79 {"tcp", global_create}, 79 {"tcp", global_create},
80 {"tcp6", global_create6},
80 {"connect6", global_connect6}, 81 {"connect6", global_connect6},
81 {"bind6", global_bind6},
82 {NULL, NULL} 82 {NULL, NULL}
83}; 83};
84 84
@@ -196,8 +196,14 @@ static int meth_bind(lua_State *L)
196{ 196{
197 p_tcp tcp = (p_tcp) auxiliar_checkclass(L, "tcp{master}", 1); 197 p_tcp tcp = (p_tcp) auxiliar_checkclass(L, "tcp{master}", 1);
198 const char *address = luaL_checkstring(L, 2); 198 const char *address = luaL_checkstring(L, 2);
199 unsigned short port = (unsigned short) luaL_checknumber(L, 3); 199 const char *port = luaL_checkstring(L, 3);
200 const char *err = inet_trybind(&tcp->sock, address, port); 200 const char *err;
201 struct addrinfo bindhints;
202 memset(&bindhints, 0, sizeof(bindhints));
203 bindhints.ai_socktype = SOCK_STREAM;
204 bindhints.ai_family = tcp->domain;
205 bindhints.ai_flags = AI_PASSIVE;
206 err = inet_trybind(&tcp->sock, address, port, &bindhints);
201 if (err) { 207 if (err) {
202 lua_pushnil(L); 208 lua_pushnil(L);
203 lua_pushstring(L, err); 209 lua_pushstring(L, err);
@@ -317,11 +323,11 @@ static int meth_settimeout(lua_State *L)
317/*-------------------------------------------------------------------------*\ 323/*-------------------------------------------------------------------------*\
318* Creates a master tcp object 324* Creates a master tcp object
319\*-------------------------------------------------------------------------*/ 325\*-------------------------------------------------------------------------*/
320static int global_create(lua_State *L) { 326static int tcp_create(lua_State *L, int domain) {
321 t_socket sock; 327 t_socket sock;
322 const char *err = inet_trycreate(&sock, SOCK_STREAM); 328 const char *err = inet_trycreate(&sock, domain, SOCK_STREAM);
323 /* try to allocate a system socket */ 329 /* try to allocate a system socket */
324 if (!err) { 330 if (!err) {
325 /* allocate tcp object */ 331 /* allocate tcp object */
326 p_tcp tcp = (p_tcp) lua_newuserdata(L, sizeof(t_tcp)); 332 p_tcp tcp = (p_tcp) lua_newuserdata(L, sizeof(t_tcp));
327 /* set its type as master object */ 333 /* set its type as master object */
@@ -333,6 +339,7 @@ static int global_create(lua_State *L) {
333 (p_error) socket_ioerror, &tcp->sock); 339 (p_error) socket_ioerror, &tcp->sock);
334 timeout_init(&tcp->tm, -1, -1); 340 timeout_init(&tcp->tm, -1, -1);
335 buffer_init(&tcp->buf, &tcp->io, &tcp->tm); 341 buffer_init(&tcp->buf, &tcp->io, &tcp->tm);
342 tcp->domain = domain;
336 return 1; 343 return 1;
337 } else { 344 } else {
338 lua_pushnil(L); 345 lua_pushnil(L);
@@ -341,92 +348,12 @@ static int global_create(lua_State *L) {
341 } 348 }
342} 349}
343 350
344static const char *trybind6(const char *localaddr, const char *localserv, 351static int global_create(lua_State *L) {
345 struct addrinfo *bindhints, p_tcp tcp) { 352 return tcp_create(L, AF_INET);
346 struct addrinfo *iterator = NULL, *resolved = NULL;
347 const char *err = NULL;
348 /* translate luasocket special values to C */
349 if (strcmp(localaddr, "*") == 0) localaddr = NULL;
350 if (!localserv) localserv = "0";
351 /* try resolving */
352 err = socket_gaistrerror(getaddrinfo(localaddr, localserv,
353 bindhints, &resolved));
354 if (err) {
355 if (resolved) freeaddrinfo(resolved);
356 return err;
357 }
358 /* iterate over resolved addresses until one is good */
359 for (iterator = resolved; iterator; iterator = iterator->ai_next) {
360 /* create a new socket each time because parameters
361 * may have changed */
362 err = socket_strerror(socket_create(&tcp->sock,
363 iterator->ai_family, iterator->ai_socktype,
364 iterator->ai_protocol));
365 /* if failed to create socket, bail out */
366 if (err != NULL) {
367 freeaddrinfo(resolved);
368 return err;
369 }
370 /* all sockets are set as non-blocking initially */
371 socket_setnonblocking(&tcp->sock);
372 /* try binding to local address */
373 err = socket_strerror(socket_bind(&tcp->sock,
374 (SA *) iterator->ai_addr,
375 iterator->ai_addrlen));
376 /* if faiiled, we try the next one */
377 if (err != NULL) socket_destroy(&tcp->sock);
378 /* if success, we abort loop */
379 else break;
380 }
381 /* at this point, if err is not set, se succeeded */
382 if (err == NULL) {
383 /* save family of chosen local address */
384 bindhints->ai_family = iterator->ai_family;
385 }
386 /* cleanup and return error */
387 freeaddrinfo(resolved);
388 return err;
389} 353}
390 354
391static int global_bind6(lua_State *L) { 355static int global_create6(lua_State *L) {
392 const char *localaddr = luaL_checkstring(L, 1); 356 return tcp_create(L, AF_INET6);
393 const char *localserv = luaL_checkstring(L, 2);
394 int backlog = luaL_checkint(L, 3);
395 p_tcp tcp = (p_tcp) lua_newuserdata(L, sizeof(t_tcp));
396 struct addrinfo bindhints;
397 const char *err = NULL;
398 /* initialize tcp structure */
399 io_init(&tcp->io, (p_send) socket_send, (p_recv) socket_recv,
400 (p_error) socket_ioerror, &tcp->sock);
401 timeout_init(&tcp->tm, -1, -1);
402 buffer_init(&tcp->buf, &tcp->io, &tcp->tm);
403 tcp->sock = SOCKET_INVALID;
404 /* try binding to local address */
405 memset(&bindhints, 0, sizeof(bindhints));
406 bindhints.ai_socktype = SOCK_STREAM;
407 bindhints.ai_family = PF_UNSPEC;
408 bindhints.ai_flags = AI_PASSIVE;
409 err = trybind6(localaddr, localserv, &bindhints, tcp);
410 if (err == NULL) {
411 /* all server sockets initially with reuseaddr set */
412 int val = 1;
413 setsockopt(tcp->sock, SOL_SOCKET, SO_REUSEADDR,
414 (char *) &val, sizeof(val));
415 /* set the backlog and listen */
416 err = socket_strerror(socket_listen(&tcp->sock, backlog));
417 if (err) {
418 socket_destroy(&tcp->sock);
419 lua_pushnil(L);
420 lua_pushstring(L, err);
421 return 2;
422 }
423 auxiliar_setclass(L, "tcp{server}", -1);
424 return 1;
425 } else {
426 lua_pushnil(L);
427 lua_pushstring(L, err);
428 return 2;
429 }
430} 357}
431 358
432static const char *tryconnect6(const char *remoteaddr, const char *remoteserv, 359static const char *tryconnect6(const char *remoteaddr, const char *remoteserv,
@@ -488,7 +415,7 @@ static int global_connect6(lua_State *L) {
488 bindhints.ai_family = PF_UNSPEC; 415 bindhints.ai_family = PF_UNSPEC;
489 bindhints.ai_flags = AI_PASSIVE; 416 bindhints.ai_flags = AI_PASSIVE;
490 if (localaddr) { 417 if (localaddr) {
491 err = trybind6(localaddr, localserv, &bindhints, tcp); 418 err = inet_trybind(&tcp->sock, localaddr, localserv, &bindhints);
492 if (err) { 419 if (err) {
493 lua_pushnil(L); 420 lua_pushnil(L);
494 lua_pushstring(L, err); 421 lua_pushstring(L, err);
diff --git a/src/tcp.h b/src/tcp.h
index a536b49..4dc9c4a 100644
--- a/src/tcp.h
+++ b/src/tcp.h
@@ -25,6 +25,7 @@ typedef struct t_tcp_ {
25 t_io io; 25 t_io io;
26 t_buffer buf; 26 t_buffer buf;
27 t_timeout tm; 27 t_timeout tm;
28 int domain;
28} t_tcp; 29} t_tcp;
29 30
30typedef t_tcp *p_tcp; 31typedef t_tcp *p_tcp;
diff --git a/src/udp.c b/src/udp.c
index 0f9b7cc..94bf125 100644
--- a/src/udp.c
+++ b/src/udp.c
@@ -27,6 +27,7 @@
27* Internal function prototypes 27* Internal function prototypes
28\*=========================================================================*/ 28\*=========================================================================*/
29static int global_create(lua_State *L); 29static int global_create(lua_State *L);
30static int global_create6(lua_State *L);
30static int meth_send(lua_State *L); 31static int meth_send(lua_State *L);
31static int meth_sendto(lua_State *L); 32static int meth_sendto(lua_State *L);
32static int meth_receive(lua_State *L); 33static int meth_receive(lua_State *L);
@@ -89,6 +90,7 @@ static t_opt optget[] = {
89/* functions in library namespace */ 90/* functions in library namespace */
90static luaL_reg func[] = { 91static luaL_reg func[] = {
91 {"udp", global_create}, 92 {"udp", global_create},
93 {"udp6", global_create6},
92 {NULL, NULL} 94 {NULL, NULL}
93}; 95};
94 96
@@ -317,8 +319,14 @@ static int meth_close(lua_State *L) {
317static int meth_setsockname(lua_State *L) { 319static int meth_setsockname(lua_State *L) {
318 p_udp udp = (p_udp) auxiliar_checkclass(L, "udp{unconnected}", 1); 320 p_udp udp = (p_udp) auxiliar_checkclass(L, "udp{unconnected}", 1);
319 const char *address = luaL_checkstring(L, 2); 321 const char *address = luaL_checkstring(L, 2);
320 unsigned short port = (unsigned short) luaL_checknumber(L, 3); 322 const char *port = luaL_checkstring(L, 3);
321 const char *err = inet_trybind(&udp->sock, address, port); 323 const char *err;
324 struct addrinfo bindhints;
325 memset(&bindhints, 0, sizeof(bindhints));
326 bindhints.ai_socktype = SOCK_DGRAM;
327 bindhints.ai_family = udp->domain;
328 bindhints.ai_flags = AI_PASSIVE;
329 err = inet_trybind(&udp->sock, address, port, &bindhints);
322 if (err) { 330 if (err) {
323 lua_pushnil(L); 331 lua_pushnil(L);
324 lua_pushstring(L, err); 332 lua_pushstring(L, err);
@@ -334,18 +342,19 @@ static int meth_setsockname(lua_State *L) {
334/*-------------------------------------------------------------------------*\ 342/*-------------------------------------------------------------------------*\
335* Creates a master udp object 343* Creates a master udp object
336\*-------------------------------------------------------------------------*/ 344\*-------------------------------------------------------------------------*/
337static int global_create(lua_State *L) { 345static int udp_create(lua_State *L, int domain) {
338 t_socket sock; 346 t_socket sock;
339 const char *err = inet_trycreate(&sock, SOCK_DGRAM); 347 const char *err = inet_trycreate(&sock, domain, SOCK_DGRAM);
340 /* try to allocate a system socket */ 348 /* try to allocate a system socket */
341 if (!err) { 349 if (!err) {
342 /* allocate tcp object */ 350 /* allocate udp object */
343 p_udp udp = (p_udp) lua_newuserdata(L, sizeof(t_udp)); 351 p_udp udp = (p_udp) lua_newuserdata(L, sizeof(t_udp));
344 auxiliar_setclass(L, "udp{unconnected}", -1); 352 auxiliar_setclass(L, "udp{unconnected}", -1);
345 /* initialize remaining structure fields */ 353 /* initialize remaining structure fields */
346 socket_setnonblocking(&sock); 354 socket_setnonblocking(&sock);
347 udp->sock = sock; 355 udp->sock = sock;
348 timeout_init(&udp->tm, -1, -1); 356 timeout_init(&udp->tm, -1, -1);
357 udp->domain = domain;
349 return 1; 358 return 1;
350 } else { 359 } else {
351 lua_pushnil(L); 360 lua_pushnil(L);
@@ -353,3 +362,11 @@ static int global_create(lua_State *L) {
353 return 2; 362 return 2;
354 } 363 }
355} 364}
365
366static int global_create(lua_State *L) {
367 return udp_create(L, AF_INET);
368}
369
370static int global_create6(lua_State *L) {
371 return udp_create(L, AF_INET6);
372}
diff --git a/src/udp.h b/src/udp.h
index 358d9e1..c5b8688 100644
--- a/src/udp.h
+++ b/src/udp.h
@@ -23,6 +23,7 @@
23typedef struct t_udp_ { 23typedef struct t_udp_ {
24 t_socket sock; 24 t_socket sock;
25 t_timeout tm; 25 t_timeout tm;
26 int domain;
26} t_udp; 27} t_udp;
27typedef t_udp *p_udp; 28typedef t_udp *p_udp;
28 29