diff --git a/etc/b64.lua b/etc/b64.lua index d74c949..f75c423 100644 --- a/etc/b64.lua +++ b/etc/b64.lua @@ -2,7 +2,7 @@ -- Little program to convert to and from Base64 -- LuaSocket sample files -- Author: Diego Nehab --- RCS ID: $Id$ +-- RCS ID: $Id: b64.lua,v 1.8 2004/06/16 04:28:21 diego Exp $ ----------------------------------------------------------------------------- local ltn12 = require("ltn12") local mime = require("mime") diff --git a/etc/dict.lua b/etc/dict.lua index 6eb3210..e375d23 100644 --- a/etc/dict.lua +++ b/etc/dict.lua @@ -2,7 +2,7 @@ -- Little program to download DICT word definitions -- LuaSocket sample files -- Author: Diego Nehab --- RCS ID: $Id$ +-- RCS ID: $Id: dict.lua,v 1.22 2005/11/22 08:33:29 diego Exp $ ----------------------------------------------------------------------------- ----------------------------------------------------------------------------- diff --git a/etc/eol.lua b/etc/eol.lua index d7c5db6..b90be79 100644 --- a/etc/eol.lua +++ b/etc/eol.lua @@ -2,7 +2,7 @@ -- Little program to adjust end of line markers. -- LuaSocket sample files -- Author: Diego Nehab --- RCS ID: $Id$ +-- RCS ID: $Id: eol.lua,v 1.8 2005/11/22 08:33:29 diego Exp $ ----------------------------------------------------------------------------- local mime = require("mime") local ltn12 = require("ltn12") diff --git a/etc/get.lua b/etc/get.lua index 0d631c2..4c344e2 100644 --- a/etc/get.lua +++ b/etc/get.lua @@ -2,7 +2,7 @@ -- Little program to download files from URLs -- LuaSocket sample files -- Author: Diego Nehab --- RCS ID: $Id$ +-- RCS ID: $Id: get.lua,v 1.25 2007/03/12 04:08:40 diego Exp $ ----------------------------------------------------------------------------- local socket = require("socket") local http = require("socket.http") diff --git a/etc/lp.lua b/etc/lp.lua index f067604..d57c928 100644 --- a/etc/lp.lua +++ b/etc/lp.lua @@ -3,7 +3,7 @@ -- LuaSocket toolkit. -- Author: David Burgess -- Modified by Diego Nehab, but David is in charge --- RCS ID: $Id$ +-- RCS ID: $Id: lp.lua,v 1.14 2005/11/21 07:04:44 diego Exp $ ----------------------------------------------------------------------------- --[[ if you have any questions: RFC 1179 diff --git a/etc/qp.lua b/etc/qp.lua index 31a572b..a4c0cad 100644 --- a/etc/qp.lua +++ b/etc/qp.lua @@ -2,7 +2,7 @@ -- Little program to convert to and from Quoted-Printable -- LuaSocket sample files -- Author: Diego Nehab --- RCS ID: $Id$ +-- RCS ID: $Id: qp.lua,v 1.5 2004/06/17 21:46:22 diego Exp $ ----------------------------------------------------------------------------- local ltn12 = require("ltn12") local mime = require("mime") diff --git a/etc/tftp.lua b/etc/tftp.lua index 4051e74..7f51c6f 100644 --- a/etc/tftp.lua +++ b/etc/tftp.lua @@ -2,7 +2,7 @@ -- TFTP support for the Lua language -- LuaSocket toolkit. -- Author: Diego Nehab --- RCS ID: $Id$ +-- RCS ID: $Id: tftp.lua,v 1.16 2005/11/22 08:33:29 diego Exp $ ----------------------------------------------------------------------------- ----------------------------------------------------------------------------- diff --git a/samples/daytimeclnt.lua b/samples/daytimeclnt.lua index 6a26ffc..90ab39e 100644 --- a/samples/daytimeclnt.lua +++ b/samples/daytimeclnt.lua @@ -2,7 +2,7 @@ -- UDP sample: daytime protocol client -- LuaSocket sample files -- Author: Diego Nehab --- RCS ID: $Id$ +-- RCS ID: $Id: daytimeclnt.lua,v 1.11 2004/06/21 06:07:57 diego Exp $ ----------------------------------------------------------------------------- local socket = require"socket" host = host or "127.0.0.1" diff --git a/samples/echoclnt.lua b/samples/echoclnt.lua index 764e433..038be4c 100644 --- a/samples/echoclnt.lua +++ b/samples/echoclnt.lua @@ -2,7 +2,7 @@ -- UDP sample: echo protocol client -- LuaSocket sample files -- Author: Diego Nehab --- RCS ID: $Id$ +-- RCS ID: $Id: echoclnt.lua,v 1.10 2005/01/02 22:44:00 diego Exp $ ----------------------------------------------------------------------------- local socket = require("socket") host = host or "localhost" diff --git a/samples/echosrvr.lua b/samples/echosrvr.lua index 8d39ed9..2697ca4 100644 --- a/samples/echosrvr.lua +++ b/samples/echosrvr.lua @@ -2,7 +2,7 @@ -- UDP sample: echo protocol server -- LuaSocket sample files -- Author: Diego Nehab --- RCS ID: $Id$ +-- RCS ID: $Id: echosrvr.lua,v 1.12 2005/11/22 08:33:29 diego Exp $ ----------------------------------------------------------------------------- local socket = require("socket") host = host or "127.0.0.1" diff --git a/samples/listener.lua b/samples/listener.lua index 4d4c3b6..9260fbb 100644 --- a/samples/listener.lua +++ b/samples/listener.lua @@ -2,7 +2,7 @@ -- TCP sample: Little program to dump lines received at a given port -- LuaSocket sample files -- Author: Diego Nehab --- RCS ID: $Id$ +-- RCS ID: $Id: listener.lua,v 1.11 2005/01/02 22:44:00 diego Exp $ ----------------------------------------------------------------------------- local socket = require("socket") host = host or "*" diff --git a/samples/mclisten.lua b/samples/mclisten.lua new file mode 100644 index 0000000..d40d789 --- /dev/null +++ b/samples/mclisten.lua @@ -0,0 +1,18 @@ +local socket = require"socket" +local group = "225.0.0.37" +local port = 12345 +local c = assert(socket.udp()) +print(assert(c:setoption("reuseport", true))) +print(assert(c:setsockname("*", port))) +--print("loop:", c:getoption("ip-multicast-loop")) +--print(assert(c:setoption("ip-multicast-loop", false))) +--print("loop:", c:getoption("ip-multicast-loop")) +--print("if:", c:getoption("ip-multicast-if")) +--print(assert(c:setoption("ip-multicast-if", "127.0.0.1"))) +--print("if:", c:getoption("ip-multicast-if")) +--print(assert(c:setoption("ip-multicast-if", "10.0.1.4"))) +--print("if:", c:getoption("ip-multicast-if")) +print(assert(c:setoption("ip-add-membership", {multiaddr = group, interface = "*"}))) +while 1 do + print(c:receivefrom()) +end diff --git a/samples/mcsend.lua b/samples/mcsend.lua new file mode 100644 index 0000000..7c24cdf --- /dev/null +++ b/samples/mcsend.lua @@ -0,0 +1,20 @@ +local socket = require"socket" +local group = "225.0.0.37" +local port = 12345 +local c = assert(socket.udp()) +--print(assert(c:setoption("reuseport", true))) +--print(assert(c:setsockname("*", port))) +--print(assert(c:setoption("ip-multicast-loop", false))) +--print(assert(c:setoption("ip-multicast-ttl", 4))) +--print(assert(c:setoption("ip-multicast-if", "10.0.1.3"))) +--print(assert(c:setoption("ip-add-membership", {multiaddr = group, interface = "*"}))) +local i = 0 +while 1 do + local message = string.format("hello all %d!", i) + assert(c:sendto(message, group, port)) + print("sent " .. message) + socket.sleep(1) + c:settimeout(0.5) + print(c:receivefrom()) + i = i + 1 +end diff --git a/samples/talker.lua b/samples/talker.lua index 901ed2c..607ff31 100644 --- a/samples/talker.lua +++ b/samples/talker.lua @@ -2,7 +2,7 @@ -- TCP sample: Little program to send text lines to a given host/port -- LuaSocket sample files -- Author: Diego Nehab --- RCS ID: $Id$ +-- RCS ID: $Id: talker.lua,v 1.9 2005/01/02 22:44:00 diego Exp $ ----------------------------------------------------------------------------- local socket = require("socket") host = host or "localhost" diff --git a/samples/tinyirc.lua b/samples/tinyirc.lua index dd2c6f8..f474302 100644 --- a/samples/tinyirc.lua +++ b/samples/tinyirc.lua @@ -2,7 +2,7 @@ -- Select sample: simple text line server -- LuaSocket sample files. -- Author: Diego Nehab --- RCS ID: $Id$ +-- RCS ID: $Id: tinyirc.lua,v 1.14 2005/11/22 08:33:29 diego Exp $ ----------------------------------------------------------------------------- local socket = require("socket") host = host or "*" diff --git a/src/auxiliar.c b/src/auxiliar.c index fcc7e23..9514970 100644 --- a/src/auxiliar.c +++ b/src/auxiliar.c @@ -2,7 +2,7 @@ * Auxiliar routines for class hierarchy manipulation * LuaSocket toolkit * -* RCS ID: $Id$ +* RCS ID: $Id: auxiliar.c,v 1.14 2005/10/07 04:40:59 diego Exp $ \*=========================================================================*/ #include #include diff --git a/src/buffer.c b/src/buffer.c index 5be0faf..fbe00eb 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -2,7 +2,7 @@ * Input/Output interface for Lua programs * LuaSocket toolkit * -* RCS ID: $Id$ +* RCS ID: $Id: buffer.c,v 1.29 2009/05/27 09:31:35 diego Exp $ \*=========================================================================*/ #include "lua.h" #include "lauxlib.h" diff --git a/src/except.c b/src/except.c index fc4c038..5faa5be 100644 --- a/src/except.c +++ b/src/except.c @@ -2,7 +2,7 @@ * Simple exception support * LuaSocket toolkit * -* RCS ID: $Id$ +* RCS ID: $Id: except.c,v 1.8 2005/09/29 06:11:41 diego Exp $ \*=========================================================================*/ #include diff --git a/src/ftp.lua b/src/ftp.lua index c90a65c..1d5ff77 100644 --- a/src/ftp.lua +++ b/src/ftp.lua @@ -2,7 +2,7 @@ -- FTP support for the Lua language -- LuaSocket toolkit. -- Author: Diego Nehab --- RCS ID: $Id$ +-- RCS ID: $Id: ftp.lua,v 1.45 2007/07/11 19:25:47 diego Exp $ ----------------------------------------------------------------------------- ----------------------------------------------------------------------------- diff --git a/src/headers.lua b/src/headers.lua new file mode 100644 index 0000000..f92ee7a --- /dev/null +++ b/src/headers.lua @@ -0,0 +1,100 @@ +----------------------------------------------------------------------------- +-- Canonic header field capitalization +-- LuaSocket toolkit. +-- Author: Diego Nehab +-- RCS ID: $Id$ +----------------------------------------------------------------------------- +module("socket.headers") + +canonic = { + ["accept"] = "Accept", + ["accept-charset"] = "Accept-Charset", + ["accept-encoding"] = "Accept-Encoding", + ["accept-language"] = "Accept-Language", + ["accept-ranges"] = "Accept-Ranges", + ["action"] = "Action", + ["alternate-recipient"] = "Alternate-Recipient", + ["age"] = "Age", + ["allow"] = "Allow", + ["arrival-date"] = "Arrival-Date", + ["authorization"] = "Authorization", + ["bcc"] = "Bcc", + ["cache-control"] = "Cache-Control", + ["cc"] = "Cc", + ["comments"] = "Comments", + ["connection"] = "Connection", + ["content-description"] = "Content-Description", + ["content-disposition"] = "Content-Disposition", + ["content-encoding"] = "Content-Encoding", + ["content-id"] = "Content-ID", + ["content-language"] = "Content-Language", + ["content-length"] = "Content-Length", + ["content-location"] = "Content-Location", + ["content-md5"] = "Content-MD5", + ["content-range"] = "Content-Range", + ["content-transfer-encoding"] = "Content-Transfer-Encoding", + ["content-type"] = "Content-Type", + ["date"] = "Date", + ["diagnostic-code"] = "Diagnostic-Code", + ["dsn-gateway"] = "DSN-Gateway", + ["etag"] = "ETag", + ["expect"] = "Expect", + ["expires"] = "Expires", + ["final-log-id"] = "Final-Log-ID", + ["final-recipient"] = "Final-Recipient", + ["from"] = "From", + ["host"] = "Host", + ["if-match"] = "If-Match", + ["if-modified-since"] = "If-Modified-Since", + ["if-none-match"] = "If-None-Match", + ["if-range"] = "If-Range", + ["if-unmodified-since"] = "If-Unmodified-Since", + ["in-reply-to"] = "In-Reply-To", + ["keywords"] = "Keywords", + ["last-attempt-date"] = "Last-Attempt-Date", + ["last-modified"] = "Last-Modified", + ["location"] = "Location", + ["max-forwards"] = "Max-Forwards", + ["message-id"] = "Message-ID", + ["mime-version"] = "MIME-Version", + ["original-envelope-id"] = "Original-Envelope-ID", + ["original-recipient"] = "Original-Recipient", + ["pragma"] = "Pragma", + ["proxy-authenticate"] = "Proxy-Authenticate", + ["proxy-authorization"] = "Proxy-Authorization", + ["range"] = "Range", + ["received"] = "Received", + ["received-from-mta"] = "Received-From-MTA", + ["references"] = "References", + ["referer"] = "Referer", + ["remote-mta"] = "Remote-MTA", + ["reply-to"] = "Reply-To", + ["reporting-mta"] = "Reporting-MTA", + ["resent-bcc"] = "Resent-Bcc", + ["resent-cc"] = "Resent-Cc", + ["resent-date"] = "Resent-Date", + ["resent-from"] = "Resent-From", + ["resent-message-id"] = "Resent-Message-ID", + ["resent-reply-to"] = "Resent-Reply-To", + ["resent-sender"] = "Resent-Sender", + ["resent-to"] = "Resent-To", + ["retry-after"] = "Retry-After", + ["return-path"] = "Return-Path", + ["sender"] = "Sender", + ["server"] = "Server", + ["smtp-remote-recipient"] = "SMTP-Remote-Recipient", + ["status"] = "Status", + ["subject"] = "Subject", + ["te"] = "TE", + ["to"] = "To", + ["trailer"] = "Trailer", + ["transfer-encoding"] = "Transfer-Encoding", + ["upgrade"] = "Upgrade", + ["user-agent"] = "User-Agent", + ["vary"] = "Vary", + ["via"] = "Via", + ["warning"] = "Warning", + ["will-retry-until"] = "Will-Retry-Until", + ["www-authenticate"] = "WWW-Authenticate", + ["x-mailer"] = "X-Mailer", +} diff --git a/src/http.lua b/src/http.lua index 4c27149..029a367 100644 --- a/src/http.lua +++ b/src/http.lua @@ -2,7 +2,7 @@ -- HTTP/1.1 client support for the Lua language. -- LuaSocket toolkit. -- Author: Diego Nehab --- RCS ID: $Id$ +-- RCS ID: $Id: http.lua,v 1.72 2009/05/27 09:31:35 diego Exp $ ----------------------------------------------------------------------------- ----------------------------------------------------------------------------- diff --git a/src/inet.c b/src/inet.c index 862288c..21a97c9 100644 --- a/src/inet.c +++ b/src/inet.c @@ -2,7 +2,7 @@ * Internet domain functions * LuaSocket toolkit * -* RCS ID: $Id$ +* RCS ID: $Id: inet.c,v 1.28 2005/10/07 04:40:59 diego Exp $ \*=========================================================================*/ #include #include @@ -16,14 +16,16 @@ * Internal function prototypes. \*=========================================================================*/ static int inet_global_toip(lua_State *L); +static int inet_global_toip6(lua_State *L); static int inet_global_tohostname(lua_State *L); static void inet_pushresolved(lua_State *L, struct hostent *hp); static int inet_global_gethostname(lua_State *L); /* DNS functions */ static luaL_reg func[] = { - { "toip", inet_global_toip }, - { "tohostname", inet_global_tohostname }, + { "toip", inet_global_toip}, + { "toip6", inet_global_toip6}, + { "tohostname", inet_global_tohostname}, { "gethostname", inet_global_gethostname}, { NULL, NULL} }; @@ -95,6 +97,50 @@ static int inet_global_toip(lua_State *L) return 2; } +static int inet_global_toip6(lua_State *L) +{ + const char *hostname = luaL_checkstring(L, 1); + struct addrinfo *iterator = NULL, *resolved = NULL; + struct addrinfo hints; + int i = 1, ret = 0; + memset(&hints, 0, sizeof(hints)); + hints.ai_socktype = SOCK_STREAM; + hints.ai_family = PF_UNSPEC; + ret = getaddrinfo(hostname, NULL, &hints, &resolved); + if (ret != 0) { + lua_pushnil(L); + lua_pushstring(L, "getaddrinfo returned error"); + return 2; + } + lua_newtable(L); + for (iterator = resolved; iterator; iterator = iterator->ai_next) { + char hbuf[NI_MAXHOST], sbuf[NI_MAXSERV]; + getnameinfo(iterator->ai_addr, iterator->ai_addrlen, hbuf, sizeof(hbuf), + sbuf, 0, NI_NUMERICHOST); + lua_pushnumber(L, i); + lua_newtable(L); + switch (iterator->ai_family) { + case AF_INET: + lua_pushliteral(L, "family"); + lua_pushliteral(L, "inet"); + lua_settable(L, -3); + break; + case AF_INET6: + lua_pushliteral(L, "family"); + lua_pushliteral(L, "inet6"); + lua_settable(L, -3); + break;; + } + lua_pushliteral(L, "addr"); + lua_pushstring(L, hbuf); + lua_settable(L, -3); + lua_settable(L, -3); + i++; + } + freeaddrinfo(resolved); + return 1; +} + /*-------------------------------------------------------------------------*\ * Gets the host name diff --git a/src/io.c b/src/io.c index 317cfd4..06dc50e 100644 --- a/src/io.c +++ b/src/io.c @@ -2,7 +2,7 @@ * Input/Output abstraction * LuaSocket toolkit * -* RCS ID: $Id$ +* RCS ID: $Id: io.c,v 1.6 2005/09/29 06:11:41 diego Exp $ \*=========================================================================*/ #include "io.h" diff --git a/src/ltn12.lua b/src/ltn12.lua index f10ad18..b42689a 100644 --- a/src/ltn12.lua +++ b/src/ltn12.lua @@ -2,7 +2,7 @@ -- LTN12 - Filters, sources, sinks and pumps. -- LuaSocket toolkit. -- Author: Diego Nehab --- RCS ID: $Id$ +-- RCS ID: $Id: ltn12.lua,v 1.31 2006/04/03 04:45:42 diego Exp $ ----------------------------------------------------------------------------- ----------------------------------------------------------------------------- diff --git a/src/luasocket.h b/src/luasocket.h index d7a78bb..3949421 100644 --- a/src/luasocket.h +++ b/src/luasocket.h @@ -11,8 +11,8 @@ /*-------------------------------------------------------------------------*\ * Current socket library version \*-------------------------------------------------------------------------*/ -#define LUASOCKET_VERSION "LuaSocket 2.0.3" -#define LUASOCKET_COPYRIGHT "Copyright (C) 1999-2009 Diego Nehab" +#define LUASOCKET_VERSION "LuaSocket 2.1.0" +#define LUASOCKET_COPYRIGHT "Copyright (C) 1999-2011 Diego Nehab" #define LUASOCKET_AUTHORS "Diego Nehab" /*-------------------------------------------------------------------------*\ diff --git a/src/mime.c b/src/mime.c index 1e8fded..218e6f7 100644 --- a/src/mime.c +++ b/src/mime.c @@ -2,7 +2,7 @@ * MIME support functions * LuaSocket toolkit * -* RCS ID: $Id$ +* RCS ID: $Id: mime.c,v 1.29 2009/05/27 09:31:35 diego Exp $ \*=========================================================================*/ #include diff --git a/src/mime.lua b/src/mime.lua index eb75db2..169eda2 100644 --- a/src/mime.lua +++ b/src/mime.lua @@ -2,7 +2,7 @@ -- MIME support for the Lua language. -- Author: Diego Nehab -- Conforming to RFCs 2045-2049 --- RCS ID: $Id$ +-- RCS ID: $Id: mime.lua,v 1.29 2007/06/11 23:44:54 diego Exp $ ----------------------------------------------------------------------------- ----------------------------------------------------------------------------- diff --git a/src/options.c b/src/options.c index 1d4c950..1f5afa8 100644 --- a/src/options.c +++ b/src/options.c @@ -2,7 +2,7 @@ * Common option interface * LuaSocket toolkit * -* RCS ID: $Id$ +* RCS ID: $Id: options.c,v 1.7 2009/05/27 09:31:35 diego Exp $ \*=========================================================================*/ #include diff --git a/src/select.c b/src/select.c index 8e47d0e..0931b73 100644 --- a/src/select.c +++ b/src/select.c @@ -2,7 +2,7 @@ * Select implementation * LuaSocket toolkit * -* RCS ID: $Id$ +* RCS ID: $Id: select.c,v 1.23 2009/05/27 09:31:35 diego Exp $ \*=========================================================================*/ #include @@ -95,8 +95,10 @@ static t_socket getfd(lua_State *L) { if (!lua_isnil(L, -1)) { lua_pushvalue(L, -2); lua_call(L, 1, 1); - if (lua_isnumber(L, -1)) - fd = (t_socket) lua_tonumber(L, -1); + if (lua_isnumber(L, -1)) { + double numfd = lua_tonumber(L, -1); + fd = (numfd >= 0.0)? (t_socket) numfd: SOCKET_INVALID; + } } lua_pop(L, 1); return fd; @@ -134,8 +136,13 @@ static void collect_fd(lua_State *L, int tab, int itab, fd = getfd(L); if (fd != SOCKET_INVALID) { /* make sure we don't overflow the fd_set */ +#ifdef _WIN32 if (n >= FD_SETSIZE) luaL_argerror(L, tab, "too many sockets"); +#else + if (fd >= FD_SETSIZE) + luaL_argerror(L, tab, "descriptor too large for set size"); +#endif FD_SET(fd, set); n++; /* keep track of the largest descriptor so far */ diff --git a/src/smtp.lua b/src/smtp.lua index b39f5d6..e258d62 100644 --- a/src/smtp.lua +++ b/src/smtp.lua @@ -2,7 +2,7 @@ -- SMTP client support for the Lua language. -- LuaSocket toolkit. -- Author: Diego Nehab --- RCS ID: $Id$ +-- RCS ID: $Id: smtp.lua,v 1.47 2009/05/27 09:31:35 diego Exp $ ----------------------------------------------------------------------------- ----------------------------------------------------------------------------- diff --git a/src/socket.h b/src/socket.h index 425628d..e325952 100644 --- a/src/socket.h +++ b/src/socket.h @@ -59,6 +59,7 @@ int socket_accept(p_socket ps, p_socket pa, SA *addr, socklen_t *addr_len, p_timeout tm); const char *socket_hoststrerror(int err); +const char *socket_gaistrerror(int err); const char *socket_strerror(int err); /* these are perfect to use with the io abstraction module diff --git a/src/socket.lua b/src/socket.lua index 458418e..211adcd 100644 --- a/src/socket.lua +++ b/src/socket.lua @@ -1,7 +1,7 @@ ----------------------------------------------------------------------------- -- LuaSocket helper module -- Author: Diego Nehab --- RCS ID: $Id$ +-- RCS ID: $Id: socket.lua,v 1.22 2005/11/22 08:33:29 diego Exp $ ----------------------------------------------------------------------------- ----------------------------------------------------------------------------- diff --git a/src/tcp.c b/src/tcp.c index 06d687b..3204b40 100644 --- a/src/tcp.c +++ b/src/tcp.c @@ -2,7 +2,7 @@ * TCP object * LuaSocket toolkit * -* RCS ID: $Id$ +* RCS ID: $Id: tcp.c,v 1.42 2009/05/27 09:31:35 diego Exp $ \*=========================================================================*/ #include @@ -19,6 +19,8 @@ * Internal function prototypes \*=========================================================================*/ static int global_create(lua_State *L); +static int global_connect6(lua_State *L); +static int global_bind6(lua_State *L); static int meth_connect(lua_State *L); static int meth_listen(lua_State *L); static int meth_bind(lua_State *L); @@ -75,6 +77,8 @@ static t_opt optset[] = { /* functions in library namespace */ static luaL_reg func[] = { {"tcp", global_create}, + {"connect6", global_connect6}, + {"bind6", global_bind6}, {NULL, NULL} }; @@ -208,6 +212,7 @@ static int meth_bind(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); unsigned short port = (unsigned short) luaL_checknumber(L, 3); @@ -220,7 +225,6 @@ static int meth_connect(lua_State *L) lua_pushstring(L, err); return 2; } - /* turn master object into a client object */ lua_pushnumber(L, 1); return 1; } @@ -313,8 +317,7 @@ static int meth_settimeout(lua_State *L) /*-------------------------------------------------------------------------*\ * Creates a master tcp object \*-------------------------------------------------------------------------*/ -static int global_create(lua_State *L) -{ +static int global_create(lua_State *L) { t_socket sock; const char *err = inet_trycreate(&sock, SOCK_STREAM); /* try to allocate a system socket */ @@ -337,3 +340,173 @@ static int global_create(lua_State *L) return 2; } } + +static const char *trybind6(const char *localaddr, const char *localserv, + struct addrinfo *bindhints, p_tcp tcp) { + struct addrinfo *iterator = NULL, *resolved = NULL; + const char *err = NULL; + /* translate luasocket special values to C */ + if (strcmp(localaddr, "*") == 0) localaddr = NULL; + if (!localserv) localserv = "0"; + /* try resolving */ + err = socket_gaistrerror(getaddrinfo(localaddr, localserv, + bindhints, &resolved)); + if (err) { + if (resolved) freeaddrinfo(resolved); + return err; + } + /* iterate over resolved addresses until one is good */ + for (iterator = resolved; iterator; iterator = iterator->ai_next) { + /* create a new socket each time because parameters + * may have changed */ + const char *err = socket_strerror(socket_create(&tcp->sock, + iterator->ai_family, iterator->ai_socktype, + iterator->ai_protocol)); + /* if failed to create socket, bail out */ + if (err != NULL) { + freeaddrinfo(resolved); + return err; + } + /* all sockets are set as non-blocking initially */ + socket_setnonblocking(&tcp->sock); + /* try binding to local address */ + err = socket_strerror(socket_bind(&tcp->sock, + (SA *) iterator->ai_addr, + iterator->ai_addrlen)); + /* if faiiled, we try the next one */ + if (err != NULL) socket_destroy(&tcp->sock); + /* if success, we abort loop */ + else break; + } + /* at this point, if err is not set, se succeeded */ + if (err == NULL) { + /* save family of chosen local address */ + bindhints->ai_family = iterator->ai_family; + } + /* cleanup and return error */ + freeaddrinfo(resolved); + return err; +} + +static int global_bind6(lua_State *L) { + const char *localaddr = luaL_checkstring(L, 1); + const char *localserv = luaL_checkstring(L, 2); + int backlog = luaL_checkint(L, 3); + p_tcp tcp = (p_tcp) lua_newuserdata(L, sizeof(t_tcp)); + struct addrinfo bindhints; + const char *err = NULL; + /* initialize tcp structure */ + 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->sock = SOCKET_INVALID; + /* try binding to local address */ + memset(&bindhints, 0, sizeof(bindhints)); + bindhints.ai_socktype = SOCK_STREAM; + bindhints.ai_family = PF_UNSPEC; + bindhints.ai_flags = AI_PASSIVE; + err = trybind6(localaddr, localserv, &bindhints, tcp); + if (err == NULL) { + /* all server sockets initially with reuseaddr set */ + int val = 1; + setsockopt(tcp->sock, SOL_SOCKET, SO_REUSEADDR, + (char *) &val, sizeof(val)); + /* set the backlog and listen */ + err = socket_strerror(socket_listen(&tcp->sock, backlog)); + if (err) { + socket_destroy(&tcp->sock); + lua_pushnil(L); + lua_pushstring(L, err); + return 2; + } + auxiliar_setclass(L, "tcp{server}", -1); + return 1; + } else { + lua_pushnil(L); + lua_pushstring(L, err); + return 2; + } +} + +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) { + const char *err = socket_strerror(socket_create(&tcp->sock, + iterator->ai_family, iterator->ai_socktype, + iterator->ai_protocol)); + if (err != NULL) { + freeaddrinfo(resolved); + return err; + } + /* 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, + 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_connect6(lua_State *L) { + const char *remoteaddr = luaL_checkstring(L, 1); + const char *remoteserv = luaL_checkstring(L, 2); + const char *localaddr = luaL_optstring(L, 3, NULL); + const char *localserv = luaL_optstring(L, 4, "0"); + p_tcp tcp = (p_tcp) lua_newuserdata(L, sizeof(t_tcp)); + struct addrinfo bindhints, connecthints; + const char *err = NULL; + /* initialize tcp structure */ + 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->sock = SOCKET_INVALID; + /* allow user to pick local address and port */ + memset(&bindhints, 0, sizeof(bindhints)); + bindhints.ai_socktype = SOCK_STREAM; + bindhints.ai_family = PF_UNSPEC; + bindhints.ai_flags = AI_PASSIVE; + if (localaddr) { + err = trybind6(localaddr, localserv, &bindhints, tcp); + if (err) { + lua_pushnil(L); + lua_pushstring(L, err); + return 2; + } + } + /* 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); + if (err) { + socket_destroy(&tcp->sock); + lua_pushnil(L); + lua_pushstring(L, err); + return 2; + } + auxiliar_setclass(L, "tcp{client}", -1); + return 1; +} diff --git a/src/timeout.c b/src/timeout.c index fb015f9..cc7309c 100644 --- a/src/timeout.c +++ b/src/timeout.c @@ -2,7 +2,7 @@ * Timeout management functions * LuaSocket toolkit * -* RCS ID: $Id$ +* RCS ID: $Id: timeout.c,v 1.31 2009/05/27 09:31:35 diego Exp $ \*=========================================================================*/ #include #include diff --git a/src/tp.lua b/src/tp.lua index 46f7f64..adeb4b0 100644 --- a/src/tp.lua +++ b/src/tp.lua @@ -2,7 +2,7 @@ -- Unified SMTP/FTP subsystem -- LuaSocket toolkit. -- Author: Diego Nehab --- RCS ID: $Id$ +-- RCS ID: $Id: tp.lua,v 1.23 2009/05/27 09:31:35 diego Exp $ ----------------------------------------------------------------------------- ----------------------------------------------------------------------------- diff --git a/src/udp.c b/src/udp.c index db519ca..e3c86e7 100644 --- a/src/udp.c +++ b/src/udp.c @@ -2,7 +2,7 @@ * UDP object * LuaSocket toolkit * -* RCS ID: $Id$ +* RCS ID: $Id: udp.c,v 1.30 2009/05/27 09:31:35 diego Exp $ \*=========================================================================*/ #include diff --git a/src/unix.c b/src/unix.c index a309823..6962517 100644 --- a/src/unix.c +++ b/src/unix.c @@ -2,7 +2,7 @@ * Unix domain socket * LuaSocket toolkit * -* RCS ID: $Id$ +* RCS ID: $Id: unix.c,v 1.14 2009/05/27 09:31:35 diego Exp $ \*=========================================================================*/ #include diff --git a/src/url.lua b/src/url.lua index 7623557..2158796 100644 --- a/src/url.lua +++ b/src/url.lua @@ -2,7 +2,7 @@ -- URI parsing, composition and relative URL resolution -- LuaSocket toolkit. -- Author: Diego Nehab --- RCS ID: $Id$ +-- RCS ID: $Id: url.lua,v 1.38 2006/04/03 04:45:42 diego Exp $ ----------------------------------------------------------------------------- ----------------------------------------------------------------------------- @@ -195,13 +195,7 @@ function build(parsed) end if userinfo then authority = userinfo .. "@" .. authority end end - if authority then - if string.sub(url, 1, 1) == "/" then - url = "//" .. authority .. url - else - url = "//" .. authority .. "/" .. url - end - end + if authority then url = "//" .. authority .. url end if parsed.scheme then url = parsed.scheme .. ":" .. url end if parsed.fragment then url = url .. "#" .. parsed.fragment end -- url = string.gsub(url, "%s", "") @@ -217,8 +211,8 @@ end -- corresponding absolute url ----------------------------------------------------------------------------- function absolute(base_url, relative_url) - local base_parsed = base_url if base.type(base_url) == "table" then + base_parsed = base_url base_url = build(base_parsed) else base_parsed = parse(base_url) diff --git a/src/usocket.c b/src/usocket.c index 1ba1043..5201b7b 100644 --- a/src/usocket.c +++ b/src/usocket.c @@ -6,7 +6,7 @@ * The penalty of calling select to avoid busy-wait is only paid when * the I/O call fail in the first place. * -* RCS ID: $Id$ +* RCS ID: $Id: usocket.c,v 1.38 2007/10/13 23:55:20 diego Exp $ \*=========================================================================*/ #include #include @@ -368,3 +368,24 @@ const char *socket_ioerror(p_socket ps, int err) { (void) ps; return socket_strerror(err); } + +const char *socket_gaistrerror(int err) { + if (err == 0) return NULL; + switch (err) { + case EAI_AGAIN: return "temporary failure in name resolution"; + case EAI_BADFLAGS: return "invalid value for ai_flags"; + case EAI_BADHINTS: return "invalid value for hints"; + case EAI_FAIL: return "non-recoverable failure in name resolution"; + case EAI_FAMILY: return "ai_family not supported"; + case EAI_MEMORY: return "memory allocation failure"; + case EAI_NONAME: + return "hostname or servname not provided, or not known"; + case EAI_OVERFLOW: return "argument buffer overflow"; + case EAI_PROTOCOL: return "resolved protocol is unknown"; + case EAI_SERVICE: return "servname not supported for socktype"; + case EAI_SOCKTYPE: return "ai_socktype not supported"; + case EAI_SYSTEM: return strerror(errno); + default: return "unknown error"; + } +} + diff --git a/src/wsocket.c b/src/wsocket.c index 2d07904..c82882a 100644 --- a/src/wsocket.c +++ b/src/wsocket.c @@ -5,7 +5,7 @@ * The penalty of calling select to avoid busy-wait is only paid when * the I/O call fail in the first place. * -* RCS ID: $Id$ +* RCS ID: $Id: wsocket.c,v 1.36 2007/06/11 23:44:54 diego Exp $ \*=========================================================================*/ #include