From a6cf48596d421c5dcc61b745dde73e3265876f69 Mon Sep 17 00:00:00 2001 From: Florian Zeitz Date: Tue, 17 Jul 2012 19:02:20 +0200 Subject: [PATCH 1/2] Add IPv6 support to udp:sendto() --- src/udp.c | 39 ++++++++++++++++++++++++++++++--------- 1 file changed, 30 insertions(+), 9 deletions(-) diff --git a/src/udp.c b/src/udp.c index 0241cc5..e65e07a 100644 --- a/src/udp.c +++ b/src/udp.c @@ -153,16 +153,37 @@ static int meth_sendto(lua_State *L) { const char *ip = luaL_checkstring(L, 3); unsigned short port = (unsigned short) luaL_checknumber(L, 4); p_timeout tm = &udp->tm; - struct sockaddr_in addr; int err; - memset(&addr, 0, sizeof(addr)); - if (!inet_aton(ip, &addr.sin_addr)) - luaL_argerror(L, 3, "invalid ip address"); - addr.sin_family = AF_INET; - addr.sin_port = htons(port); - timeout_markstart(tm); - err = socket_sendto(&udp->sock, data, count, &sent, - (SA *) &addr, sizeof(addr), tm); + switch (udp->family) { + case PF_INET: { + struct sockaddr_in addr; + memset(&addr, 0, sizeof(addr)); + if (!inet_pton(AF_INET, ip, &addr.sin_addr)) + luaL_argerror(L, 3, "invalid ip address"); + addr.sin_family = AF_INET; + addr.sin_port = htons(port); + timeout_markstart(tm); + err = socket_sendto(&udp->sock, data, count, &sent, + (SA *) &addr, sizeof(addr), tm); + break; + } + case PF_INET6: { + struct sockaddr_in6 addr; + memset(&addr, 0, sizeof(addr)); + if (!inet_pton(AF_INET6, ip, &addr.sin6_addr)) + luaL_argerror(L, 3, "invalid ip address"); + addr.sin6_family = AF_INET6; + addr.sin6_port = htons(port); + timeout_markstart(tm); + err = socket_sendto(&udp->sock, data, count, &sent, + (SA *) &addr, sizeof(addr), tm); + break; + } + default: + lua_pushnil(L); + lua_pushfstring(L, "unknown family %d", udp->family); + return 2; + } if (err != IO_DONE) { lua_pushnil(L); lua_pushstring(L, udp_strerror(err)); From 7503bb0ca3f4f6216d48185d7a92e6ba5ef6d124 Mon Sep 17 00:00:00 2001 From: Florian Zeitz Date: Wed, 18 Jul 2012 21:05:30 +0200 Subject: [PATCH 2/2] Add IPv6 support to udp:receivefrom() --- src/udp.c | 70 ++++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 54 insertions(+), 16 deletions(-) diff --git a/src/udp.c b/src/udp.c index e65e07a..bdf584b 100644 --- a/src/udp.c +++ b/src/udp.c @@ -222,29 +222,67 @@ static int meth_receive(lua_State *L) { \*-------------------------------------------------------------------------*/ static int meth_receivefrom(lua_State *L) { p_udp udp = (p_udp) auxiliar_checkclass(L, "udp{unconnected}", 1); - struct sockaddr_in addr; - socklen_t addr_len = sizeof(addr); char buffer[UDP_DATAGRAMSIZE]; size_t got, count = (size_t) luaL_optnumber(L, 2, sizeof(buffer)); int err; p_timeout tm = &udp->tm; timeout_markstart(tm); count = MIN(count, sizeof(buffer)); - err = socket_recvfrom(&udp->sock, buffer, count, &got, - (SA *) &addr, &addr_len, tm); - /* Unlike TCP, recv() of zero is not closed, but a zero-length packet. */ - if (err == IO_CLOSED) - err = IO_DONE; - if (err == IO_DONE) { - lua_pushlstring(L, buffer, got); - lua_pushstring(L, inet_ntoa(addr.sin_addr)); - lua_pushnumber(L, ntohs(addr.sin_port)); - return 3; - } else { - lua_pushnil(L); - lua_pushstring(L, udp_strerror(err)); - return 2; + switch (udp->family) { + case PF_INET: { + struct sockaddr_in addr; + socklen_t addr_len = sizeof(addr); + err = socket_recvfrom(&udp->sock, buffer, count, &got, + (SA *) &addr, &addr_len, tm); + /* Unlike TCP, recv() of zero is not closed, but a zero-length packet. */ + if (err == IO_CLOSED) + err = IO_DONE; + if (err == IO_DONE) { + char addrstr[INET_ADDRSTRLEN]; + lua_pushlstring(L, buffer, got); + if (!inet_ntop(AF_INET, &addr.sin_addr, + addrstr, sizeof(addrstr))) { + lua_pushnil(L); + lua_pushstring(L, "invalid source address"); + return 2; + } + lua_pushstring(L, addrstr); + lua_pushnumber(L, ntohs(addr.sin_port)); + return 3; + } + break; + } + case PF_INET6: { + struct sockaddr_in6 addr; + socklen_t addr_len = sizeof(addr); + err = socket_recvfrom(&udp->sock, buffer, count, &got, + (SA *) &addr, &addr_len, tm); + /* Unlike TCP, recv() of zero is not closed, but a zero-length packet. */ + if (err == IO_CLOSED) + err = IO_DONE; + if (err == IO_DONE) { + char addrstr[INET6_ADDRSTRLEN]; + lua_pushlstring(L, buffer, got); + if (!inet_ntop(AF_INET6, &addr.sin6_addr, + addrstr, sizeof(addrstr))) { + lua_pushnil(L); + lua_pushstring(L, "invalid source address"); + return 2; + } + lua_pushstring(L, addrstr); + lua_pushnumber(L, ntohs(addr.sin6_port)); + return 3; + } + break; + } + default: + lua_pushnil(L); + lua_pushfstring(L, "unknown family %d", udp->family); + return 2; } + lua_pushnil(L); + lua_pushstring(L, udp_strerror(err)); + return 2; } /*-------------------------------------------------------------------------*\