diff options
| author | Diego Nehab <diego@impa.br> | 2013-05-27 21:17:00 +0800 |
|---|---|---|
| committer | Diego Nehab <diego@impa.br> | 2013-05-27 21:17:00 +0800 |
| commit | 3d61b0fe36708bce78bd087c7f7247e93e07a667 (patch) | |
| tree | 51727c3f53b3e550467ee60eca54a2a202a828f3 /src/inet.c | |
| parent | afe04943184c95adfbb2d05b8b7f0f4b3c36c3b5 (diff) | |
| parent | 834a3cf520637df0af9967e1f8ad9e40837771cb (diff) | |
| download | luasocket-3d61b0fe36708bce78bd087c7f7247e93e07a667.tar.gz luasocket-3d61b0fe36708bce78bd087c7f7247e93e07a667.tar.bz2 luasocket-3d61b0fe36708bce78bd087c7f7247e93e07a667.zip | |
Merge branch 'pkulchenko' into unstable
Diffstat (limited to 'src/inet.c')
| -rw-r--r-- | src/inet.c | 116 |
1 files changed, 91 insertions, 25 deletions
| @@ -79,24 +79,22 @@ static int inet_global_tohostname(lua_State *L) { | |||
| 79 | } | 79 | } |
| 80 | 80 | ||
| 81 | static int inet_global_getnameinfo(lua_State *L) { | 81 | static int inet_global_getnameinfo(lua_State *L) { |
| 82 | char hbuf[NI_MAXHOST]; | ||
| 83 | char sbuf[NI_MAXSERV]; | ||
| 82 | int i, ret; | 84 | int i, ret; |
| 83 | char host[1024]; | ||
| 84 | char serv[32]; | ||
| 85 | struct addrinfo hints; | 85 | struct addrinfo hints; |
| 86 | struct addrinfo *resolved, *iter; | 86 | struct addrinfo *resolved, *iter; |
| 87 | const char *node = luaL_optstring(L, 1, NULL); | 87 | const char *host = luaL_optstring(L, 1, NULL); |
| 88 | const char *service = luaL_optstring(L, 2, NULL); | 88 | const char *serv = luaL_optstring(L, 2, NULL); |
| 89 | 89 | ||
| 90 | if (!(node || service)) | 90 | if (!(host || serv)) |
| 91 | luaL_error(L, "You have to specify a hostname, a service, or both"); | 91 | luaL_error(L, "host and serv cannot be both nil"); |
| 92 | 92 | ||
| 93 | memset(&hints, 0, sizeof(hints)); | 93 | memset(&hints, 0, sizeof(hints)); |
| 94 | hints.ai_socktype = SOCK_STREAM; | 94 | hints.ai_socktype = SOCK_STREAM; |
| 95 | hints.ai_family = PF_UNSPEC; | 95 | hints.ai_family = PF_UNSPEC; |
| 96 | 96 | ||
| 97 | /* getaddrinfo must get a node and a service argument */ | 97 | ret = getaddrinfo(host, serv, &hints, &resolved); |
| 98 | ret = getaddrinfo(node ? node : "127.0.0.1", service ? service : "7", | ||
| 99 | &hints, &resolved); | ||
| 100 | if (ret != 0) { | 98 | if (ret != 0) { |
| 101 | lua_pushnil(L); | 99 | lua_pushnil(L); |
| 102 | lua_pushstring(L, socket_gaistrerror(ret)); | 100 | lua_pushstring(L, socket_gaistrerror(ret)); |
| @@ -105,19 +103,19 @@ static int inet_global_getnameinfo(lua_State *L) { | |||
| 105 | 103 | ||
| 106 | lua_newtable(L); | 104 | lua_newtable(L); |
| 107 | for (i = 1, iter = resolved; iter; i++, iter = iter->ai_next) { | 105 | for (i = 1, iter = resolved; iter; i++, iter = iter->ai_next) { |
| 108 | getnameinfo(iter->ai_addr, (socklen_t) iter->ai_addrlen, host, | 106 | getnameinfo(iter->ai_addr, (socklen_t) iter->ai_addrlen, |
| 109 | node ? (socklen_t) sizeof(host) : 0, serv, service ? (socklen_t) sizeof(serv) : 0, 0); | 107 | hbuf, host? (socklen_t) sizeof(hbuf): 0, |
| 110 | 108 | sbuf, serv? (socklen_t) sizeof(sbuf): 0, 0); | |
| 111 | if (node) { | 109 | if (host) { |
| 112 | lua_pushnumber(L, i); | 110 | lua_pushnumber(L, i); |
| 113 | lua_pushstring(L, host); | 111 | lua_pushstring(L, hbuf); |
| 114 | lua_settable(L, -3); | 112 | lua_settable(L, -3); |
| 115 | } | 113 | } |
| 116 | } | 114 | } |
| 117 | freeaddrinfo(resolved); | 115 | freeaddrinfo(resolved); |
| 118 | 116 | ||
| 119 | if (service) { | 117 | if (serv) { |
| 120 | lua_pushstring(L, serv); | 118 | lua_pushstring(L, sbuf); |
| 121 | return 2; | 119 | return 2; |
| 122 | } else { | 120 | } else { |
| 123 | return 1; | 121 | return 1; |
| @@ -176,9 +174,14 @@ static int inet_global_getaddrinfo(lua_State *L) | |||
| 176 | } | 174 | } |
| 177 | lua_newtable(L); | 175 | lua_newtable(L); |
| 178 | for (iterator = resolved; iterator; iterator = iterator->ai_next) { | 176 | for (iterator = resolved; iterator; iterator = iterator->ai_next) { |
| 179 | char hbuf[NI_MAXHOST], sbuf[NI_MAXSERV]; | 177 | char hbuf[NI_MAXHOST]; |
| 180 | getnameinfo(iterator->ai_addr, (socklen_t) iterator->ai_addrlen, hbuf, | 178 | ret = getnameinfo(iterator->ai_addr, (socklen_t) iterator->ai_addrlen, |
| 181 | (socklen_t) sizeof(hbuf), sbuf, 0, NI_NUMERICHOST); | 179 | hbuf, (socklen_t) sizeof(hbuf), NULL, 0, NI_NUMERICHOST); |
| 180 | if (ret){ | ||
| 181 | lua_pushnil(L); | ||
| 182 | lua_pushstring(L, socket_gaistrerror(ret)); | ||
| 183 | return 2; | ||
| 184 | } | ||
| 182 | lua_pushnumber(L, i); | 185 | lua_pushnumber(L, i); |
| 183 | lua_newtable(L); | 186 | lua_newtable(L); |
| 184 | switch (iterator->ai_family) { | 187 | switch (iterator->ai_family) { |
| @@ -203,7 +206,6 @@ static int inet_global_getaddrinfo(lua_State *L) | |||
| 203 | return 1; | 206 | return 1; |
| 204 | } | 207 | } |
| 205 | 208 | ||
| 206 | |||
| 207 | /*-------------------------------------------------------------------------*\ | 209 | /*-------------------------------------------------------------------------*\ |
| 208 | * Gets the host name | 210 | * Gets the host name |
| 209 | \*-------------------------------------------------------------------------*/ | 211 | \*-------------------------------------------------------------------------*/ |
| @@ -222,7 +224,6 @@ static int inet_global_gethostname(lua_State *L) | |||
| 222 | } | 224 | } |
| 223 | 225 | ||
| 224 | 226 | ||
| 225 | |||
| 226 | /*=========================================================================*\ | 227 | /*=========================================================================*\ |
| 227 | * Lua methods | 228 | * Lua methods |
| 228 | \*=========================================================================*/ | 229 | \*=========================================================================*/ |
| @@ -385,7 +386,6 @@ const char *inet_trydisconnect(p_socket ps, int family, p_timeout tm) | |||
| 385 | struct in6_addr addrany = IN6ADDR_ANY_INIT; | 386 | struct in6_addr addrany = IN6ADDR_ANY_INIT; |
| 386 | memset((char *) &sin6, 0, sizeof(sin6)); | 387 | memset((char *) &sin6, 0, sizeof(sin6)); |
| 387 | sin6.sin6_family = AF_UNSPEC; | 388 | sin6.sin6_family = AF_UNSPEC; |
| 388 | fprintf(stderr, "disconnecting\n"); | ||
| 389 | sin6.sin6_addr = addrany; | 389 | sin6.sin6_addr = addrany; |
| 390 | return socket_strerror(socket_connect(ps, (SA *) &sin6, | 390 | return socket_strerror(socket_connect(ps, (SA *) &sin6, |
| 391 | sizeof(sin6), tm)); | 391 | sizeof(sin6), tm)); |
| @@ -397,7 +397,7 @@ fprintf(stderr, "disconnecting\n"); | |||
| 397 | /*-------------------------------------------------------------------------*\ | 397 | /*-------------------------------------------------------------------------*\ |
| 398 | * Tries to connect to remote address (address, port) | 398 | * Tries to connect to remote address (address, port) |
| 399 | \*-------------------------------------------------------------------------*/ | 399 | \*-------------------------------------------------------------------------*/ |
| 400 | const char *inet_tryconnect(p_socket ps, const char *address, | 400 | const char *inet_tryconnect(p_socket ps, int *family, const char *address, |
| 401 | const char *serv, p_timeout tm, struct addrinfo *connecthints) | 401 | const char *serv, p_timeout tm, struct addrinfo *connecthints) |
| 402 | { | 402 | { |
| 403 | struct addrinfo *iterator = NULL, *resolved = NULL; | 403 | struct addrinfo *iterator = NULL, *resolved = NULL; |
| @@ -411,6 +411,23 @@ const char *inet_tryconnect(p_socket ps, const char *address, | |||
| 411 | } | 411 | } |
| 412 | for (iterator = resolved; iterator; iterator = iterator->ai_next) { | 412 | for (iterator = resolved; iterator; iterator = iterator->ai_next) { |
| 413 | timeout_markstart(tm); | 413 | timeout_markstart(tm); |
| 414 | /* create new socket if necessary. if there was no | ||
| 415 | * bind, we need to create one for every new family | ||
| 416 | * that shows up while iterating. if there was a | ||
| 417 | * bind, all families will be the same and we will | ||
| 418 | * not enter this branch. */ | ||
| 419 | if (*family != iterator->ai_family) { | ||
| 420 | socket_destroy(ps); | ||
| 421 | err = socket_strerror(socket_create(ps, iterator->ai_family, | ||
| 422 | iterator->ai_socktype, iterator->ai_protocol)); | ||
| 423 | if (err != NULL) { | ||
| 424 | freeaddrinfo(resolved); | ||
| 425 | return err; | ||
| 426 | } | ||
| 427 | *family = iterator->ai_family; | ||
| 428 | /* all sockets initially non-blocking */ | ||
| 429 | socket_setnonblocking(ps); | ||
| 430 | } | ||
| 414 | /* try connecting to remote address */ | 431 | /* try connecting to remote address */ |
| 415 | err = socket_strerror(socket_connect(ps, (SA *) iterator->ai_addr, | 432 | err = socket_strerror(socket_connect(ps, (SA *) iterator->ai_addr, |
| 416 | (socklen_t) iterator->ai_addrlen, tm)); | 433 | (socklen_t) iterator->ai_addrlen, tm)); |
| @@ -425,7 +442,8 @@ const char *inet_tryconnect(p_socket ps, const char *address, | |||
| 425 | /*-------------------------------------------------------------------------*\ | 442 | /*-------------------------------------------------------------------------*\ |
| 426 | * Tries to accept a socket | 443 | * Tries to accept a socket |
| 427 | \*-------------------------------------------------------------------------*/ | 444 | \*-------------------------------------------------------------------------*/ |
| 428 | const char *inet_tryaccept(p_socket server, int family, p_socket client, p_timeout tm) | 445 | const char *inet_tryaccept(p_socket server, int family, p_socket client, |
| 446 | p_timeout tm) | ||
| 429 | { | 447 | { |
| 430 | socklen_t len; | 448 | socklen_t len; |
| 431 | t_sockaddr_storage addr; | 449 | t_sockaddr_storage addr; |
| @@ -446,6 +464,9 @@ const char *inet_trybind(p_socket ps, const char *address, const char *serv, | |||
| 446 | struct addrinfo *iterator = NULL, *resolved = NULL; | 464 | struct addrinfo *iterator = NULL, *resolved = NULL; |
| 447 | const char *err = NULL; | 465 | const char *err = NULL; |
| 448 | t_socket sock = *ps; | 466 | t_socket sock = *ps; |
| 467 | /* translate luasocket special values to C */ | ||
| 468 | if (strcmp(address, "*") == 0) address = NULL; | ||
| 469 | if (!serv) serv = "0"; | ||
| 449 | /* try resolving */ | 470 | /* try resolving */ |
| 450 | err = socket_gaistrerror(getaddrinfo(address, serv, bindhints, &resolved)); | 471 | err = socket_gaistrerror(getaddrinfo(address, serv, bindhints, &resolved)); |
| 451 | if (err) { | 472 | if (err) { |
| @@ -485,7 +506,7 @@ const char *inet_trybind(p_socket ps, const char *address, const char *serv, | |||
| 485 | * Some systems do not provide this so that we provide our own. It's not | 506 | * Some systems do not provide this so that we provide our own. It's not |
| 486 | * marvelously fast, but it works just fine. | 507 | * marvelously fast, but it works just fine. |
| 487 | \*-------------------------------------------------------------------------*/ | 508 | \*-------------------------------------------------------------------------*/ |
| 488 | #ifdef INET_ATON | 509 | #ifdef LUASOCKET_INET_ATON |
| 489 | int inet_aton(const char *cp, struct in_addr *inp) | 510 | int inet_aton(const char *cp, struct in_addr *inp) |
| 490 | { | 511 | { |
| 491 | unsigned int a = 0, b = 0, c = 0, d = 0; | 512 | unsigned int a = 0, b = 0, c = 0, d = 0; |
| @@ -507,4 +528,49 @@ int inet_aton(const char *cp, struct in_addr *inp) | |||
| 507 | } | 528 | } |
| 508 | #endif | 529 | #endif |
| 509 | 530 | ||
| 531 | /*-------------------------------------------------------------------------*\ | ||
| 532 | * inet_ntop/inet_pton for MinGW from | ||
| 533 | * http://mingw-users.1079350.n2.nabble.com/IPv6-getaddrinfo-amp-inet-ntop-td5891996.html | ||
| 534 | \*-------------------------------------------------------------------------*/ | ||
| 535 | |||
| 536 | #ifdef LUASOCKET_INET_PTON | ||
| 537 | const char *inet_ntop(int af, const void *src, char *dst, socklen_t cnt) | ||
| 538 | { | ||
| 539 | if (af == AF_INET) { | ||
| 540 | struct sockaddr_in in; | ||
| 541 | memset(&in, 0, sizeof(in)); | ||
| 542 | in.sin_family = AF_INET; | ||
| 543 | memcpy(&in.sin_addr, src, sizeof(struct in_addr)); | ||
| 544 | getnameinfo((struct sockaddr *)&in, sizeof(struct sockaddr_in), | ||
| 545 | dst, cnt, NULL, 0, NI_NUMERICHOST); | ||
| 546 | return dst; | ||
| 547 | } else if (af == AF_INET6) { | ||
| 548 | struct sockaddr_in6 in; | ||
| 549 | memset(&in, 0, sizeof(in)); | ||
| 550 | in.sin6_family = AF_INET6; | ||
| 551 | memcpy(&in.sin6_addr, src, sizeof(struct in_addr6)); | ||
| 552 | getnameinfo((struct sockaddr *)&in, sizeof(struct sockaddr_in6), | ||
| 553 | dst, cnt, NULL, 0, NI_NUMERICHOST); | ||
| 554 | return dst; | ||
| 555 | } | ||
| 556 | return NULL; | ||
| 557 | } | ||
| 558 | |||
| 559 | int inet_pton(int af, const char *src, void *dst) | ||
| 560 | { | ||
| 561 | struct addrinfo hints, *res, *ressave; | ||
| 562 | memset(&hints, 0, sizeof(struct addrinfo)); | ||
| 563 | hints.ai_family = af; | ||
| 564 | if (getaddrinfo(src, NULL, &hints, &res) != 0) { | ||
| 565 | return -1; | ||
| 566 | } | ||
| 567 | ressave = res; | ||
| 568 | while (res) { | ||
| 569 | memcpy(dst, res->ai_addr, res->ai_addrlen); | ||
| 570 | res = res->ai_next; | ||
| 571 | } | ||
| 572 | freeaddrinfo(ressave); | ||
| 573 | return 0; | ||
| 574 | } | ||
| 510 | 575 | ||
| 576 | #endif | ||
