diff options
author | Peter Breitenlohner <peb@mppmu.mpg.de> | 2013-03-21 09:16:59 +0000 |
---|---|---|
committer | Peter Breitenlohner <peb@mppmu.mpg.de> | 2013-03-21 09:16:59 +0000 |
commit | 388463b9fa865c3b2311508c41647b0f3c532031 (patch) | |
tree | 1cdfbf5552d0783ecbcc52017e49567e5042af33 /Build/source/texk/web2c/luatexdir/luasocket/src/udp.c | |
parent | abd0b00a4e8c1ac6f5b20c7474d70ef579129991 (diff) |
Import MetaPost 1.800 and LuaTeX beta-0.75.0 from LuaTeX repository r4604
git-svn-id: svn://tug.org/texlive/trunk@29453 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Build/source/texk/web2c/luatexdir/luasocket/src/udp.c')
-rw-r--r-- | Build/source/texk/web2c/luatexdir/luasocket/src/udp.c | 262 |
1 files changed, 197 insertions, 65 deletions
diff --git a/Build/source/texk/web2c/luatexdir/luasocket/src/udp.c b/Build/source/texk/web2c/luatexdir/luasocket/src/udp.c index fc25aa027dc..8e14fac290f 100644 --- a/Build/source/texk/web2c/luatexdir/luasocket/src/udp.c +++ b/Build/source/texk/web2c/luatexdir/luasocket/src/udp.c @@ -1,10 +1,8 @@ /*=========================================================================*\ -* UDP object +* UDP object * LuaSocket toolkit -* -* RCS ID: $Id: udp.c,v 1.29 2005/10/07 04:40:59 diego Exp $ \*=========================================================================*/ -#include <string.h> +#include <string.h> #include "lua.h" #include "lauxlib.h" @@ -18,36 +16,40 @@ /* min and max macros */ #ifndef MIN #define MIN(x, y) ((x) < (y) ? x : y) -#endif +#endif #ifndef MAX #define MAX(x, y) ((x) > (y) ? x : y) -#endif +#endif /*=========================================================================*\ * Internal function prototypes \*=========================================================================*/ static int global_create(lua_State *L); +static int global_create6(lua_State *L); static int meth_send(lua_State *L); static int meth_sendto(lua_State *L); static int meth_receive(lua_State *L); static int meth_receivefrom(lua_State *L); +static int meth_getfamily(lua_State *L); static int meth_getsockname(lua_State *L); static int meth_getpeername(lua_State *L); static int meth_setsockname(lua_State *L); static int meth_setpeername(lua_State *L); static int meth_close(lua_State *L); static int meth_setoption(lua_State *L); +static int meth_getoption(lua_State *L); static int meth_settimeout(lua_State *L); static int meth_getfd(lua_State *L); static int meth_setfd(lua_State *L); static int meth_dirty(lua_State *L); /* udp object methods */ -static luaL_reg udp[] = { +static luaL_Reg udp_methods[] = { {"__gc", meth_close}, {"__tostring", auxiliar_tostring}, {"close", meth_close}, {"dirty", meth_dirty}, + {"getfamily", meth_getfamily}, {"getfd", meth_getfd}, {"getpeername", meth_getpeername}, {"getsockname", meth_getsockname}, @@ -57,27 +59,39 @@ static luaL_reg udp[] = { {"sendto", meth_sendto}, {"setfd", meth_setfd}, {"setoption", meth_setoption}, + {"getoption", meth_getoption}, {"setpeername", meth_setpeername}, {"setsockname", meth_setsockname}, {"settimeout", meth_settimeout}, {NULL, NULL} }; -/* socket options */ -static t_opt opt[] = { - {"dontroute", opt_dontroute}, - {"broadcast", opt_broadcast}, - {"reuseaddr", opt_reuseaddr}, - {"ip-multicast-ttl", opt_ip_multicast_ttl}, - {"ip-multicast-loop", opt_ip_multicast_loop}, - {"ip-add-membership", opt_ip_add_membership}, - {"ip-drop-membership", opt_ip_drop_membersip}, - {NULL, NULL} +/* 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} +}; + +/* socket options for getoption */ +static t_opt optget[] = { + {"ip-multicast-if", opt_get_ip_multicast_if}, + {"ip-multicast-loop", opt_get_ip_multicast_loop}, + {NULL, NULL} }; /* functions in library namespace */ -static luaL_reg func[] = { +static luaL_Reg func[] = { {"udp", global_create}, + {"udp6", global_create6}, {NULL, NULL} }; @@ -87,15 +101,15 @@ static luaL_reg func[] = { int udp_open(lua_State *L) { /* create classes */ - auxiliar_newclass(L, "udp{connected}", udp); - auxiliar_newclass(L, "udp{unconnected}", udp); + auxiliar_newclass(L, "udp{connected}", udp_methods); + auxiliar_newclass(L, "udp{unconnected}", udp_methods); /* create class groups */ auxiliar_add2group(L, "udp{connected}", "udp{any}"); auxiliar_add2group(L, "udp{unconnected}", "udp{any}"); auxiliar_add2group(L, "udp{connected}", "select{able}"); auxiliar_add2group(L, "udp{unconnected}", "select{able}"); /* define library functions */ - luaL_openlib(L, NULL, func, 0); + luaL_openlib(L, NULL, func, 0); return 0; } @@ -125,7 +139,7 @@ static int meth_send(lua_State *L) { lua_pushstring(L, udp_strerror(err)); return 2; } - lua_pushnumber(L, sent); + lua_pushnumber(L, (lua_Number) sent); return 1; } @@ -139,22 +153,43 @@ 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)); return 2; } - lua_pushnumber(L, sent); + lua_pushnumber(L, (lua_Number) sent); return 1; } @@ -170,6 +205,9 @@ static int meth_receive(lua_State *L) { count = MIN(count, sizeof(buffer)); timeout_markstart(tm); err = socket_recv(&udp->sock, buffer, count, &got, 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_pushstring(L, udp_strerror(err)); @@ -184,26 +222,82 @@ 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); - 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 { + 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_pushstring(L, udp_strerror(err)); + lua_pushfstring(L, "unknown family %d", udp->family); return 2; } + lua_pushnil(L); + lua_pushstring(L, udp_strerror(err)); + return 2; +} + +/*-------------------------------------------------------------------------*\ +* Returns family as string +\*-------------------------------------------------------------------------*/ +static int meth_getfamily(lua_State *L) +{ + p_udp udp = (p_udp) auxiliar_checkgroup(L, "udp{any}", 1); + if (udp->family == PF_INET6) { + lua_pushliteral(L, "inet6"); + return 1; + } else { + lua_pushliteral(L, "inet4"); + return 1; + } } /*-------------------------------------------------------------------------*\ @@ -234,12 +328,12 @@ static int meth_dirty(lua_State *L) { \*-------------------------------------------------------------------------*/ static int meth_getpeername(lua_State *L) { p_udp udp = (p_udp) auxiliar_checkclass(L, "udp{connected}", 1); - return inet_meth_getpeername(L, &udp->sock); + return inet_meth_getpeername(L, &udp->sock, udp->family); } static int meth_getsockname(lua_State *L) { p_udp udp = (p_udp) auxiliar_checkgroup(L, "udp{any}", 1); - return inet_meth_getsockname(L, &udp->sock); + return inet_meth_getsockname(L, &udp->sock, udp->family); } /*-------------------------------------------------------------------------*\ @@ -247,7 +341,15 @@ static int meth_getsockname(lua_State *L) { \*-------------------------------------------------------------------------*/ static int meth_setoption(lua_State *L) { p_udp udp = (p_udp) auxiliar_checkgroup(L, "udp{any}", 1); - return opt_meth_setoption(L, opt, &udp->sock); + return opt_meth_setoption(L, optset, &udp->sock); +} + +/*-------------------------------------------------------------------------*\ +* Just call option handler +\*-------------------------------------------------------------------------*/ +static int meth_getoption(lua_State *L) { + p_udp udp = (p_udp) auxiliar_checkgroup(L, "udp{any}", 1); + return opt_meth_getoption(L, optget, &udp->sock); } /*-------------------------------------------------------------------------*\ @@ -264,26 +366,36 @@ static int meth_settimeout(lua_State *L) { static int meth_setpeername(lua_State *L) { p_udp udp = (p_udp) auxiliar_checkgroup(L, "udp{any}", 1); p_timeout tm = &udp->tm; - const char *address = luaL_checkstring(L, 2); + const char *address = luaL_checkstring(L, 2); int connecting = strcmp(address, "*"); - unsigned short port = connecting ? - (unsigned short) luaL_checknumber(L, 3) : - (unsigned short) luaL_optnumber(L, 3, 0); - const char *err = inet_tryconnect(&udp->sock, address, port, tm); - if (err) { - lua_pushnil(L); - lua_pushstring(L, err); - return 2; + const char *port = connecting? luaL_checkstring(L, 3): "0"; + struct addrinfo connecthints; + const char *err; + memset(&connecthints, 0, sizeof(connecthints)); + connecthints.ai_socktype = SOCK_DGRAM; + /* make sure we try to connect only to the same family */ + connecthints.ai_family = udp->family; + if (connecting) { + err = inet_tryconnect(&udp->sock, address, port, tm, &connecthints); + if (err) { + lua_pushnil(L); + lua_pushstring(L, err); + return 2; + } + auxiliar_setclass(L, "udp{connected}", 1); + } else { + /* we ignore possible errors because Mac OS X always + * returns EAFNOSUPPORT */ + inet_trydisconnect(&udp->sock, udp->family, tm); + auxiliar_setclass(L, "udp{unconnected}", 1); } /* change class to connected or unconnected depending on address */ - if (connecting) auxiliar_setclass(L, "udp{connected}", 1); - else auxiliar_setclass(L, "udp{unconnected}", 1); lua_pushnumber(L, 1); return 1; } /*-------------------------------------------------------------------------*\ -* Closes socket used by object +* Closes socket used by object \*-------------------------------------------------------------------------*/ static int meth_close(lua_State *L) { p_udp udp = (p_udp) auxiliar_checkgroup(L, "udp{any}", 1); @@ -298,8 +410,14 @@ static int meth_close(lua_State *L) { static int meth_setsockname(lua_State *L) { p_udp udp = (p_udp) auxiliar_checkclass(L, "udp{unconnected}", 1); const char *address = luaL_checkstring(L, 2); - unsigned short port = (unsigned short) luaL_checknumber(L, 3); - const char *err = inet_trybind(&udp->sock, address, port); + const char *port = luaL_checkstring(L, 3); + const char *err; + struct addrinfo bindhints; + memset(&bindhints, 0, sizeof(bindhints)); + bindhints.ai_socktype = SOCK_DGRAM; + bindhints.ai_family = udp->family; + bindhints.ai_flags = AI_PASSIVE; + err = inet_trybind(&udp->sock, address, port, &bindhints); if (err) { lua_pushnil(L); lua_pushstring(L, err); @@ -313,20 +431,26 @@ static int meth_setsockname(lua_State *L) { * Library functions \*=========================================================================*/ /*-------------------------------------------------------------------------*\ -* Creates a master udp object +* Creates a master udp object \*-------------------------------------------------------------------------*/ -static int global_create(lua_State *L) { +static int udp_create(lua_State *L, int family) { t_socket sock; - const char *err = inet_trycreate(&sock, SOCK_DGRAM); + const char *err = inet_trycreate(&sock, family, SOCK_DGRAM); /* try to allocate a system socket */ - if (!err) { - /* allocate tcp object */ + if (!err) { + /* allocate udp object */ p_udp udp = (p_udp) lua_newuserdata(L, sizeof(t_udp)); auxiliar_setclass(L, "udp{unconnected}", -1); /* initialize remaining structure fields */ socket_setnonblocking(&sock); + if (family == PF_INET6) { + int yes = 1; + setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, + (void *)&yes, sizeof(yes)); + } udp->sock = sock; timeout_init(&udp->tm, -1, -1); + udp->family = family; return 1; } else { lua_pushnil(L); @@ -334,3 +458,11 @@ static int global_create(lua_State *L) { return 2; } } + +static int global_create(lua_State *L) { + return udp_create(L, AF_INET); +} + +static int global_create6(lua_State *L) { + return udp_create(L, AF_INET6); +} |