aboutsummaryrefslogtreecommitdiff
path: root/src/inet.c
diff options
context:
space:
mode:
authorSam Roberts <vieuxtech@gmail.com>2012-05-10 14:14:22 -0700
committerSam Roberts <vieuxtech@gmail.com>2012-05-10 14:14:22 -0700
commit156669c28bc62bfddbd5625c4bb4c1f8da94802b (patch)
tree074ea57dd044a9bed306464af8c9f141bdf0ca19 /src/inet.c
parent3d3e69c6e43f6431969e072e78df43b0ab73c48d (diff)
downloadluasocket-156669c28bc62bfddbd5625c4bb4c1f8da94802b.tar.gz
luasocket-156669c28bc62bfddbd5625c4bb4c1f8da94802b.tar.bz2
luasocket-156669c28bc62bfddbd5625c4bb4c1f8da94802b.zip
socket.connect now implemented in the C core
This avoid socket.lua duplicating the iteration over the results of getaddrinfo(). Some problems with the C implementation not initializing sockets or the luasocket family have also been fixed, and error reporting made more robust.
Diffstat (limited to 'src/inet.c')
-rw-r--r--src/inet.c54
1 files changed, 42 insertions, 12 deletions
diff --git a/src/inet.c b/src/inet.c
index 55e89d7..e769cd8 100644
--- a/src/inet.c
+++ b/src/inet.c
@@ -143,6 +143,22 @@ static int inet_global_toip(lua_State *L)
143 return 2; 143 return 2;
144} 144}
145 145
146int 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
154int 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
146static int inet_global_getaddrinfo(lua_State *L) 162static 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