Merge pull request #20 from Florob/sendto

IPv6 support for udp:sendto() and udp:receivefrom()
This commit is contained in:
Diego Nehab 2012-07-31 22:04:06 -07:00
commit 6370b61414

109
src/udp.c
View File

@ -153,16 +153,37 @@ static int meth_sendto(lua_State *L) {
const char *ip = luaL_checkstring(L, 3); const char *ip = luaL_checkstring(L, 3);
unsigned short port = (unsigned short) luaL_checknumber(L, 4); unsigned short port = (unsigned short) luaL_checknumber(L, 4);
p_timeout tm = &udp->tm; p_timeout tm = &udp->tm;
struct sockaddr_in addr;
int err; int err;
memset(&addr, 0, sizeof(addr)); switch (udp->family) {
if (!inet_aton(ip, &addr.sin_addr)) case PF_INET: {
luaL_argerror(L, 3, "invalid ip address"); struct sockaddr_in addr;
addr.sin_family = AF_INET; memset(&addr, 0, sizeof(addr));
addr.sin_port = htons(port); if (!inet_pton(AF_INET, ip, &addr.sin_addr))
timeout_markstart(tm); luaL_argerror(L, 3, "invalid ip address");
err = socket_sendto(&udp->sock, data, count, &sent, addr.sin_family = AF_INET;
(SA *) &addr, sizeof(addr), tm); 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) { if (err != IO_DONE) {
lua_pushnil(L); lua_pushnil(L);
lua_pushstring(L, udp_strerror(err)); lua_pushstring(L, udp_strerror(err));
@ -201,29 +222,67 @@ static int meth_receive(lua_State *L) {
\*-------------------------------------------------------------------------*/ \*-------------------------------------------------------------------------*/
static int meth_receivefrom(lua_State *L) { static int meth_receivefrom(lua_State *L) {
p_udp udp = (p_udp) auxiliar_checkclass(L, "udp{unconnected}", 1); 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]; char buffer[UDP_DATAGRAMSIZE];
size_t got, count = (size_t) luaL_optnumber(L, 2, sizeof(buffer)); size_t got, count = (size_t) luaL_optnumber(L, 2, sizeof(buffer));
int err; int err;
p_timeout tm = &udp->tm; p_timeout tm = &udp->tm;
timeout_markstart(tm); timeout_markstart(tm);
count = MIN(count, sizeof(buffer)); count = MIN(count, sizeof(buffer));
err = socket_recvfrom(&udp->sock, buffer, count, &got, switch (udp->family) {
(SA *) &addr, &addr_len, tm); case PF_INET: {
/* Unlike TCP, recv() of zero is not closed, but a zero-length packet. */ struct sockaddr_in addr;
if (err == IO_CLOSED) socklen_t addr_len = sizeof(addr);
err = IO_DONE; err = socket_recvfrom(&udp->sock, buffer, count, &got,
if (err == IO_DONE) { (SA *) &addr, &addr_len, tm);
lua_pushlstring(L, buffer, got); /* Unlike TCP, recv() of zero is not closed, but a zero-length packet. */
lua_pushstring(L, inet_ntoa(addr.sin_addr)); if (err == IO_CLOSED)
lua_pushnumber(L, ntohs(addr.sin_port)); err = IO_DONE;
return 3; if (err == IO_DONE) {
} else { char addrstr[INET_ADDRSTRLEN];
lua_pushnil(L); lua_pushlstring(L, buffer, got);
lua_pushstring(L, udp_strerror(err)); if (!inet_ntop(AF_INET, &addr.sin_addr,
return 2; 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;
} }
/*-------------------------------------------------------------------------*\ /*-------------------------------------------------------------------------*\