From a233e27865d96566a6cb13960d08605ce34d9f0d Mon Sep 17 00:00:00 2001 From: Diego Nehab Date: Thu, 30 May 2013 16:20:34 +0800 Subject: [PATCH] Leaving if in src/ but out of build for now. --- README | 11 +++- src/inet.c | 131 +++++++++++++++++------------------------ src/makefile | 16 ++--- src/options.c | 135 ++++++++++++++++++++++++++++++++++++++---- src/options.h | 9 +++ src/serial.c | 1 + src/udp.c | 159 +++++++++++++++++++------------------------------- src/unix.c | 1 + 8 files changed, 266 insertions(+), 197 deletions(-) diff --git a/README b/README index e9dc323..d3529e1 100644 --- a/README +++ b/README @@ -1,6 +1,11 @@ -This is the LuaSocket 2.1. It has been tested on --[[WinXP--]], Mac OS X, -and --[[Linux--]]. Please use the Lua mailing list to report any bugs -(or "features") you encounter. +This is the LuaSocket 2.1. It has been tested on Windows 7, Mac OS X, +and Linux. + +Please use the project page at GitHub + + https://github.com/diegonehab/luasocket + +to file bug reports or propose changes. Have fun, Diego Nehab. diff --git a/src/inet.c b/src/inet.c index 35bc438..50b3e5c 100644 --- a/src/inet.c +++ b/src/inet.c @@ -3,6 +3,7 @@ * LuaSocket toolkit \*=========================================================================*/ #include +#include #include #include "lua.h" @@ -227,7 +228,6 @@ static int inet_global_gethostname(lua_State *L) } } - /*=========================================================================*\ * Lua methods \*=========================================================================*/ @@ -236,44 +236,33 @@ static int inet_global_gethostname(lua_State *L) \*-------------------------------------------------------------------------*/ int inet_meth_getpeername(lua_State *L, p_socket ps, int family) { - switch (family) { - case PF_INET: { - struct sockaddr_in peer; - socklen_t peer_len = sizeof(peer); - char name[INET_ADDRSTRLEN]; - if (getpeername(*ps, (SA *) &peer, &peer_len) < 0) { - lua_pushnil(L); - lua_pushstring(L, socket_strerror(errno)); - return 2; - } else { - inet_ntop(family, &peer.sin_addr, name, sizeof(name)); - lua_pushstring(L, name); - lua_pushnumber(L, ntohs(peer.sin_port)); - lua_pushliteral(L, "inet"); - return 3; - } - } - case PF_INET6: { - struct sockaddr_in6 peer; - socklen_t peer_len = sizeof(peer); - char name[INET6_ADDRSTRLEN]; - if (getpeername(*ps, (SA *) &peer, &peer_len) < 0) { - lua_pushnil(L); - lua_pushstring(L, socket_strerror(errno)); - return 2; - } else { - inet_ntop(family, &peer.sin6_addr, name, sizeof(name)); - lua_pushstring(L, name); - lua_pushnumber(L, ntohs(peer.sin6_port)); - lua_pushliteral(L, "inet6"); - return 3; - } - } - default: - lua_pushnil(L); - lua_pushfstring(L, "unknown family %d", family); - return 2; + int err; + struct sockaddr_storage peer; + socklen_t peer_len = sizeof(peer); + char name[INET6_ADDRSTRLEN]; + char port[6]; /* 65535 = 5 bytes + 0 to terminate it */ + if (getpeername(*ps, (SA *) &peer, &peer_len) < 0) { + lua_pushnil(L); + lua_pushstring(L, socket_strerror(errno)); + return 2; } + if ((err = getnameinfo((struct sockaddr *) &peer, peer_len, + name, INET6_ADDRSTRLEN, + port, sizeof(port), NI_NUMERICHOST | NI_NUMERICSERV))) { + lua_pushnil(L); + lua_pushstring(L, gai_strerror(err)); + return 2; + } + lua_pushstring(L, name); + lua_pushinteger(L, (int) strtol(port, (char **) NULL, 10)); + if (family == PF_INET) { + lua_pushliteral(L, "inet"); + } else if (family == PF_INET6) { + lua_pushliteral(L, "inet6"); + } else { + lua_pushliteral(L, "uknown family"); + } + return 3; } /*-------------------------------------------------------------------------*\ @@ -281,44 +270,33 @@ int inet_meth_getpeername(lua_State *L, p_socket ps, int family) \*-------------------------------------------------------------------------*/ int inet_meth_getsockname(lua_State *L, p_socket ps, int family) { - switch (family) { - case PF_INET: { - struct sockaddr_in local; - socklen_t local_len = sizeof(local); - char name[INET_ADDRSTRLEN]; - if (getsockname(*ps, (SA *) &local, &local_len) < 0) { - lua_pushnil(L); - lua_pushstring(L, socket_strerror(errno)); - return 2; - } else { - inet_ntop(family, &local.sin_addr, name, sizeof(name)); - lua_pushstring(L, name); - lua_pushnumber(L, ntohs(local.sin_port)); - lua_pushliteral(L, "inet"); - return 3; - } - } - case PF_INET6: { - struct sockaddr_in6 local; - socklen_t local_len = sizeof(local); - char name[INET6_ADDRSTRLEN]; - if (getsockname(*ps, (SA *) &local, &local_len) < 0) { - lua_pushnil(L); - lua_pushstring(L, socket_strerror(errno)); - return 2; - } else { - inet_ntop(family, &local.sin6_addr, name, sizeof(name)); - lua_pushstring(L, name); - lua_pushnumber(L, ntohs(local.sin6_port)); - lua_pushliteral(L, "inet6"); - return 3; - } - } - default: - lua_pushnil(L); - lua_pushfstring(L, "unknown family %d", family); - return 2; + int err; + struct sockaddr_storage peer; + socklen_t peer_len = sizeof(peer); + char name[INET6_ADDRSTRLEN]; + char port[6]; /* 65535 = 5 bytes + 0 to terminate it */ + if (getsockname(*ps, (SA *) &peer, &peer_len) < 0) { + lua_pushnil(L); + lua_pushstring(L, socket_strerror(errno)); + return 2; } + if ((err=getnameinfo((struct sockaddr *)&peer, peer_len, + name, INET6_ADDRSTRLEN, + port, 6, NI_NUMERICHOST | NI_NUMERICSERV))) { + lua_pushnil(L); + lua_pushstring(L, gai_strerror(err)); + return 2; + } + lua_pushstring(L, name); + lua_pushstring(L, port); + if (family == PF_INET) { + lua_pushliteral(L, "inet"); + } else if (family == PF_INET6) { + lua_pushliteral(L, "inet6"); + } else { + lua_pushliteral(L, "uknown family"); + } + return 3; } /*=========================================================================*\ @@ -456,7 +434,8 @@ const char *inet_tryaccept(p_socket server, int family, p_socket client, } else { len = sizeof(struct sockaddr_in); } - return socket_strerror(socket_accept(server, client, (SA *) &addr, &len, tm)); + return socket_strerror(socket_accept(server, client, (SA *) &addr, + &len, tm)); } /*-------------------------------------------------------------------------*\ diff --git a/src/makefile b/src/makefile index 42589f6..f7b0401 100644 --- a/src/makefile +++ b/src/makefile @@ -30,7 +30,7 @@ DEBUG?=NODEBUG COMPAT?=NOCOMPAT # where lua headers are found for macosx builds -# LUAINC_macosx: +# LUAINC_macosx: # /opt/local/include LUAINC_macosx_base?=/opt/local/include LUAINC_macosx?=$(LUAINC_macosx_base)/lua/$(LUAV) @@ -41,9 +41,9 @@ CDIR_macosx?=lib/lua/$(LUAV) LDIR_macosx?=share/lua/$(LUAV) -# LUAINC_linux: -# /usr/include/lua$(LUAV) -# /usr/local/include +# LUAINC_linux: +# /usr/include/lua$(LUAV) +# /usr/local/include # /usr/local/include/lua$(LUAV) # where lua headers are found for linux builds LUAINC_linux_base?=/usr/include @@ -134,7 +134,7 @@ DEF_macosx= -DLUASOCKET_$(DEBUG) -DUNIX_HAS_SUN_LEN -DLUA_$(COMPAT)_MODULE \ -DMIME_API='__attribute__((visibility("default")))' CFLAGS_macosx= -I$(LUAINC) $(DEF) -pedantic -Wall -O2 -fno-common \ -fvisibility=hidden -LDFLAGS_macosx= -bundle -undefined dynamic_lookup -o +LDFLAGS_macosx= -bundle -undefined dynamic_lookup -o LD_macosx= export MACOSX_DEPLOYMENT_TARGET="10.3"; gcc SOCKET_macosx=usocket.o @@ -308,15 +308,15 @@ none: all: $(SOCKET_SO) $(MIME_SO) $(SOCKET_SO): $(SOCKET_OBJS) - $(LD) $(SOCKET_OBJS) $(LDFLAGS)$@ + $(LD) $(SOCKET_OBJS) $(LDFLAGS)$@ $(MIME_SO): $(MIME_OBJS) - $(LD) $(MIME_OBJS) $(LDFLAGS)$@ + $(LD) $(MIME_OBJS) $(LDFLAGS)$@ all-unix: all $(UNIX_SO) $(SERIAL_SO) $(UNIX_SO): $(UNIX_OBJS) - $(LD) $(UNIX_OBJS) $(LDFLAGS)$@ + $(LD) $(UNIX_OBJS) $(LDFLAGS)$@ $(SERIAL_SO): $(SERIAL_OBJS) $(LD) $(SERIAL_OBJS) $(LDFLAGS)$@ diff --git a/src/options.c b/src/options.c index 6f36ba4..8737d9c 100644 --- a/src/options.c +++ b/src/options.c @@ -3,6 +3,9 @@ * LuaSocket toolkit \*=========================================================================*/ #include +#include +#include +#include #include "lauxlib.h" @@ -10,12 +13,30 @@ #include "options.h" #include "inet.h" +/* Some platforms use IPV6_JOIN_GROUP instead if + * IPV6_ADD_MEMBERSHIP. The semantics are same, though. */ +#ifndef IPV6_ADD_MEMBERSHIP +#ifdef IPV6_JOIN_GROUP +#define IPV6_ADD_MEMBERSHIP IPV6_JOIN_GROUP +#endif /* IPV6_JOIN_GROUP */ +#endif /* !IPV6_ADD_MEMBERSHIP */ + +/* Same with IPV6_DROP_MEMBERSHIP / IPV6_LEAVE_GROUP. */ +#ifndef IPV6_DROP_MEMBERSHIP +#ifdef IPV6_LEAVE_GROUP +#define IPV6_DROP_MEMBERSHIP IPV6_LEAVE_GROUP +#endif /* IPV6_LEAVE_GROUP */ +#endif /* !IPV6_DROP_MEMBERSHIP */ + /*=========================================================================*\ * Internal functions prototypes \*=========================================================================*/ static int opt_setmembership(lua_State *L, p_socket ps, int level, int name); +static int opt_ip6_setmembership(lua_State *L, p_socket ps, int level, int name); static int opt_setboolean(lua_State *L, p_socket ps, int level, int name); static int opt_getboolean(lua_State *L, p_socket ps, int level, int name); +static int opt_setint(lua_State *L, p_socket ps, int level, int name); +static int opt_getint(lua_State *L, p_socket ps, int level, int name); static int opt_set(lua_State *L, p_socket ps, int level, int name, void *val, int len); static int opt_get(lua_State *L, p_socket ps, int level, int name, @@ -106,6 +127,26 @@ int opt_set_broadcast(lua_State *L, p_socket ps) return opt_setboolean(L, ps, SOL_SOCKET, SO_BROADCAST); } +int opt_set_ip6_unicast_hops(lua_State *L, p_socket ps) +{ + return opt_setint(L, ps, IPPROTO_IPV6, IPV6_UNICAST_HOPS); +} + +int opt_get_ip6_unicast_hops(lua_State *L, p_socket ps) +{ + return opt_getint(L, ps, IPPROTO_IPV6, IPV6_UNICAST_HOPS); +} + +int opt_set_ip6_multicast_hops(lua_State *L, p_socket ps) +{ + return opt_setint(L, ps, IPPROTO_IPV6, IPV6_MULTICAST_HOPS); +} + +int opt_get_ip6_multicast_hops(lua_State *L, p_socket ps) +{ + return opt_getint(L, ps, IPPROTO_IPV6, IPV6_MULTICAST_HOPS); +} + int opt_set_ip_multicast_loop(lua_State *L, p_socket ps) { return opt_setboolean(L, ps, IPPROTO_IP, IP_MULTICAST_LOOP); @@ -116,6 +157,16 @@ int opt_get_ip_multicast_loop(lua_State *L, p_socket ps) return opt_getboolean(L, ps, IPPROTO_IP, IP_MULTICAST_LOOP); } +int opt_set_ip6_multicast_loop(lua_State *L, p_socket ps) +{ + return opt_setboolean(L, ps, IPPROTO_IPV6, IPV6_MULTICAST_LOOP); +} + +int opt_get_ip6_multicast_loop(lua_State *L, p_socket ps) +{ + return opt_getboolean(L, ps, IPPROTO_IPV6, IPV6_MULTICAST_LOOP); +} + int opt_set_linger(lua_State *L, p_socket ps) { struct linger li; /* obj, name, table */ @@ -150,9 +201,7 @@ int opt_get_linger(lua_State *L, p_socket ps) int opt_set_ip_multicast_ttl(lua_State *L, p_socket ps) { - int val = (int) luaL_checknumber(L, 3); /* obj, name, int */ - return opt_set(L, ps, IPPROTO_IP, IP_MULTICAST_TTL, - (char *) &val, sizeof(val)); + return opt_setint(L, ps, IPPROTO_IP, IP_MULTICAST_TTL); } int opt_set_ip_multicast_if(lua_State *L, p_socket ps) @@ -189,6 +238,21 @@ int opt_set_ip_drop_membersip(lua_State *L, p_socket ps) return opt_setmembership(L, ps, IPPROTO_IP, IP_DROP_MEMBERSHIP); } +int opt_set_ip6_add_membership(lua_State *L, p_socket ps) +{ + return opt_ip6_setmembership(L, ps, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP); +} + +int opt_set_ip6_drop_membersip(lua_State *L, p_socket ps) +{ + return opt_ip6_setmembership(L, ps, IPPROTO_IPV6, IPV6_DROP_MEMBERSHIP); +} + +int opt_get_ip6_v6only(lua_State *L, p_socket ps) +{ + return opt_getboolean(L, ps, IPPROTO_IPV6, IPV6_V6ONLY); +} + int opt_set_ip6_v6only(lua_State *L, p_socket ps) { return opt_setboolean(L, ps, IPPROTO_IPV6, IPV6_V6ONLY); @@ -218,6 +282,37 @@ static int opt_setmembership(lua_State *L, p_socket ps, int level, int name) return opt_set(L, ps, level, name, (char *) &val, sizeof(val)); } +static int opt_ip6_setmembership(lua_State *L, p_socket ps, int level, int name) +{ + struct ipv6_mreq val; /* obj, opt-name, table */ + memset(&val, 0, sizeof(val)); + if (!lua_istable(L, 3)) auxiliar_typeerror(L,3,lua_typename(L, LUA_TTABLE)); + lua_pushstring(L, "multiaddr"); + lua_gettable(L, 3); + if (!lua_isstring(L, -1)) + luaL_argerror(L, 3, "string 'multiaddr' field expected"); + if (!inet_pton(AF_INET6, lua_tostring(L, -1), &val.ipv6mr_multiaddr)) + luaL_argerror(L, 3, "invalid 'multiaddr' ip address"); + lua_pushstring(L, "interface"); + lua_gettable(L, 3); + /* By default we listen to interface on default route + * (sigh). However, interface= can override it. We support either + * number, or name for it. */ + if (!lua_isnil(L, -1)) { + if (lua_isnumber(L, -1)) { + val.ipv6mr_interface = lua_tonumber(L, -1); + } else if (lua_isstring(L, -1)) { + if (!(val.ipv6mr_interface = if_nametoindex(lua_tostring(L, -1)))) { + lua_pushnil(L); + lua_pushstring(L, "nonexistent interface"); + return 2; + } + } else + luaL_argerror(L, -1, "number/string 'interface' field expected"); + } + return opt_set(L, ps, level, name, (char *) &val, sizeof(val)); +} + static int opt_get(lua_State *L, p_socket ps, int level, int name, void *val, int* len) { @@ -256,15 +351,15 @@ static int opt_getboolean(lua_State *L, p_socket ps, int level, int name) int opt_get_error(lua_State *L, p_socket ps) { - int val = 0; - socklen_t len = sizeof(val); - if (getsockopt(*ps, SOL_SOCKET, SO_ERROR, (char *) &val, &len) < 0) { - lua_pushnil(L); - lua_pushstring(L, "getsockopt failed"); - return 2; - } - lua_pushstring(L, socket_strerror(val)); - return 1; + int val = 0; + socklen_t len = sizeof(val); + if (getsockopt(*ps, SOL_SOCKET, SO_ERROR, (char *) &val, &len) < 0) { + lua_pushnil(L); + lua_pushstring(L, "getsockopt failed"); + return 2; + } + lua_pushstring(L, socket_strerror(val)); + return 1; } static int opt_setboolean(lua_State *L, p_socket ps, int level, int name) @@ -273,3 +368,19 @@ static int opt_setboolean(lua_State *L, p_socket ps, int level, int name) return opt_set(L, ps, level, name, (char *) &val, sizeof(val)); } +static int opt_getint(lua_State *L, p_socket ps, int level, int name) +{ + int val = 0; + int len = sizeof(val); + int err = opt_get(L, ps, level, name, (char *) &val, &len); + if (err) + return err; + lua_pushnumber(L, val); + return 1; +} + +static int opt_setint(lua_State *L, p_socket ps, int level, int name) +{ + int val = (int) lua_tonumber(L, 3); /* obj, name, int */ + return opt_set(L, ps, level, name, (char *) &val, sizeof(val)); +} diff --git a/src/options.h b/src/options.h index 1cabd7d..5657a06 100644 --- a/src/options.h +++ b/src/options.h @@ -32,6 +32,11 @@ int opt_set_ip_multicast_ttl(lua_State *L, p_socket ps); int opt_set_ip_multicast_loop(lua_State *L, p_socket ps); int opt_set_ip_add_membership(lua_State *L, p_socket ps); int opt_set_ip_drop_membersip(lua_State *L, p_socket ps); +int opt_set_ip6_unicast_hops(lua_State *L, p_socket ps); +int opt_set_ip6_multicast_hops(lua_State *L, p_socket ps); +int opt_set_ip6_multicast_loop(lua_State *L, p_socket ps); +int opt_set_ip6_add_membership(lua_State *L, p_socket ps); +int opt_set_ip6_drop_membersip(lua_State *L, p_socket ps); int opt_set_ip6_v6only(lua_State *L, p_socket ps); /* supported options for getoption */ @@ -43,6 +48,10 @@ int opt_get_reuseaddr(lua_State *L, p_socket ps); int opt_get_ip_multicast_loop(lua_State *L, p_socket ps); int opt_get_ip_multicast_if(lua_State *L, p_socket ps); int opt_get_error(lua_State *L, p_socket ps); +int opt_get_ip6_multicast_loop(lua_State *L, p_socket ps); +int opt_get_ip6_multicast_hops(lua_State *L, p_socket ps); +int opt_get_ip6_unicast_hops(lua_State *L, p_socket ps); +int opt_get_ip6_v6only(lua_State *L, p_socket ps); /* invokes the appropriate option handler */ int opt_meth_setoption(lua_State *L, p_opt opt, p_socket ps); diff --git a/src/serial.c b/src/serial.c index 66e8da6..583d4e5 100644 --- a/src/serial.c +++ b/src/serial.c @@ -73,6 +73,7 @@ LUASOCKET_API int luaopen_socket_serial(lua_State *L) { auxiliar_add2group(L, "serial{client}", "serial{any}"); #if LUA_VERSION_NUM > 501 && !defined(LUA_COMPAT_MODULE) lua_pushcfunction(L, global_create); + (void) func; #else /* set function into socket namespace */ luaL_openlib(L, "socket", func, 0); diff --git a/src/udp.c b/src/udp.c index 5945dca..8638b1d 100644 --- a/src/udp.c +++ b/src/udp.c @@ -3,6 +3,7 @@ * LuaSocket toolkit \*=========================================================================*/ #include +#include #include "lua.h" #include "lauxlib.h" @@ -68,25 +69,34 @@ static luaL_Reg udp_methods[] = { /* socket options for setoption */ static t_opt optset[] = { - {"dontroute", opt_set_dontroute}, - {"broadcast", opt_set_broadcast}, - {"reuseaddr", opt_set_reuseaddr}, - {"reuseport", opt_set_reuseport}, - {"ip-multicast-if", opt_set_ip_multicast_if}, - {"ip-multicast-ttl", opt_set_ip_multicast_ttl}, - {"ip-multicast-loop", opt_set_ip_multicast_loop}, - {"ip-add-membership", opt_set_ip_add_membership}, - {"ip-drop-membership", opt_set_ip_drop_membersip}, - {"ipv6-v6only", opt_set_ip6_v6only}, - {NULL, NULL} + {"dontroute", opt_set_dontroute}, + {"broadcast", opt_set_broadcast}, + {"reuseaddr", opt_set_reuseaddr}, + {"reuseport", opt_set_reuseport}, + {"ip-multicast-if", opt_set_ip_multicast_if}, + {"ip-multicast-ttl", opt_set_ip_multicast_ttl}, + {"ip-multicast-loop", opt_set_ip_multicast_loop}, + {"ip-add-membership", opt_set_ip_add_membership}, + {"ip-drop-membership", opt_set_ip_drop_membersip}, + {"ipv6-unicast-hops", opt_set_ip6_unicast_hops}, + {"ipv6-multicast-hops", opt_set_ip6_unicast_hops}, + {"ipv6-multicast-loop", opt_set_ip6_multicast_loop}, + {"ipv6-add-membership", opt_set_ip6_add_membership}, + {"ipv6-drop-membership", opt_set_ip6_drop_membersip}, + {"ipv6-v6only", opt_set_ip6_v6only}, + {NULL, NULL} }; /* socket options for getoption */ static t_opt optget[] = { - {"ip-multicast-if", opt_get_ip_multicast_if}, - {"ip-multicast-loop", opt_get_ip_multicast_loop}, - {"error", opt_get_error}, - {NULL, NULL} + {"ip-multicast-if", opt_get_ip_multicast_if}, + {"ip-multicast-loop", opt_get_ip_multicast_loop}, + {"error", opt_get_error}, + {"ipv6-unicast-hops", opt_get_ip6_unicast_hops}, + {"ipv6-multicast-hops", opt_get_ip6_unicast_hops}, + {"ipv6-multicast-loop", opt_get_ip6_multicast_loop}, + {"ipv6-v6only", opt_get_ip6_v6only}, + {NULL, NULL} }; /* functions in library namespace */ @@ -156,39 +166,24 @@ static int meth_sendto(lua_State *L) { size_t count, sent = 0; const char *data = luaL_checklstring(L, 2, &count); const char *ip = luaL_checkstring(L, 3); - unsigned short port = (unsigned short) luaL_checknumber(L, 4); + const char *port = luaL_checkstring(L, 4); p_timeout tm = &udp->tm; int err; - switch (udp->family) { - case PF_INET: { - struct sockaddr_in addr; - memset(&addr, 0, sizeof(addr)); - if (inet_pton(AF_INET, ip, &addr.sin_addr) != 1) - 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) != 1) - 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: + struct addrinfo aihint; + struct addrinfo *ai; + memset(&aihint, 0, sizeof(aihint)); + aihint.ai_family = udp->family; + aihint.ai_socktype = SOCK_DGRAM; + aihint.ai_flags = AI_NUMERICHOST | AI_NUMERICSERV; + if ((err = getaddrinfo(ip, port, &aihint, &ai))) { lua_pushnil(L); - lua_pushfstring(L, "unknown family %d", udp->family); + lua_pushstring(L, udp_strerror(err)); return 2; } + timeout_markstart(tm); + err = socket_sendto(&udp->sock, data, count, &sent, ai->ai_addr, + ai->ai_addrlen, tm); + freeaddrinfo(ai); if (err != IO_DONE) { lua_pushnil(L); lua_pushstring(L, udp_strerror(err)); @@ -225,71 +220,39 @@ static int meth_receive(lua_State *L) { /*-------------------------------------------------------------------------*\ * Receives data and sender from a UDP socket \*-------------------------------------------------------------------------*/ -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); char buffer[UDP_DATAGRAMSIZE]; size_t got, count = (size_t) luaL_optnumber(L, 2, sizeof(buffer)); int err; p_timeout tm = &udp->tm; + struct sockaddr_storage addr; + socklen_t addr_len = sizeof(addr); + char addrstr[INET6_ADDRSTRLEN]; + char portstr[6]; timeout_markstart(tm); 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, - (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: + 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_pushnil(L); - lua_pushfstring(L, "unknown family %d", udp->family); + lua_pushstring(L, udp_strerror(err)); return 2; } - lua_pushnil(L); - lua_pushstring(L, udp_strerror(err)); - return 2; + if ((err = getnameinfo((struct sockaddr *)&addr, addr_len, addrstr, + INET6_ADDRSTRLEN, portstr, 6, NI_NUMERICHOST | NI_NUMERICSERV))) { + lua_pushnil(L); + lua_pushstring(L, gai_strerror(err)); + return 2; + } + lua_pushlstring(L, buffer, got); + lua_pushstring(L, addrstr); + lua_pushinteger(L, (int) strtol(portstr, (char **) NULL, 10)); + return 3; } /*-------------------------------------------------------------------------*\ diff --git a/src/unix.c b/src/unix.c index 5710c27..91aaaf8 100644 --- a/src/unix.c +++ b/src/unix.c @@ -91,6 +91,7 @@ int luaopen_socket_unix(lua_State *L) { auxiliar_add2group(L, "unix{server}", "unix{any}"); #if LUA_VERSION_NUM > 501 && !defined(LUA_COMPAT_MODULE) lua_pushcfunction(L, global_create); + (void) func; #else /* set function into socket namespace */ luaL_openlib(L, "socket", func, 0);