diff options
Diffstat (limited to 'src/udp.c')
-rw-r--r-- | src/udp.c | 57 |
1 files changed, 29 insertions, 28 deletions
@@ -27,6 +27,7 @@ | |||
27 | * Internal function prototypes | 27 | * Internal function prototypes |
28 | \*=========================================================================*/ | 28 | \*=========================================================================*/ |
29 | static int global_create(lua_State *L); | 29 | static int global_create(lua_State *L); |
30 | static int global_create4(lua_State *L); | ||
30 | static int global_create6(lua_State *L); | 31 | static int global_create6(lua_State *L); |
31 | static int meth_send(lua_State *L); | 32 | static int meth_send(lua_State *L); |
32 | static int meth_sendto(lua_State *L); | 33 | static int meth_sendto(lua_State *L); |
@@ -107,6 +108,7 @@ static t_opt optget[] = { | |||
107 | /* functions in library namespace */ | 108 | /* functions in library namespace */ |
108 | static luaL_Reg func[] = { | 109 | static luaL_Reg func[] = { |
109 | {"udp", global_create}, | 110 | {"udp", global_create}, |
111 | {"udp4", global_create4}, | ||
110 | {"udp6", global_create6}, | 112 | {"udp6", global_create6}, |
111 | {NULL, NULL} | 113 | {NULL, NULL} |
112 | }; | 114 | }; |
@@ -183,7 +185,7 @@ static int meth_sendto(lua_State *L) { | |||
183 | return 2; | 185 | return 2; |
184 | } | 186 | } |
185 | timeout_markstart(tm); | 187 | timeout_markstart(tm); |
186 | err = socket_sendto(&udp->sock, data, count, &sent, ai->ai_addr, | 188 | err = socket_sendto(&udp->sock, data, count, &sent, ai->ai_addr, |
187 | (socklen_t) ai->ai_addrlen, tm); | 189 | (socklen_t) ai->ai_addrlen, tm); |
188 | freeaddrinfo(ai); | 190 | freeaddrinfo(ai); |
189 | if (err != IO_DONE) { | 191 | if (err != IO_DONE) { |
@@ -235,7 +237,7 @@ static int meth_receivefrom(lua_State *L) | |||
235 | char portstr[6]; | 237 | char portstr[6]; |
236 | timeout_markstart(tm); | 238 | timeout_markstart(tm); |
237 | count = MIN(count, sizeof(buffer)); | 239 | count = MIN(count, sizeof(buffer)); |
238 | err = socket_recvfrom(&udp->sock, buffer, count, &got, (SA *) &addr, | 240 | err = socket_recvfrom(&udp->sock, buffer, count, &got, (SA *) &addr, |
239 | &addr_len, tm); | 241 | &addr_len, tm); |
240 | /* Unlike TCP, recv() of zero is not closed, but a zero-length packet. */ | 242 | /* Unlike TCP, recv() of zero is not closed, but a zero-length packet. */ |
241 | if (err == IO_CLOSED) | 243 | if (err == IO_CLOSED) |
@@ -245,7 +247,7 @@ static int meth_receivefrom(lua_State *L) | |||
245 | lua_pushstring(L, udp_strerror(err)); | 247 | lua_pushstring(L, udp_strerror(err)); |
246 | return 2; | 248 | return 2; |
247 | } | 249 | } |
248 | err = getnameinfo((struct sockaddr *)&addr, addr_len, addrstr, | 250 | err = getnameinfo((struct sockaddr *)&addr, addr_len, addrstr, |
249 | INET6_ADDRSTRLEN, portstr, 6, NI_NUMERICHOST | NI_NUMERICSERV); | 251 | INET6_ADDRSTRLEN, portstr, 6, NI_NUMERICHOST | NI_NUMERICSERV); |
250 | if (err) { | 252 | if (err) { |
251 | lua_pushnil(L); | 253 | lua_pushnil(L); |
@@ -264,7 +266,7 @@ static int meth_receivefrom(lua_State *L) | |||
264 | static int meth_getfamily(lua_State *L) | 266 | static int meth_getfamily(lua_State *L) |
265 | { | 267 | { |
266 | p_udp udp = (p_udp) auxiliar_checkgroup(L, "udp{any}", 1); | 268 | p_udp udp = (p_udp) auxiliar_checkgroup(L, "udp{any}", 1); |
267 | if (udp->family == PF_INET6) { | 269 | if (udp->family == AF_INET6) { |
268 | lua_pushliteral(L, "inet6"); | 270 | lua_pushliteral(L, "inet6"); |
269 | return 1; | 271 | return 1; |
270 | } else { | 272 | } else { |
@@ -349,7 +351,7 @@ static int meth_setpeername(lua_State *L) { | |||
349 | /* make sure we try to connect only to the same family */ | 351 | /* make sure we try to connect only to the same family */ |
350 | connecthints.ai_family = udp->family; | 352 | connecthints.ai_family = udp->family; |
351 | if (connecting) { | 353 | if (connecting) { |
352 | err = inet_tryconnect(&udp->sock, &udp->family, address, | 354 | err = inet_tryconnect(&udp->sock, &udp->family, address, |
353 | port, tm, &connecthints); | 355 | port, tm, &connecthints); |
354 | if (err) { | 356 | if (err) { |
355 | lua_pushnil(L); | 357 | lua_pushnil(L); |
@@ -363,7 +365,6 @@ static int meth_setpeername(lua_State *L) { | |||
363 | inet_trydisconnect(&udp->sock, udp->family, tm); | 365 | inet_trydisconnect(&udp->sock, udp->family, tm); |
364 | auxiliar_setclass(L, "udp{unconnected}", 1); | 366 | auxiliar_setclass(L, "udp{unconnected}", 1); |
365 | } | 367 | } |
366 | /* change class to connected or unconnected depending on address */ | ||
367 | lua_pushnumber(L, 1); | 368 | lua_pushnumber(L, 1); |
368 | return 1; | 369 | return 1; |
369 | } | 370 | } |
@@ -391,7 +392,7 @@ static int meth_setsockname(lua_State *L) { | |||
391 | bindhints.ai_socktype = SOCK_DGRAM; | 392 | bindhints.ai_socktype = SOCK_DGRAM; |
392 | bindhints.ai_family = udp->family; | 393 | bindhints.ai_family = udp->family; |
393 | bindhints.ai_flags = AI_PASSIVE; | 394 | bindhints.ai_flags = AI_PASSIVE; |
394 | err = inet_trybind(&udp->sock, address, port, &bindhints); | 395 | err = inet_trybind(&udp->sock, &udp->family, address, port, &bindhints); |
395 | if (err) { | 396 | if (err) { |
396 | lua_pushnil(L); | 397 | lua_pushnil(L); |
397 | lua_pushstring(L, err); | 398 | lua_pushstring(L, err); |
@@ -408,32 +409,32 @@ static int meth_setsockname(lua_State *L) { | |||
408 | * Creates a master udp object | 409 | * Creates a master udp object |
409 | \*-------------------------------------------------------------------------*/ | 410 | \*-------------------------------------------------------------------------*/ |
410 | static int udp_create(lua_State *L, int family) { | 411 | static int udp_create(lua_State *L, int family) { |
411 | t_socket sock; | 412 | /* allocate udp object */ |
412 | const char *err = inet_trycreate(&sock, family, SOCK_DGRAM); | 413 | p_udp udp = (p_udp) lua_newuserdata(L, sizeof(t_udp)); |
413 | /* try to allocate a system socket */ | 414 | auxiliar_setclass(L, "udp{unconnected}", -1); |
414 | if (!err) { | 415 | /* if family is AF_UNSPEC, we leave the socket invalid and |
415 | /* allocate udp object */ | 416 | * store AF_UNSPEC into family. This will allow it to later be |
416 | p_udp udp = (p_udp) lua_newuserdata(L, sizeof(t_udp)); | 417 | * replaced with an AF_INET6 or AF_INET socket upon first use. */ |
417 | auxiliar_setclass(L, "udp{unconnected}", -1); | 418 | udp->sock = SOCKET_INVALID; |
418 | /* initialize remaining structure fields */ | 419 | timeout_init(&udp->tm, -1, -1); |
419 | socket_setnonblocking(&sock); | 420 | udp->family = family; |
420 | if (family == PF_INET6) { | 421 | if (family != AF_UNSPEC) { |
421 | int yes = 1; | 422 | const char *err = inet_trycreate(&udp->sock, family, SOCK_DGRAM, 0); |
422 | setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, | 423 | if (err != NULL) { |
423 | (void *)&yes, sizeof(yes)); | 424 | lua_pushnil(L); |
425 | lua_pushstring(L, err); | ||
426 | return 2; | ||
424 | } | 427 | } |
425 | udp->sock = sock; | 428 | socket_setnonblocking(&udp->sock); |
426 | timeout_init(&udp->tm, -1, -1); | ||
427 | udp->family = family; | ||
428 | return 1; | ||
429 | } else { | ||
430 | lua_pushnil(L); | ||
431 | lua_pushstring(L, err); | ||
432 | return 2; | ||
433 | } | 429 | } |
430 | return 1; | ||
434 | } | 431 | } |
435 | 432 | ||
436 | static int global_create(lua_State *L) { | 433 | static int global_create(lua_State *L) { |
434 | return udp_create(L, AF_UNSPEC); | ||
435 | } | ||
436 | |||
437 | static int global_create4(lua_State *L) { | ||
437 | return udp_create(L, AF_INET); | 438 | return udp_create(L, AF_INET); |
438 | } | 439 | } |
439 | 440 | ||