Add IPv6 support to udp:receivefrom()

This commit is contained in:
Florian Zeitz 2012-07-18 21:05:30 +02:00
parent a6cf48596d
commit 7503bb0ca3

View File

@ -222,30 +222,68 @@ 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));
switch (udp->family) {
case PF_INET: {
struct sockaddr_in addr;
socklen_t addr_len = sizeof(addr);
err = socket_recvfrom(&udp->sock, buffer, count, &got, err = socket_recvfrom(&udp->sock, buffer, count, &got,
(SA *) &addr, &addr_len, tm); (SA *) &addr, &addr_len, tm);
/* Unlike TCP, recv() of zero is not closed, but a zero-length packet. */ /* Unlike TCP, recv() of zero is not closed, but a zero-length packet. */
if (err == IO_CLOSED) if (err == IO_CLOSED)
err = IO_DONE; err = IO_DONE;
if (err == IO_DONE) { if (err == IO_DONE) {
char addrstr[INET_ADDRSTRLEN];
lua_pushlstring(L, buffer, got); lua_pushlstring(L, buffer, got);
lua_pushstring(L, inet_ntoa(addr.sin_addr)); 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)); lua_pushnumber(L, ntohs(addr.sin_port));
return 3; return 3;
} else { }
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_pushnil(L);
lua_pushstring(L, udp_strerror(err)); lua_pushstring(L, udp_strerror(err));
return 2; return 2;
} }
}
/*-------------------------------------------------------------------------*\ /*-------------------------------------------------------------------------*\
* Returns family as string * Returns family as string