diff options
Diffstat (limited to 'Build/source/texk/web2c/luatexdir/luasocket/src/tcp.c')
-rw-r--r-- | Build/source/texk/web2c/luatexdir/luasocket/src/tcp.c | 170 |
1 files changed, 73 insertions, 97 deletions
diff --git a/Build/source/texk/web2c/luatexdir/luasocket/src/tcp.c b/Build/source/texk/web2c/luatexdir/luasocket/src/tcp.c index e7334031478..ef9ee6f9c2f 100644 --- a/Build/source/texk/web2c/luatexdir/luasocket/src/tcp.c +++ b/Build/source/texk/web2c/luatexdir/luasocket/src/tcp.c @@ -6,6 +6,7 @@ #include "lua.h" #include "lauxlib.h" +#include "compat.h" #include "auxiliar.h" #include "socket.h" @@ -17,6 +18,7 @@ * Internal function prototypes \*=========================================================================*/ static int global_create(lua_State *L); +static int global_create4(lua_State *L); static int global_create6(lua_State *L); static int global_connect(lua_State *L); static int meth_connect(lua_State *L); @@ -34,6 +36,7 @@ static int meth_accept(lua_State *L); static int meth_close(lua_State *L); static int meth_getoption(lua_State *L); static int meth_setoption(lua_State *L); +static int meth_gettimeout(lua_State *L); static int meth_settimeout(lua_State *L); static int meth_getfd(lua_State *L); static int meth_setfd(lua_State *L); @@ -63,6 +66,7 @@ static luaL_Reg tcp_methods[] = { {"setpeername", meth_connect}, {"setsockname", meth_bind}, {"settimeout", meth_settimeout}, + {"gettimeout", meth_gettimeout}, {"shutdown", meth_shutdown}, {NULL, NULL} }; @@ -71,14 +75,17 @@ static luaL_Reg tcp_methods[] = { static t_opt optget[] = { {"keepalive", opt_get_keepalive}, {"reuseaddr", opt_get_reuseaddr}, + {"reuseport", opt_get_reuseport}, {"tcp-nodelay", opt_get_tcp_nodelay}, {"linger", opt_get_linger}, + {"error", opt_get_error}, {NULL, NULL} }; static t_opt optset[] = { {"keepalive", opt_set_keepalive}, {"reuseaddr", opt_set_reuseaddr}, + {"reuseport", opt_set_reuseport}, {"tcp-nodelay", opt_set_tcp_nodelay}, {"ipv6-v6only", opt_set_ip6_v6only}, {"linger", opt_set_linger}, @@ -88,6 +95,7 @@ static t_opt optset[] = { /* functions in library namespace */ static luaL_Reg func[] = { {"tcp", global_create}, + {"tcp4", global_create4}, {"tcp6", global_create6}, {"connect", global_connect}, {NULL, NULL} @@ -99,15 +107,15 @@ static luaL_Reg func[] = { int tcp_open(lua_State *L) { /* create classes */ - auxiliar_newclass(L, "tcp.master", tcp_methods); - auxiliar_newclass(L, "tcp.client", tcp_methods); - auxiliar_newclass(L, "tcp.server", tcp_methods); + auxiliar_newclass(L, "tcp{master}", tcp_methods); + auxiliar_newclass(L, "tcp{client}", tcp_methods); + auxiliar_newclass(L, "tcp{server}", tcp_methods); /* create class groups */ - auxiliar_add2group(L, "tcp.master", "tcp{any}"); - auxiliar_add2group(L, "tcp.client", "tcp{any}"); - auxiliar_add2group(L, "tcp.server", "tcp{any}"); + auxiliar_add2group(L, "tcp{master}", "tcp{any}"); + auxiliar_add2group(L, "tcp{client}", "tcp{any}"); + auxiliar_add2group(L, "tcp{server}", "tcp{any}"); /* define library functions */ - luaL_openlib(L, NULL, func, 0); + luaL_setfuncs(L, func, 0); return 0; } @@ -118,22 +126,22 @@ int tcp_open(lua_State *L) * Just call buffered IO methods \*-------------------------------------------------------------------------*/ static int meth_send(lua_State *L) { - p_tcp tcp = (p_tcp) auxiliar_checkclass(L, "tcp.client", 1); + p_tcp tcp = (p_tcp) auxiliar_checkclass(L, "tcp{client}", 1); return buffer_meth_send(L, &tcp->buf); } static int meth_receive(lua_State *L) { - p_tcp tcp = (p_tcp) auxiliar_checkclass(L, "tcp.client", 1); + p_tcp tcp = (p_tcp) auxiliar_checkclass(L, "tcp{client}", 1); return buffer_meth_receive(L, &tcp->buf); } static int meth_getstats(lua_State *L) { - p_tcp tcp = (p_tcp) auxiliar_checkclass(L, "tcp.client", 1); + p_tcp tcp = (p_tcp) auxiliar_checkclass(L, "tcp{client}", 1); return buffer_meth_getstats(L, &tcp->buf); } static int meth_setstats(lua_State *L) { - p_tcp tcp = (p_tcp) auxiliar_checkclass(L, "tcp.client", 1); + p_tcp tcp = (p_tcp) auxiliar_checkclass(L, "tcp{client}", 1); return buffer_meth_setstats(L, &tcp->buf); } @@ -183,14 +191,14 @@ static int meth_dirty(lua_State *L) \*-------------------------------------------------------------------------*/ static int meth_accept(lua_State *L) { - p_tcp server = (p_tcp) auxiliar_checkclass(L, "tcp.server", 1); + p_tcp server = (p_tcp) auxiliar_checkclass(L, "tcp{server}", 1); p_timeout tm = timeout_markstart(&server->tm); t_socket sock; const char *err = inet_tryaccept(&server->sock, server->family, &sock, tm); /* if successful, push client socket */ if (err == NULL) { p_tcp clnt = (p_tcp) lua_newuserdata(L, sizeof(t_tcp)); - auxiliar_setclass(L, "tcp.client", -1); + auxiliar_setclass(L, "tcp{client}", -1); /* initialize structure fields */ memset(clnt, 0, sizeof(t_tcp)); socket_setnonblocking(&sock); @@ -211,9 +219,8 @@ static int meth_accept(lua_State *L) /*-------------------------------------------------------------------------*\ * Binds an object to an address \*-------------------------------------------------------------------------*/ -static int meth_bind(lua_State *L) -{ - p_tcp tcp = (p_tcp) auxiliar_checkclass(L, "tcp.master", 1); +static int meth_bind(lua_State *L) { + p_tcp tcp = (p_tcp) auxiliar_checkclass(L, "tcp{master}", 1); const char *address = luaL_checkstring(L, 2); const char *port = luaL_checkstring(L, 3); const char *err; @@ -222,8 +229,7 @@ static int meth_bind(lua_State *L) bindhints.ai_socktype = SOCK_STREAM; bindhints.ai_family = tcp->family; bindhints.ai_flags = AI_PASSIVE; - address = strcmp(address, "*")? address: NULL; - err = inet_trybind(&tcp->sock, address, port, &bindhints); + err = inet_trybind(&tcp->sock, &tcp->family, address, port, &bindhints); if (err) { lua_pushnil(L); lua_pushstring(L, err); @@ -236,8 +242,7 @@ static int meth_bind(lua_State *L) /*-------------------------------------------------------------------------*\ * Turns a master tcp object into a client object. \*-------------------------------------------------------------------------*/ -static int meth_connect(lua_State *L) -{ +static int meth_connect(lua_State *L) { p_tcp tcp = (p_tcp) auxiliar_checkgroup(L, "tcp{any}", 1); const char *address = luaL_checkstring(L, 2); const char *port = luaL_checkstring(L, 3); @@ -248,9 +253,10 @@ static int meth_connect(lua_State *L) /* make sure we try to connect only to the same family */ connecthints.ai_family = tcp->family; timeout_markstart(&tcp->tm); - err = inet_tryconnect(&tcp->sock, address, port, &tcp->tm, &connecthints); + err = inet_tryconnect(&tcp->sock, &tcp->family, address, port, + &tcp->tm, &connecthints); /* have to set the class even if it failed due to non-blocking connects */ - auxiliar_setclass(L, "tcp.client", 1); + auxiliar_setclass(L, "tcp{client}", 1); if (err) { lua_pushnil(L); lua_pushstring(L, err); @@ -277,9 +283,12 @@ static int meth_close(lua_State *L) static int meth_getfamily(lua_State *L) { p_tcp tcp = (p_tcp) auxiliar_checkgroup(L, "tcp{any}", 1); - if (tcp->family == PF_INET6) { + if (tcp->family == AF_INET6) { lua_pushliteral(L, "inet6"); return 1; + } else if (tcp->family == AF_INET) { + lua_pushliteral(L, "inet4"); + return 1; } else { lua_pushliteral(L, "inet4"); return 1; @@ -291,7 +300,7 @@ static int meth_getfamily(lua_State *L) \*-------------------------------------------------------------------------*/ static int meth_listen(lua_State *L) { - p_tcp tcp = (p_tcp) auxiliar_checkclass(L, "tcp.master", 1); + p_tcp tcp = (p_tcp) auxiliar_checkclass(L, "tcp{master}", 1); int backlog = (int) luaL_optnumber(L, 2, 32); int err = socket_listen(&tcp->sock, backlog); if (err != IO_DONE) { @@ -300,7 +309,7 @@ static int meth_listen(lua_State *L) return 2; } /* turn master object into a server object */ - auxiliar_setclass(L, "tcp.server", 1); + auxiliar_setclass(L, "tcp{server}", 1); lua_pushnumber(L, 1); return 1; } @@ -312,7 +321,7 @@ static int meth_shutdown(lua_State *L) { /* SHUT_RD, SHUT_WR, SHUT_RDWR have the value 0, 1, 2, so we can use method index directly */ static const char* methods[] = { "receive", "send", "both", NULL }; - p_tcp tcp = (p_tcp) auxiliar_checkclass(L, "tcp.client", 1); + p_tcp tcp = (p_tcp) auxiliar_checkclass(L, "tcp{client}", 1); int how = luaL_checkoption(L, 2, "both", methods); socket_shutdown(&tcp->sock, how); lua_pushnumber(L, 1); @@ -343,6 +352,12 @@ static int meth_settimeout(lua_State *L) return timeout_meth_settimeout(L, &tcp->tm); } +static int meth_gettimeout(lua_State *L) +{ + p_tcp tcp = (p_tcp) auxiliar_checkgroup(L, "tcp{any}", 1); + return timeout_meth_gettimeout(L, &tcp->tm); +} + /*=========================================================================*\ * Library functions \*=========================================================================*/ @@ -350,37 +365,36 @@ static int meth_settimeout(lua_State *L) * Creates a master tcp object \*-------------------------------------------------------------------------*/ static int tcp_create(lua_State *L, int family) { - t_socket sock; - const char *err = inet_trycreate(&sock, family, SOCK_STREAM); - /* try to allocate a system socket */ - if (!err) { - /* allocate tcp object */ - p_tcp tcp = (p_tcp) lua_newuserdata(L, sizeof(t_tcp)); - memset(tcp, 0, sizeof(t_tcp)); - /* set its type as master object */ - auxiliar_setclass(L, "tcp.master", -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)); + p_tcp tcp = (p_tcp) lua_newuserdata(L, sizeof(t_tcp)); + memset(tcp, 0, sizeof(t_tcp)); + /* set its type as master object */ + auxiliar_setclass(L, "tcp{master}", -1); + /* if family is AF_UNSPEC, we leave the socket invalid and + * store AF_UNSPEC into family. This will allow it to later be + * replaced with an AF_INET6 or AF_INET socket upon first use. */ + tcp->sock = SOCKET_INVALID; + tcp->family = family; + io_init(&tcp->io, (p_send) socket_send, (p_recv) socket_recv, + (p_error) socket_ioerror, &tcp->sock); + timeout_init(&tcp->tm, -1, -1); + buffer_init(&tcp->buf, &tcp->io, &tcp->tm); + if (family != AF_UNSPEC) { + const char *err = inet_trycreate(&tcp->sock, family, SOCK_STREAM, 0); + if (err != NULL) { + lua_pushnil(L); + lua_pushstring(L, err); + return 2; } - tcp->sock = sock; - io_init(&tcp->io, (p_send) socket_send, (p_recv) socket_recv, - (p_error) socket_ioerror, &tcp->sock); - timeout_init(&tcp->tm, -1, -1); - buffer_init(&tcp->buf, &tcp->io, &tcp->tm); - tcp->family = family; - return 1; - } else { - lua_pushnil(L); - lua_pushstring(L, err); - return 2; + socket_setnonblocking(&tcp->sock); } + return 1; } static int global_create(lua_State *L) { + return tcp_create(L, AF_UNSPEC); +} + +static int global_create4(lua_State *L) { return tcp_create(L, AF_INET); } @@ -388,46 +402,6 @@ static int global_create6(lua_State *L) { return tcp_create(L, AF_INET6); } -static const char *tryconnect6(const char *remoteaddr, const char *remoteserv, - struct addrinfo *connecthints, p_tcp tcp) { - struct addrinfo *iterator = NULL, *resolved = NULL; - const char *err = NULL; - /* try resolving */ - err = socket_gaistrerror(getaddrinfo(remoteaddr, remoteserv, - connecthints, &resolved)); - if (err != NULL) { - if (resolved) freeaddrinfo(resolved); - return err; - } - /* iterate over all returned addresses trying to connect */ - for (iterator = resolved; iterator; iterator = iterator->ai_next) { - p_timeout tm = timeout_markstart(&tcp->tm); - /* create new socket if one wasn't created by the bind stage */ - if (tcp->sock == SOCKET_INVALID) { - err = socket_strerror(socket_create(&tcp->sock, - iterator->ai_family, iterator->ai_socktype, - iterator->ai_protocol)); - if (err != NULL) { - freeaddrinfo(resolved); - return err; - } - tcp->family = iterator->ai_family; - /* all sockets initially non-blocking */ - socket_setnonblocking(&tcp->sock); - } - /* finally try connecting to remote address */ - err = socket_strerror(socket_connect(&tcp->sock, - (SA *) iterator->ai_addr, - (socklen_t) iterator->ai_addrlen, tm)); - /* if success, break out of loop */ - if (err == NULL) break; - } - - freeaddrinfo(resolved); - /* here, if err is set, we failed */ - return err; -} - static int global_connect(lua_State *L) { const char *remoteaddr = luaL_checkstring(L, 1); const char *remoteserv = luaL_checkstring(L, 2); @@ -444,32 +418,34 @@ static int global_connect(lua_State *L) { timeout_init(&tcp->tm, -1, -1); buffer_init(&tcp->buf, &tcp->io, &tcp->tm); tcp->sock = SOCKET_INVALID; + tcp->family = AF_UNSPEC; /* allow user to pick local address and port */ memset(&bindhints, 0, sizeof(bindhints)); bindhints.ai_socktype = SOCK_STREAM; bindhints.ai_family = family; bindhints.ai_flags = AI_PASSIVE; if (localaddr) { - err = inet_trybind(&tcp->sock, localaddr, localserv, &bindhints); + err = inet_trybind(&tcp->sock, &tcp->family, localaddr, + localserv, &bindhints); if (err) { lua_pushnil(L); lua_pushstring(L, err); return 2; } - tcp->family = bindhints.ai_family; } /* try to connect to remote address and port */ memset(&connecthints, 0, sizeof(connecthints)); connecthints.ai_socktype = SOCK_STREAM; /* make sure we try to connect only to the same family */ - connecthints.ai_family = bindhints.ai_family; - err = tryconnect6(remoteaddr, remoteserv, &connecthints, tcp); + connecthints.ai_family = tcp->family; + err = inet_tryconnect(&tcp->sock, &tcp->family, remoteaddr, remoteserv, + &tcp->tm, &connecthints); if (err) { socket_destroy(&tcp->sock); lua_pushnil(L); lua_pushstring(L, err); return 2; } - auxiliar_setclass(L, "tcp.client", -1); + auxiliar_setclass(L, "tcp{client}", -1); return 1; } |