diff options
| author | Florian Zeitz <florob@babelmonkeys.de> | 2011-06-14 01:17:07 +0200 |
|---|---|---|
| committer | Sam Roberts <vieuxtech@gmail.com> | 2012-04-11 13:33:34 -0700 |
| commit | 923eef192925cae29223974dbf1addd59b4b0f28 (patch) | |
| tree | fa8a9daf1b6acd5a7b9d0b6528d0aba8147ac8d0 /src/inet.c | |
| parent | 5c33ef99977587dd9ae4e013d2d43aa8bf493ad1 (diff) | |
| download | luasocket-923eef192925cae29223974dbf1addd59b4b0f28.tar.gz luasocket-923eef192925cae29223974dbf1addd59b4b0f28.tar.bz2 luasocket-923eef192925cae29223974dbf1addd59b4b0f28.zip | |
Rework binding IPv6 sockets by harmonizing it with the IPv4 variant
Diffstat (limited to 'src/inet.c')
| -rw-r--r-- | src/inet.c | 58 |
1 files changed, 34 insertions, 24 deletions
| @@ -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 | \*-------------------------------------------------------------------------*/ |
| 67 | static int inet_global_tohostname(lua_State *L) { | 67 | static 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) { | |||
| 85 | static int inet_global_toip(lua_State *L) | 85 | static 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 | \*-------------------------------------------------------------------------*/ |
| 247 | const char *inet_trycreate(p_socket ps, int type) { | 247 | const 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 | \*-------------------------------------------------------------------------*/ |
| 254 | const char *inet_tryconnect(p_socket ps, const char *address, | 254 | const 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 | \*-------------------------------------------------------------------------*/ |
| 279 | const char *inet_trybind(p_socket ps, const char *address, unsigned short port) | 279 | const 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 | /*-------------------------------------------------------------------------*\ |
