aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFlorian Zeitz <florob@babelmonkeys.de>2012-07-18 21:05:30 +0200
committerFlorian Zeitz <florob@babelmonkeys.de>2012-07-18 21:05:30 +0200
commit7503bb0ca3f4f6216d48185d7a92e6ba5ef6d124 (patch)
tree6cc3bfa29d5af665ed805c80620be4db7a41cf7f
parenta6cf48596d421c5dcc61b745dde73e3265876f69 (diff)
downloadluasocket-7503bb0ca3f4f6216d48185d7a92e6ba5ef6d124.tar.gz
luasocket-7503bb0ca3f4f6216d48185d7a92e6ba5ef6d124.tar.bz2
luasocket-7503bb0ca3f4f6216d48185d7a92e6ba5ef6d124.zip
Add IPv6 support to udp:receivefrom()
-rw-r--r--src/udp.c70
1 files 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) {
222\*-------------------------------------------------------------------------*/ 222\*-------------------------------------------------------------------------*/
223static int meth_receivefrom(lua_State *L) { 223static int meth_receivefrom(lua_State *L) {
224 p_udp udp = (p_udp) auxiliar_checkclass(L, "udp{unconnected}", 1); 224 p_udp udp = (p_udp) auxiliar_checkclass(L, "udp{unconnected}", 1);
225 struct sockaddr_in addr;
226 socklen_t addr_len = sizeof(addr);
227 char buffer[UDP_DATAGRAMSIZE]; 225 char buffer[UDP_DATAGRAMSIZE];
228 size_t got, count = (size_t) luaL_optnumber(L, 2, sizeof(buffer)); 226 size_t got, count = (size_t) luaL_optnumber(L, 2, sizeof(buffer));
229 int err; 227 int err;
230 p_timeout tm = &udp->tm; 228 p_timeout tm = &udp->tm;
231 timeout_markstart(tm); 229 timeout_markstart(tm);
232 count = MIN(count, sizeof(buffer)); 230 count = MIN(count, sizeof(buffer));
233 err = socket_recvfrom(&udp->sock, buffer, count, &got, 231 switch (udp->family) {
234 (SA *) &addr, &addr_len, tm); 232 case PF_INET: {
235 /* Unlike TCP, recv() of zero is not closed, but a zero-length packet. */ 233 struct sockaddr_in addr;
236 if (err == IO_CLOSED) 234 socklen_t addr_len = sizeof(addr);
237 err = IO_DONE; 235 err = socket_recvfrom(&udp->sock, buffer, count, &got,
238 if (err == IO_DONE) { 236 (SA *) &addr, &addr_len, tm);
239 lua_pushlstring(L, buffer, got); 237 /* Unlike TCP, recv() of zero is not closed, but a zero-length packet. */
240 lua_pushstring(L, inet_ntoa(addr.sin_addr)); 238 if (err == IO_CLOSED)
241 lua_pushnumber(L, ntohs(addr.sin_port)); 239 err = IO_DONE;
242 return 3; 240 if (err == IO_DONE) {
243 } else { 241 char addrstr[INET_ADDRSTRLEN];
244 lua_pushnil(L); 242 lua_pushlstring(L, buffer, got);
245 lua_pushstring(L, udp_strerror(err)); 243 if (!inet_ntop(AF_INET, &addr.sin_addr,
246 return 2; 244 addrstr, sizeof(addrstr))) {
245 lua_pushnil(L);
246 lua_pushstring(L, "invalid source address");
247 return 2;
248 }
249 lua_pushstring(L, addrstr);
250 lua_pushnumber(L, ntohs(addr.sin_port));
251 return 3;
252 }
253 break;
254 }
255 case PF_INET6: {
256 struct sockaddr_in6 addr;
257 socklen_t addr_len = sizeof(addr);
258 err = socket_recvfrom(&udp->sock, buffer, count, &got,
259 (SA *) &addr, &addr_len, tm);
260 /* Unlike TCP, recv() of zero is not closed, but a zero-length packet. */
261 if (err == IO_CLOSED)
262 err = IO_DONE;
263 if (err == IO_DONE) {
264 char addrstr[INET6_ADDRSTRLEN];
265 lua_pushlstring(L, buffer, got);
266 if (!inet_ntop(AF_INET6, &addr.sin6_addr,
267 addrstr, sizeof(addrstr))) {
268 lua_pushnil(L);
269 lua_pushstring(L, "invalid source address");
270 return 2;
271 }
272 lua_pushstring(L, addrstr);
273 lua_pushnumber(L, ntohs(addr.sin6_port));
274 return 3;
275 }
276 break;
277 }
278 default:
279 lua_pushnil(L);
280 lua_pushfstring(L, "unknown family %d", udp->family);
281 return 2;
247 } 282 }
283 lua_pushnil(L);
284 lua_pushstring(L, udp_strerror(err));
285 return 2;
248} 286}
249 287
250/*-------------------------------------------------------------------------*\ 288/*-------------------------------------------------------------------------*\