diff options
Diffstat (limited to 'src/inet.c')
| -rw-r--r-- | src/inet.c | 54 |
1 files changed, 42 insertions, 12 deletions
| @@ -143,6 +143,22 @@ static int inet_global_toip(lua_State *L) | |||
| 143 | return 2; | 143 | return 2; |
| 144 | } | 144 | } |
| 145 | 145 | ||
| 146 | int inet_optfamily(lua_State* L, int narg, const char* def) | ||
| 147 | { | ||
| 148 | static const char* optname[] = { "unspec", "inet", "inet6", NULL }; | ||
| 149 | static int optvalue[] = { PF_UNSPEC, PF_INET, PF_INET6, 0 }; | ||
| 150 | |||
| 151 | return optvalue[luaL_checkoption(L, narg, def, optname)]; | ||
| 152 | } | ||
| 153 | |||
| 154 | int inet_optsocktype(lua_State* L, int narg, const char* def) | ||
| 155 | { | ||
| 156 | static const char* optname[] = { "stream", "dgram", NULL }; | ||
| 157 | static int optvalue[] = { SOCK_STREAM, SOCK_DGRAM, 0 }; | ||
| 158 | |||
| 159 | return optvalue[luaL_checkoption(L, narg, def, optname)]; | ||
| 160 | } | ||
| 161 | |||
| 146 | static int inet_global_getaddrinfo(lua_State *L) | 162 | static int inet_global_getaddrinfo(lua_State *L) |
| 147 | { | 163 | { |
| 148 | const char *hostname = luaL_checkstring(L, 1); | 164 | const char *hostname = luaL_checkstring(L, 1); |
| @@ -197,7 +213,7 @@ static int inet_global_gethostname(lua_State *L) | |||
| 197 | name[256] = '\0'; | 213 | name[256] = '\0'; |
| 198 | if (gethostname(name, 256) < 0) { | 214 | if (gethostname(name, 256) < 0) { |
| 199 | lua_pushnil(L); | 215 | lua_pushnil(L); |
| 200 | lua_pushstring(L, "gethostname failed"); | 216 | lua_pushstring(L, socket_strerror(errno)); |
| 201 | return 2; | 217 | return 2; |
| 202 | } else { | 218 | } else { |
| 203 | lua_pushstring(L, name); | 219 | lua_pushstring(L, name); |
| @@ -222,7 +238,7 @@ int inet_meth_getpeername(lua_State *L, p_socket ps, int family) | |||
| 222 | char name[INET_ADDRSTRLEN]; | 238 | char name[INET_ADDRSTRLEN]; |
| 223 | if (getpeername(*ps, (SA *) &peer, &peer_len) < 0) { | 239 | if (getpeername(*ps, (SA *) &peer, &peer_len) < 0) { |
| 224 | lua_pushnil(L); | 240 | lua_pushnil(L); |
| 225 | lua_pushstring(L, "getpeername failed"); | 241 | lua_pushstring(L, socket_strerror(errno)); |
| 226 | return 2; | 242 | return 2; |
| 227 | } else { | 243 | } else { |
| 228 | inet_ntop(family, &peer.sin_addr, name, sizeof(name)); | 244 | inet_ntop(family, &peer.sin_addr, name, sizeof(name)); |
| @@ -238,7 +254,7 @@ int inet_meth_getpeername(lua_State *L, p_socket ps, int family) | |||
| 238 | char name[INET6_ADDRSTRLEN]; | 254 | char name[INET6_ADDRSTRLEN]; |
| 239 | if (getpeername(*ps, (SA *) &peer, &peer_len) < 0) { | 255 | if (getpeername(*ps, (SA *) &peer, &peer_len) < 0) { |
| 240 | lua_pushnil(L); | 256 | lua_pushnil(L); |
| 241 | lua_pushstring(L, "getpeername failed"); | 257 | lua_pushstring(L, socket_strerror(errno)); |
| 242 | return 2; | 258 | return 2; |
| 243 | } else { | 259 | } else { |
| 244 | inet_ntop(family, &peer.sin6_addr, name, sizeof(name)); | 260 | inet_ntop(family, &peer.sin6_addr, name, sizeof(name)); |
| @@ -251,7 +267,7 @@ int inet_meth_getpeername(lua_State *L, p_socket ps, int family) | |||
| 251 | } | 267 | } |
| 252 | default: | 268 | default: |
| 253 | lua_pushnil(L); | 269 | lua_pushnil(L); |
| 254 | lua_pushstring(L, "unknown family"); | 270 | lua_pushfstring(L, "unknown family %d", family); |
| 255 | return 2; | 271 | return 2; |
| 256 | } | 272 | } |
| 257 | } | 273 | } |
| @@ -268,7 +284,7 @@ int inet_meth_getsockname(lua_State *L, p_socket ps, int family) | |||
| 268 | char name[INET_ADDRSTRLEN]; | 284 | char name[INET_ADDRSTRLEN]; |
| 269 | if (getsockname(*ps, (SA *) &local, &local_len) < 0) { | 285 | if (getsockname(*ps, (SA *) &local, &local_len) < 0) { |
| 270 | lua_pushnil(L); | 286 | lua_pushnil(L); |
| 271 | lua_pushstring(L, "getsockname failed"); | 287 | lua_pushstring(L, socket_strerror(errno)); |
| 272 | return 2; | 288 | return 2; |
| 273 | } else { | 289 | } else { |
| 274 | inet_ntop(family, &local.sin_addr, name, sizeof(name)); | 290 | inet_ntop(family, &local.sin_addr, name, sizeof(name)); |
| @@ -284,7 +300,7 @@ int inet_meth_getsockname(lua_State *L, p_socket ps, int family) | |||
| 284 | char name[INET6_ADDRSTRLEN]; | 300 | char name[INET6_ADDRSTRLEN]; |
| 285 | if (getsockname(*ps, (SA *) &local, &local_len) < 0) { | 301 | if (getsockname(*ps, (SA *) &local, &local_len) < 0) { |
| 286 | lua_pushnil(L); | 302 | lua_pushnil(L); |
| 287 | lua_pushstring(L, "getsockname failed"); | 303 | lua_pushstring(L, socket_strerror(errno)); |
| 288 | return 2; | 304 | return 2; |
| 289 | } else { | 305 | } else { |
| 290 | inet_ntop(family, &local.sin6_addr, name, sizeof(name)); | 306 | inet_ntop(family, &local.sin6_addr, name, sizeof(name)); |
| @@ -296,7 +312,7 @@ int inet_meth_getsockname(lua_State *L, p_socket ps, int family) | |||
| 296 | } | 312 | } |
| 297 | default: | 313 | default: |
| 298 | lua_pushnil(L); | 314 | lua_pushnil(L); |
| 299 | lua_pushstring(L, "unknown family"); | 315 | lua_pushfstring(L, "unknown family %d", family); |
| 300 | return 2; | 316 | return 2; |
| 301 | } | 317 | } |
| 302 | } | 318 | } |
| @@ -390,6 +406,7 @@ const char *inet_trybind(p_socket ps, const char *address, const char *serv, | |||
| 390 | { | 406 | { |
| 391 | struct addrinfo *iterator = NULL, *resolved = NULL; | 407 | struct addrinfo *iterator = NULL, *resolved = NULL; |
| 392 | const char *err = NULL; | 408 | const char *err = NULL; |
| 409 | t_socket sock = *ps; | ||
| 393 | /* translate luasocket special values to C */ | 410 | /* translate luasocket special values to C */ |
| 394 | if (strcmp(address, "*") == 0) address = NULL; | 411 | if (strcmp(address, "*") == 0) address = NULL; |
| 395 | if (!serv) serv = "0"; | 412 | if (!serv) serv = "0"; |
| @@ -402,17 +419,30 @@ const char *inet_trybind(p_socket ps, const char *address, const char *serv, | |||
| 402 | } | 419 | } |
| 403 | /* iterate over resolved addresses until one is good */ | 420 | /* iterate over resolved addresses until one is good */ |
| 404 | for (iterator = resolved; iterator; iterator = iterator->ai_next) { | 421 | for (iterator = resolved; iterator; iterator = iterator->ai_next) { |
| 422 | if(sock == SOCKET_INVALID) { | ||
| 423 | err = socket_strerror( socket_create(&sock, iterator->ai_family, | ||
| 424 | iterator->ai_socktype, iterator->ai_protocol)); | ||
| 425 | if(err) | ||
| 426 | continue; | ||
| 427 | } | ||
| 405 | /* try binding to local address */ | 428 | /* try binding to local address */ |
| 406 | err = socket_strerror(socket_bind(ps, | 429 | err = socket_strerror(socket_bind(&sock, |
| 407 | (SA *) iterator->ai_addr, | 430 | (SA *) iterator->ai_addr, |
| 408 | iterator->ai_addrlen)); | 431 | iterator->ai_addrlen)); |
| 409 | /* if faiiled, we try the next one */ | 432 | |
| 410 | if (err != NULL) socket_destroy(ps); | 433 | /* keep trying unless bind succeeded */ |
| 411 | /* if success, we abort loop */ | 434 | if (err) { |
| 412 | else break; | 435 | if(sock != *ps) |
| 436 | socket_destroy(&sock); | ||
| 437 | } else { | ||
| 438 | /* remember what we connected to, particularly the family */ | ||
| 439 | *bindhints = *iterator; | ||
| 440 | break; | ||
| 441 | } | ||
| 413 | } | 442 | } |
| 414 | /* cleanup and return error */ | 443 | /* cleanup and return error */ |
| 415 | freeaddrinfo(resolved); | 444 | freeaddrinfo(resolved); |
| 445 | *ps = sock; | ||
| 416 | return err; | 446 | return err; |
| 417 | } | 447 | } |
| 418 | 448 | ||
