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 | /*-------------------------------------------------------------------------*\ |