diff options
| author | Diego Nehab <diego@tecgraf.puc-rio.br> | 2003-06-26 18:47:49 +0000 |
|---|---|---|
| committer | Diego Nehab <diego@tecgraf.puc-rio.br> | 2003-06-26 18:47:49 +0000 |
| commit | 71f6bb60bf2b7457091c7106190f92ab7e51f7c6 (patch) | |
| tree | 8ad3668667bd3da3c34f7ff7ae0a9a7a4daa4679 | |
| parent | f330540576031528f0daac231c61d4dd06e8ba1e (diff) | |
| download | luasocket-71f6bb60bf2b7457091c7106190f92ab7e51f7c6.tar.gz luasocket-71f6bb60bf2b7457091c7106190f92ab7e51f7c6.tar.bz2 luasocket-71f6bb60bf2b7457091c7106190f92ab7e51f7c6.zip | |
Finished implementation of LuaSocket 2.0 alpha on Linux.
Some testing still needed.
41 files changed, 692 insertions, 331 deletions
| @@ -8,7 +8,9 @@ a given domain/family and protocol. Then connect or bind if needed. Then | |||
| 8 | use IO functions. | 8 | use IO functions. |
| 9 | 9 | ||
| 10 | All functions return a non-nil value as first return value if successful. | 10 | All functions return a non-nil value as first return value if successful. |
| 11 | All functions return nil followed by error message in case of error. | 11 | All functions return whatever could be retrieved followed by error message |
| 12 | in case of error. The best way to check for errors is to check for the | ||
| 13 | presence of an error message. | ||
| 12 | WARNING: The send function was affected. | 14 | WARNING: The send function was affected. |
| 13 | 15 | ||
| 14 | Better error messages and parameter checking. | 16 | Better error messages and parameter checking. |
| @@ -1,24 +1,26 @@ | |||
| 1 | - Melhorar a interface de setoptions (aceitar nada como true, por exemplo) | ||
| 1 | - Inicializaccao das classes pode falhar? | 2 | - Inicializaccao das classes pode falhar? |
| 2 | - Ajeitar melhor a hierarquia de classes. Ajeitar o file... | 3 | - Ajeitar melhor a hierarquia de classes. Ajeitar o file... |
| 4 | - GARBAGE COLLECTOR! | ||
| 5 | - Adicionar um método sock:setoption??? | ||
| 6 | - testar em várias plataformas | ||
| 7 | - adicionar exemplos de expansão: pipe, local, named pipe | ||
| 3 | 8 | ||
| 4 | * Como mostrar um erro em lua_socketlibopen()... | 9 | * Como mostrar um erro em lua_socketlibopen()... |
| 5 | * O location do "redirect" pode ser relativo ao servidor atual (não pode, | 10 | * O location do "redirect" pode ser relativo ao servidor atual (não pode, |
| 6 | mas os servidores fazem merda...) | 11 | mas os servidores fazem merda...) |
| 7 | * - Ajeitar para Lua 4.1 | 12 | * Ajeitar para Lua 5.0 |
| 13 | * Padronizar os retornos de funccao | ||
| 14 | * Separar as classes em arquivos | ||
| 15 | * Retorno de sendto em datagram sockets pode ser refused | ||
| 16 | * Fazer compilar com g++ | ||
| 8 | 17 | ||
| 9 | - Padronizar os retornos de funccao | ||
| 10 | - Thread-safe | 18 | - Thread-safe |
| 11 | - proteger gethostby*.* com um mutex GLOBAL! | 19 | - proteger gethostby*.* com um mutex GLOBAL! |
| 12 | - proteger o atomizar o conjunto (timedout, receive), (timedout, send) | 20 | - proteger ou atomizar o conjunto (timedout, receive), (timedout, send) |
| 13 | - Usar "require" nos módulos | 21 | - inet_ntoa também é uma merda. |
| 14 | - SSL | 22 | - SSL |
| 15 | - Fazer compilar com g++ | 23 | - Proxy support pro http |
| 16 | - usar lua_verror | ||
| 17 | - separar as classes em arquivos | ||
| 18 | - criar mais uma classe, a de stream, entre p_sock e p_client | ||
| 19 | - criar um internal include file ls.h | ||
| 20 | - impedir que voe quando chamar accept(udpsocket()) | ||
| 21 | - trocar recv and send por read e write (ver se funciona) | ||
| 22 | 24 | ||
| 23 | - checar operações em closed sockets | 25 | - checar operações em closed sockets |
| 24 | - checar teste de writable socket com select | 26 | - checar teste de writable socket com select |
| @@ -34,6 +36,4 @@ | |||
| 34 | - unix 92 bytes maximo no endereço, incluindo o zero | 36 | - unix 92 bytes maximo no endereço, incluindo o zero |
| 35 | - unix 9216 maximo de datagram size | 37 | - unix 9216 maximo de datagram size |
| 36 | 38 | ||
| 37 | - retorno de send/receive em datagram sockets pode ser refused... | ||
| 38 | 39 | ||
| 39 | - adicionar um método sock:setoption??? | ||
diff --git a/etc/check-links.lua b/etc/check-links.lua index 4c96fdc..c45131c 100644 --- a/etc/check-links.lua +++ b/etc/check-links.lua | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | ----------------------------------------------------------------------------- | 1 | ----------------------------------------------------------------------------- |
| 2 | -- Little program that checks links in HTML files | 2 | -- Little program that checks links in HTML files |
| 3 | -- LuaSocket 1.5 sample files. | 3 | -- LuaSocket sample files |
| 4 | -- Author: Diego Nehab | 4 | -- Author: Diego Nehab |
| 5 | -- RCS ID: $Id$ | 5 | -- RCS ID: $Id$ |
| 6 | ----------------------------------------------------------------------------- | 6 | ----------------------------------------------------------------------------- |
diff --git a/etc/dict.lua b/etc/dict.lua index 89bdb4f..9926538 100644 --- a/etc/dict.lua +++ b/etc/dict.lua | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | ----------------------------------------------------------------------------- | 1 | ----------------------------------------------------------------------------- |
| 2 | -- Little program to download DICT word definitions | 2 | -- Little program to download DICT word definitions |
| 3 | -- LuaSocket 1.5 sample files | 3 | -- LuaSocket sample files |
| 4 | -- Author: Diego Nehab | 4 | -- Author: Diego Nehab |
| 5 | -- RCS ID: $Id$ | 5 | -- RCS ID: $Id$ |
| 6 | ----------------------------------------------------------------------------- | 6 | ----------------------------------------------------------------------------- |
diff --git a/etc/get.lua b/etc/get.lua index e972d16..caaa607 100644 --- a/etc/get.lua +++ b/etc/get.lua | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | ----------------------------------------------------------------------------- | 1 | ----------------------------------------------------------------------------- |
| 2 | -- Little program to download files from URLs | 2 | -- Little program to download files from URLs |
| 3 | -- LuaSocket 1.5 sample files | 3 | -- LuaSocket sample files |
| 4 | -- Author: Diego Nehab | 4 | -- Author: Diego Nehab |
| 5 | -- RCS ID: $Id$ | 5 | -- RCS ID: $Id$ |
| 6 | ----------------------------------------------------------------------------- | 6 | ----------------------------------------------------------------------------- |
diff --git a/etc/tftp.lua b/etc/tftp.lua index a0db68e..d1b5594 100644 --- a/etc/tftp.lua +++ b/etc/tftp.lua | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | ----------------------------------------------------------------------------- | 1 | ----------------------------------------------------------------------------- |
| 2 | -- TFTP support for the Lua language | 2 | -- TFTP support for the Lua language |
| 3 | -- LuaSocket 1.5 toolkit. | 3 | -- LuaSocket toolkit. |
| 4 | -- Author: Diego Nehab | 4 | -- Author: Diego Nehab |
| 5 | -- Conforming to: RFC 783, LTN7 | 5 | -- Conforming to: RFC 783, LTN7 |
| 6 | -- RCS ID: $Id$ | 6 | -- RCS ID: $Id$ |
diff --git a/samples/daytimeclnt.lua b/samples/daytimeclnt.lua index 85ddca1..5064fff 100644 --- a/samples/daytimeclnt.lua +++ b/samples/daytimeclnt.lua | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | ----------------------------------------------------------------------------- | 1 | ----------------------------------------------------------------------------- |
| 2 | -- UDP sample: daytime protocol client | 2 | -- UDP sample: daytime protocol client |
| 3 | -- LuaSocket 1.5 sample files. | 3 | -- LuaSocket sample files |
| 4 | -- Author: Diego Nehab | 4 | -- Author: Diego Nehab |
| 5 | -- RCS ID: $Id$ | 5 | -- RCS ID: $Id$ |
| 6 | ----------------------------------------------------------------------------- | 6 | ----------------------------------------------------------------------------- |
diff --git a/samples/echoclnt.lua b/samples/echoclnt.lua index bca0b4d..e028b86 100644 --- a/samples/echoclnt.lua +++ b/samples/echoclnt.lua | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | ----------------------------------------------------------------------------- | 1 | ----------------------------------------------------------------------------- |
| 2 | -- UDP sample: echo protocol client | 2 | -- UDP sample: echo protocol client |
| 3 | -- LuaSocket 1.5 sample files | 3 | -- LuaSocket sample files |
| 4 | -- Author: Diego Nehab | 4 | -- Author: Diego Nehab |
| 5 | -- RCS ID: $Id$ | 5 | -- RCS ID: $Id$ |
| 6 | ----------------------------------------------------------------------------- | 6 | ----------------------------------------------------------------------------- |
diff --git a/samples/echosrvr.lua b/samples/echosrvr.lua index 18bd84e..127ccb8 100644 --- a/samples/echosrvr.lua +++ b/samples/echosrvr.lua | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | ----------------------------------------------------------------------------- | 1 | ----------------------------------------------------------------------------- |
| 2 | -- UDP sample: echo protocol server | 2 | -- UDP sample: echo protocol server |
| 3 | -- LuaSocket 1.5 sample files | 3 | -- LuaSocket sample files |
| 4 | -- Author: Diego Nehab | 4 | -- Author: Diego Nehab |
| 5 | -- RCS ID: $Id$ | 5 | -- RCS ID: $Id$ |
| 6 | ----------------------------------------------------------------------------- | 6 | ----------------------------------------------------------------------------- |
diff --git a/samples/listener.lua b/samples/listener.lua index 4846419..dff4d25 100644 --- a/samples/listener.lua +++ b/samples/listener.lua | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | ----------------------------------------------------------------------------- | 1 | ----------------------------------------------------------------------------- |
| 2 | -- TCP sample: Little program to dump lines received at a given port | 2 | -- TCP sample: Little program to dump lines received at a given port |
| 3 | -- LuaSocket 1.5 sample files | 3 | -- LuaSocket sample files |
| 4 | -- Author: Diego Nehab | 4 | -- Author: Diego Nehab |
| 5 | -- RCS ID: $Id$ | 5 | -- RCS ID: $Id$ |
| 6 | ----------------------------------------------------------------------------- | 6 | ----------------------------------------------------------------------------- |
diff --git a/samples/talker.lua b/samples/talker.lua index c7a239a..1b0652f 100644 --- a/samples/talker.lua +++ b/samples/talker.lua | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | ----------------------------------------------------------------------------- | 1 | ----------------------------------------------------------------------------- |
| 2 | -- TCP sample: Little program to send text lines to a given host/port | 2 | -- TCP sample: Little program to send text lines to a given host/port |
| 3 | -- LuaSocket 1.5 sample files | 3 | -- LuaSocket sample files |
| 4 | -- Author: Diego Nehab | 4 | -- Author: Diego Nehab |
| 5 | -- RCS ID: $Id$ | 5 | -- RCS ID: $Id$ |
| 6 | ----------------------------------------------------------------------------- | 6 | ----------------------------------------------------------------------------- |
diff --git a/samples/tinyirc.lua b/samples/tinyirc.lua index 0b20303..0ad00ab 100644 --- a/samples/tinyirc.lua +++ b/samples/tinyirc.lua | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | ----------------------------------------------------------------------------- | 1 | ----------------------------------------------------------------------------- |
| 2 | -- Select sample: simple text line server | 2 | -- Select sample: simple text line server |
| 3 | -- LuaSocket 1.5 sample files. | 3 | -- LuaSocket sample files. |
| 4 | -- Author: Diego Nehab | 4 | -- Author: Diego Nehab |
| 5 | -- RCS ID: $Id$ | 5 | -- RCS ID: $Id$ |
| 6 | ----------------------------------------------------------------------------- | 6 | ----------------------------------------------------------------------------- |
diff --git a/src/auxiliar.c b/src/auxiliar.c index 96138f1..8b2fa37 100644 --- a/src/auxiliar.c +++ b/src/auxiliar.c | |||
| @@ -1,142 +1,167 @@ | |||
| 1 | /*=========================================================================*\ | 1 | /*=========================================================================*\ |
| 2 | * Auxiliar routines for class hierarchy manipulation | 2 | * Auxiliar routines for class hierarchy manipulation |
| 3 | * LuaSocket toolkit | ||
| 3 | * | 4 | * |
| 4 | * RCS ID: $Id$ | 5 | * RCS ID: $Id$ |
| 5 | \*=========================================================================*/ | 6 | \*=========================================================================*/ |
| 7 | #include <string.h> | ||
| 8 | |||
| 9 | #include "luasocket.h" | ||
| 6 | #include "auxiliar.h" | 10 | #include "auxiliar.h" |
| 7 | 11 | ||
| 8 | /*=========================================================================*\ | 12 | /*=========================================================================*\ |
| 9 | * Exported functions | 13 | * Exported functions |
| 10 | \*=========================================================================*/ | 14 | \*=========================================================================*/ |
| 11 | /*-------------------------------------------------------------------------*\ | 15 | /*-------------------------------------------------------------------------*\ |
| 12 | * Creates a new class. A class has methods given by the func array and the | 16 | * Initializes the module |
| 13 | * field 'class' tells the object class. The table 'group' list the class | ||
| 14 | * groups the object belongs to. | ||
| 15 | \*-------------------------------------------------------------------------*/ | 17 | \*-------------------------------------------------------------------------*/ |
| 16 | void aux_newclass(lua_State *L, const char *name, luaL_reg *func) | 18 | void aux_open(lua_State *L) |
| 17 | { | 19 | { |
| 18 | lua_pushstring(L, name); | 20 | /* create namespace table */ |
| 19 | lua_newtable(L); | 21 | lua_pushstring(L, LUASOCKET_LIBNAME); |
| 20 | lua_pushstring(L, "__index"); | ||
| 21 | lua_newtable(L); | 22 | lua_newtable(L); |
| 22 | luaL_openlib(L, NULL, func, 0); | 23 | #ifdef LUASOCKET_DEBUG |
| 23 | lua_pushstring(L, "class"); | 24 | lua_pushstring(L, "debug"); |
| 24 | lua_pushstring(L, name); | 25 | lua_pushnumber(L, 1); |
| 25 | lua_rawset(L, -3); | ||
| 26 | lua_pushstring(L, "group"); | ||
| 27 | lua_newtable(L); | ||
| 28 | lua_rawset(L, -3); | ||
| 29 | lua_rawset(L, -3); | 26 | lua_rawset(L, -3); |
| 30 | lua_rawset(L, LUA_REGISTRYINDEX); | 27 | #endif |
| 28 | lua_settable(L, LUA_GLOBALSINDEX); | ||
| 29 | /* make sure modules know what is our namespace */ | ||
| 30 | lua_pushstring(L, "LUASOCKET_LIBNAME"); | ||
| 31 | lua_pushstring(L, LUASOCKET_LIBNAME); | ||
| 32 | lua_settable(L, LUA_GLOBALSINDEX); | ||
| 31 | } | 33 | } |
| 32 | 34 | ||
| 33 | /*-------------------------------------------------------------------------*\ | 35 | /*-------------------------------------------------------------------------*\ |
| 34 | * Add group to object list of groups. | 36 | * Creates a new class with given methods |
| 35 | \*-------------------------------------------------------------------------*/ | 37 | \*-------------------------------------------------------------------------*/ |
| 36 | void aux_add2group(lua_State *L, const char *name, const char *group) | 38 | void aux_newclass(lua_State *L, const char *classname, luaL_reg *func) |
| 37 | { | 39 | { |
| 38 | lua_pushstring(L, name); | 40 | luaL_newmetatable(L, classname); /* mt */ |
| 39 | lua_rawget(L, LUA_REGISTRYINDEX); | 41 | lua_pushstring(L, "__index"); /* mt,"__index" */ |
| 40 | lua_pushstring(L, "__index"); | 42 | lua_newtable(L); /* mt,"__index",it */ |
| 41 | lua_rawget(L, -2); | 43 | luaL_openlib(L, NULL, func, 0); |
| 42 | lua_pushstring(L, "group"); | 44 | #ifdef LUASOCKET_DEBUG |
| 43 | lua_rawget(L, -2); | 45 | lua_pushstring(L, "class"); /* mt,"__index",it,"class" */ |
| 44 | lua_pushstring(L, group); | 46 | lua_pushstring(L, classname); /* mt,"__index",it,"class",classname */ |
| 45 | lua_pushnumber(L, 1); | 47 | lua_rawset(L, -3); /* mt,"__index",it */ |
| 48 | #endif | ||
| 49 | /* get __gc method from class and use it for garbage collection */ | ||
| 50 | lua_pushstring(L, "__gc"); /* mt,"__index",it,"__gc" */ | ||
| 51 | lua_pushstring(L, "__gc"); /* mt,"__index",it,"__gc","__gc" */ | ||
| 52 | lua_rawget(L, -3); /* mt,"__index",it,"__gc",fn */ | ||
| 53 | lua_rawset(L, -5); /* mt,"__index",it */ | ||
| 54 | lua_rawset(L, -3); /* mt */ | ||
| 55 | lua_pop(L, 1); | ||
| 56 | } | ||
| 57 | |||
| 58 | /*-------------------------------------------------------------------------*\ | ||
| 59 | * Insert class into group | ||
| 60 | \*-------------------------------------------------------------------------*/ | ||
| 61 | void aux_add2group(lua_State *L, const char *classname, const char *groupname) | ||
| 62 | { | ||
| 63 | luaL_getmetatable(L, classname); | ||
| 64 | lua_pushstring(L, groupname); | ||
| 65 | lua_pushboolean(L, 1); | ||
| 46 | lua_rawset(L, -3); | 66 | lua_rawset(L, -3); |
| 47 | lua_pop(L, 3); | 67 | lua_pop(L, 1); |
| 68 | } | ||
| 69 | |||
| 70 | /*-------------------------------------------------------------------------*\ | ||
| 71 | * Make sure argument is a boolean | ||
| 72 | \*-------------------------------------------------------------------------*/ | ||
| 73 | int aux_checkboolean(lua_State *L, int objidx) | ||
| 74 | { | ||
| 75 | if (!lua_isboolean(L, objidx)) | ||
| 76 | luaL_typerror(L, objidx, lua_typename(L, LUA_TBOOLEAN)); | ||
| 77 | return lua_toboolean(L, objidx); | ||
| 48 | } | 78 | } |
| 49 | 79 | ||
| 50 | /*-------------------------------------------------------------------------*\ | 80 | /*-------------------------------------------------------------------------*\ |
| 51 | * Get a userdata making sure the object belongs to a given class. | 81 | * Calls appropriate option handler |
| 52 | \*-------------------------------------------------------------------------*/ | 82 | \*-------------------------------------------------------------------------*/ |
| 53 | void *aux_checkclass(lua_State *L, const char *name, int objidx) | 83 | int aux_meth_setoption(lua_State *L, luaL_reg *opt) |
| 54 | { | 84 | { |
| 55 | void *data = aux_getclassudata(L, name, objidx); | 85 | const char *name = luaL_checkstring(L, 2); /* obj, name, args */ |
| 86 | while (opt->name && strcmp(name, opt->name)) | ||
| 87 | opt++; | ||
| 88 | if (!opt->func) { | ||
| 89 | char msg[45]; | ||
| 90 | sprintf(msg, "unknown option `%.35s'", name); | ||
| 91 | luaL_argerror(L, 2, msg); | ||
| 92 | } | ||
| 93 | lua_remove(L, 2); /* obj, args */ | ||
| 94 | lua_pushcfunction(L, opt->func); /* obj, args, func */ | ||
| 95 | lua_insert(L, 1); /* func, obj, args */ | ||
| 96 | lua_call(L, lua_gettop(L)-1, LUA_MULTRET); | ||
| 97 | return lua_gettop(L); | ||
| 98 | } | ||
| 99 | |||
| 100 | /*-------------------------------------------------------------------------*\ | ||
| 101 | * Return userdata pointer if object belongs to a given class, abort with | ||
| 102 | * error otherwise | ||
| 103 | \*-------------------------------------------------------------------------*/ | ||
| 104 | void *aux_checkclass(lua_State *L, const char *classname, int objidx) | ||
| 105 | { | ||
| 106 | void *data = aux_getclassudata(L, classname, objidx); | ||
| 56 | if (!data) { | 107 | if (!data) { |
| 57 | char msg[45]; | 108 | char msg[45]; |
| 58 | sprintf(msg, "%.35s expected", name); | 109 | sprintf(msg, "%.35s expected", classname); |
| 59 | luaL_argerror(L, objidx, msg); | 110 | luaL_argerror(L, objidx, msg); |
| 60 | } | 111 | } |
| 61 | return data; | 112 | return data; |
| 62 | } | 113 | } |
| 63 | 114 | ||
| 64 | /*-------------------------------------------------------------------------*\ | 115 | /*-------------------------------------------------------------------------*\ |
| 65 | * Get a userdata making sure the object belongs to a given group. | 116 | * Return userdata pointer if object belongs to a given group, abort with |
| 117 | * error otherwise | ||
| 66 | \*-------------------------------------------------------------------------*/ | 118 | \*-------------------------------------------------------------------------*/ |
| 67 | void *aux_checkgroup(lua_State *L, const char *group, int objidx) | 119 | void *aux_checkgroup(lua_State *L, const char *groupname, int objidx) |
| 68 | { | 120 | { |
| 69 | void *data = aux_getgroupudata(L, group, objidx); | 121 | void *data = aux_getgroupudata(L, groupname, objidx); |
| 70 | if (!data) { | 122 | if (!data) { |
| 71 | char msg[45]; | 123 | char msg[45]; |
| 72 | sprintf(msg, "%.35s expected", group); | 124 | sprintf(msg, "%.35s expected", groupname); |
| 73 | luaL_argerror(L, objidx, msg); | 125 | luaL_argerror(L, objidx, msg); |
| 74 | } | 126 | } |
| 75 | return data; | 127 | return data; |
| 76 | } | 128 | } |
| 77 | 129 | ||
| 78 | /*-------------------------------------------------------------------------*\ | 130 | /*-------------------------------------------------------------------------*\ |
| 79 | * Set object class. | 131 | * Set object class |
| 80 | \*-------------------------------------------------------------------------*/ | 132 | \*-------------------------------------------------------------------------*/ |
| 81 | void aux_setclass(lua_State *L, const char *name, int objidx) | 133 | void aux_setclass(lua_State *L, const char *classname, int objidx) |
| 82 | { | 134 | { |
| 83 | lua_pushstring(L, name); | 135 | luaL_getmetatable(L, classname); |
| 84 | lua_rawget(L, LUA_REGISTRYINDEX); | ||
| 85 | if (objidx < 0) objidx--; | 136 | if (objidx < 0) objidx--; |
| 86 | lua_setmetatable(L, objidx); | 137 | lua_setmetatable(L, objidx); |
| 87 | } | 138 | } |
| 88 | 139 | ||
| 89 | /*=========================================================================*\ | ||
| 90 | * Internal functions | ||
| 91 | \*=========================================================================*/ | ||
| 92 | /*-------------------------------------------------------------------------*\ | 140 | /*-------------------------------------------------------------------------*\ |
| 93 | * Get a userdata if object belongs to a given group. | 141 | * Get a userdata pointer if object belongs to a given group. Return NULL |
| 142 | * otherwise | ||
| 94 | \*-------------------------------------------------------------------------*/ | 143 | \*-------------------------------------------------------------------------*/ |
| 95 | void *aux_getgroupudata(lua_State *L, const char *group, int objidx) | 144 | void *aux_getgroupudata(lua_State *L, const char *groupname, int objidx) |
| 96 | { | 145 | { |
| 97 | if (!lua_getmetatable(L, objidx)) | 146 | if (!lua_getmetatable(L, objidx)) |
| 98 | return NULL; | ||
| 99 | lua_pushstring(L, "__index"); | ||
| 100 | lua_rawget(L, -2); | ||
| 101 | if (!lua_istable(L, -1)) { | ||
| 102 | lua_pop(L, 2); | ||
| 103 | return NULL; | ||
| 104 | } | ||
| 105 | lua_pushstring(L, "group"); | ||
| 106 | lua_rawget(L, -2); | ||
| 107 | if (!lua_istable(L, -1)) { | ||
| 108 | lua_pop(L, 3); | ||
| 109 | return NULL; | 147 | return NULL; |
| 110 | } | 148 | lua_pushstring(L, groupname); |
| 111 | lua_pushstring(L, group); | ||
| 112 | lua_rawget(L, -2); | 149 | lua_rawget(L, -2); |
| 113 | if (lua_isnil(L, -1)) { | 150 | if (lua_isnil(L, -1)) { |
| 114 | lua_pop(L, 4); | 151 | lua_pop(L, 2); |
| 115 | return NULL; | 152 | return NULL; |
| 153 | } else { | ||
| 154 | lua_pop(L, 2); | ||
| 155 | return lua_touserdata(L, objidx); | ||
| 116 | } | 156 | } |
| 117 | lua_pop(L, 4); | ||
| 118 | return lua_touserdata(L, objidx); | ||
| 119 | } | 157 | } |
| 120 | 158 | ||
| 121 | /*-------------------------------------------------------------------------*\ | 159 | /*-------------------------------------------------------------------------*\ |
| 122 | * Get a userdata if object belongs to a given class. | 160 | * Get a userdata pointer if object belongs to a given class. Return NULL |
| 161 | * otherwise | ||
| 123 | \*-------------------------------------------------------------------------*/ | 162 | \*-------------------------------------------------------------------------*/ |
| 124 | void *aux_getclassudata(lua_State *L, const char *group, int objidx) | 163 | void *aux_getclassudata(lua_State *L, const char *classname, int objidx) |
| 125 | { | 164 | { |
| 126 | if (!lua_getmetatable(L, objidx)) | 165 | return luaL_checkudata(L, objidx, classname); |
| 127 | return NULL; | ||
| 128 | lua_pushstring(L, "__index"); | ||
| 129 | lua_rawget(L, -2); | ||
| 130 | if (!lua_istable(L, -1)) { | ||
| 131 | lua_pop(L, 2); | ||
| 132 | return NULL; | ||
| 133 | } | ||
| 134 | lua_pushstring(L, "class"); | ||
| 135 | lua_rawget(L, -2); | ||
| 136 | if (lua_isnil(L, -1)) { | ||
| 137 | lua_pop(L, 3); | ||
| 138 | return NULL; | ||
| 139 | } | ||
| 140 | lua_pop(L, 3); | ||
| 141 | return lua_touserdata(L, objidx); | ||
| 142 | } | 166 | } |
| 167 | |||
diff --git a/src/auxiliar.h b/src/auxiliar.h index 66be31d..324e800 100644 --- a/src/auxiliar.h +++ b/src/auxiliar.h | |||
| @@ -1,22 +1,37 @@ | |||
| 1 | #ifndef AUX_H | ||
| 2 | #define AUX_H | ||
| 1 | /*=========================================================================*\ | 3 | /*=========================================================================*\ |
| 2 | * Auxiliar routines for class hierarchy manipulation | 4 | * Auxiliar routines for class hierarchy manipulation |
| 5 | * LuaSocket toolkit | ||
| 6 | * | ||
| 7 | * A LuaSocket class is a name associated with Lua metatables. A LuaSocket | ||
| 8 | * group is a name associated to a class. A class can belong to any number | ||
| 9 | * of groups. This module provides the functionality to: | ||
| 10 | * | ||
| 11 | * - create new classes | ||
| 12 | * - add classes to groups | ||
| 13 | * - set the class of object | ||
| 14 | * - check if an object belongs to a given class or group | ||
| 15 | * | ||
| 16 | * LuaSocket class names follow the convention <module>{<class>}. Modules | ||
| 17 | * can define any number of classes and groups. The module tcp.c, for | ||
| 18 | * example, defines the classes tcp{master}, tcp{client} and tcp{server} and | ||
| 19 | * the groups tcp{client, server} and tcp{any}. Module functions can then | ||
| 20 | * perform type-checking on it's arguments by either class or group. | ||
| 21 | * | ||
| 22 | * LuaSocket metatables define the __index metamethod as being a table. This | ||
| 23 | * table has one field for each method supported by the class. In DEBUG | ||
| 24 | * mode, it also has one field with the class name. | ||
| 25 | * | ||
| 26 | * The mapping from class name to the corresponding metatable and the | ||
| 27 | * reverse mapping are done using lauxlib. | ||
| 3 | * | 28 | * |
| 4 | * RCS ID: $Id$ | 29 | * RCS ID: $Id$ |
| 5 | \*=========================================================================*/ | 30 | \*=========================================================================*/ |
| 6 | #ifndef AUX_H | ||
| 7 | #define AUX_H | ||
| 8 | 31 | ||
| 9 | #include <lua.h> | 32 | #include <lua.h> |
| 10 | #include <lauxlib.h> | 33 | #include <lauxlib.h> |
| 11 | 34 | ||
| 12 | void aux_newclass(lua_State *L, const char *name, luaL_reg *func); | ||
| 13 | void aux_add2group(lua_State *L, const char *name, const char *group); | ||
| 14 | void *aux_checkclass(lua_State *L, const char *name, int objidx); | ||
| 15 | void *aux_checkgroup(lua_State *L, const char *group, int objidx); | ||
| 16 | void *aux_getclassudata(lua_State *L, const char *group, int objidx); | ||
| 17 | void *aux_getgroupudata(lua_State *L, const char *group, int objidx); | ||
| 18 | void aux_setclass(lua_State *L, const char *name, int objidx); | ||
| 19 | |||
| 20 | /* min and max macros */ | 35 | /* min and max macros */ |
| 21 | #ifndef MIN | 36 | #ifndef MIN |
| 22 | #define MIN(x, y) ((x) < (y) ? x : y) | 37 | #define MIN(x, y) ((x) < (y) ? x : y) |
| @@ -25,4 +40,15 @@ void aux_setclass(lua_State *L, const char *name, int objidx); | |||
| 25 | #define MAX(x, y) ((x) > (y) ? x : y) | 40 | #define MAX(x, y) ((x) > (y) ? x : y) |
| 26 | #endif | 41 | #endif |
| 27 | 42 | ||
| 28 | #endif | 43 | void aux_open(lua_State *L); |
| 44 | void aux_newclass(lua_State *L, const char *classname, luaL_reg *func); | ||
| 45 | void aux_add2group(lua_State *L, const char *classname, const char *group); | ||
| 46 | void aux_setclass(lua_State *L, const char *classname, int objidx); | ||
| 47 | void *aux_checkclass(lua_State *L, const char *classname, int objidx); | ||
| 48 | void *aux_checkgroup(lua_State *L, const char *groupname, int objidx); | ||
| 49 | void *aux_getclassudata(lua_State *L, const char *groupname, int objidx); | ||
| 50 | void *aux_getgroupudata(lua_State *L, const char *groupname, int objidx); | ||
| 51 | int aux_meth_setoption(lua_State *L, luaL_reg *opt); | ||
| 52 | int aux_checkboolean(lua_State *L, int objidx); | ||
| 53 | |||
| 54 | #endif /* AUX_H */ | ||
diff --git a/src/buffer.c b/src/buffer.c index ab059bb..c860f35 100644 --- a/src/buffer.c +++ b/src/buffer.c | |||
| @@ -1,12 +1,12 @@ | |||
| 1 | /*=========================================================================*\ | 1 | /*=========================================================================*\ |
| 2 | * Buffered input/output routines | 2 | * Input/Output interface for Lua programs |
| 3 | * LuaSocket toolkit | ||
| 3 | * | 4 | * |
| 4 | * RCS ID: $Id$ | 5 | * RCS ID: $Id$ |
| 5 | \*=========================================================================*/ | 6 | \*=========================================================================*/ |
| 6 | #include <lua.h> | 7 | #include <lua.h> |
| 7 | #include <lauxlib.h> | 8 | #include <lauxlib.h> |
| 8 | 9 | ||
| 9 | #include "error.h" | ||
| 10 | #include "auxiliar.h" | 10 | #include "auxiliar.h" |
| 11 | #include "buffer.h" | 11 | #include "buffer.h" |
| 12 | 12 | ||
| @@ -42,7 +42,7 @@ void buf_init(p_buf buf, p_io io, p_tm tm) | |||
| 42 | } | 42 | } |
| 43 | 43 | ||
| 44 | /*-------------------------------------------------------------------------*\ | 44 | /*-------------------------------------------------------------------------*\ |
| 45 | * Send data through buffered object | 45 | * object:send() interface |
| 46 | \*-------------------------------------------------------------------------*/ | 46 | \*-------------------------------------------------------------------------*/ |
| 47 | int buf_meth_send(lua_State *L, p_buf buf) | 47 | int buf_meth_send(lua_State *L, p_buf buf) |
| 48 | { | 48 | { |
| @@ -59,7 +59,7 @@ int buf_meth_send(lua_State *L, p_buf buf) | |||
| 59 | total += sent; | 59 | total += sent; |
| 60 | } | 60 | } |
| 61 | lua_pushnumber(L, total); | 61 | lua_pushnumber(L, total); |
| 62 | error_push(L, err); | 62 | io_pusherror(L, err); |
| 63 | #ifdef LUASOCKET_DEBUG | 63 | #ifdef LUASOCKET_DEBUG |
| 64 | /* push time elapsed during operation as the last return value */ | 64 | /* push time elapsed during operation as the last return value */ |
| 65 | lua_pushnumber(L, (tm_gettime() - tm_getstart(tm))/1000.0); | 65 | lua_pushnumber(L, (tm_gettime() - tm_getstart(tm))/1000.0); |
| @@ -68,7 +68,7 @@ int buf_meth_send(lua_State *L, p_buf buf) | |||
| 68 | } | 68 | } |
| 69 | 69 | ||
| 70 | /*-------------------------------------------------------------------------*\ | 70 | /*-------------------------------------------------------------------------*\ |
| 71 | * Receive data from a buffered object | 71 | * object:receive() interface |
| 72 | \*-------------------------------------------------------------------------*/ | 72 | \*-------------------------------------------------------------------------*/ |
| 73 | int buf_meth_receive(lua_State *L, p_buf buf) | 73 | int buf_meth_receive(lua_State *L, p_buf buf) |
| 74 | { | 74 | { |
| @@ -101,13 +101,13 @@ int buf_meth_receive(lua_State *L, p_buf buf) | |||
| 101 | luaL_argcheck(L, 0, arg, "invalid receive pattern"); | 101 | luaL_argcheck(L, 0, arg, "invalid receive pattern"); |
| 102 | break; | 102 | break; |
| 103 | } | 103 | } |
| 104 | /* raw pattern */ | 104 | /* get a fixed number of bytes */ |
| 105 | } else err = recvraw(L, buf, (size_t) lua_tonumber(L, arg)); | 105 | } else err = recvraw(L, buf, (size_t) lua_tonumber(L, arg)); |
| 106 | } | 106 | } |
| 107 | /* push nil for each pattern after an error */ | 107 | /* push nil for each pattern after an error */ |
| 108 | for ( ; arg <= top; arg++) lua_pushnil(L); | 108 | for ( ; arg <= top; arg++) lua_pushnil(L); |
| 109 | /* last return is an error code */ | 109 | /* last return is an error code */ |
| 110 | error_push(L, err); | 110 | io_pusherror(L, err); |
| 111 | #ifdef LUASOCKET_DEBUG | 111 | #ifdef LUASOCKET_DEBUG |
| 112 | /* push time elapsed during operation as the last return value */ | 112 | /* push time elapsed during operation as the last return value */ |
| 113 | lua_pushnumber(L, (tm_gettime() - tm_getstart(tm))/1000.0); | 113 | lua_pushnumber(L, (tm_gettime() - tm_getstart(tm))/1000.0); |
| @@ -127,9 +127,10 @@ int buf_isempty(p_buf buf) | |||
| 127 | * Internal functions | 127 | * Internal functions |
| 128 | \*=========================================================================*/ | 128 | \*=========================================================================*/ |
| 129 | /*-------------------------------------------------------------------------*\ | 129 | /*-------------------------------------------------------------------------*\ |
| 130 | * Sends a raw block of data through a buffered object. | 130 | * Sends a block of data (unbuffered) |
| 131 | \*-------------------------------------------------------------------------*/ | 131 | \*-------------------------------------------------------------------------*/ |
| 132 | static int sendraw(p_buf buf, const char *data, size_t count, size_t *sent) | 132 | static |
| 133 | int sendraw(p_buf buf, const char *data, size_t count, size_t *sent) | ||
| 133 | { | 134 | { |
| 134 | p_io io = buf->io; | 135 | p_io io = buf->io; |
| 135 | p_tm tm = buf->tm; | 136 | p_tm tm = buf->tm; |
| @@ -145,7 +146,7 @@ static int sendraw(p_buf buf, const char *data, size_t count, size_t *sent) | |||
| 145 | } | 146 | } |
| 146 | 147 | ||
| 147 | /*-------------------------------------------------------------------------*\ | 148 | /*-------------------------------------------------------------------------*\ |
| 148 | * Reads a raw block of data from a buffered object. | 149 | * Reads a fixed number of bytes (buffered) |
| 149 | \*-------------------------------------------------------------------------*/ | 150 | \*-------------------------------------------------------------------------*/ |
| 150 | static | 151 | static |
| 151 | int recvraw(lua_State *L, p_buf buf, size_t wanted) | 152 | int recvraw(lua_State *L, p_buf buf, size_t wanted) |
| @@ -167,7 +168,7 @@ int recvraw(lua_State *L, p_buf buf, size_t wanted) | |||
| 167 | } | 168 | } |
| 168 | 169 | ||
| 169 | /*-------------------------------------------------------------------------*\ | 170 | /*-------------------------------------------------------------------------*\ |
| 170 | * Reads everything until the connection is closed | 171 | * Reads everything until the connection is closed (buffered) |
| 171 | \*-------------------------------------------------------------------------*/ | 172 | \*-------------------------------------------------------------------------*/ |
| 172 | static | 173 | static |
| 173 | int recvall(lua_State *L, p_buf buf) | 174 | int recvall(lua_State *L, p_buf buf) |
| @@ -187,12 +188,12 @@ int recvall(lua_State *L, p_buf buf) | |||
| 187 | 188 | ||
| 188 | /*-------------------------------------------------------------------------*\ | 189 | /*-------------------------------------------------------------------------*\ |
| 189 | * Reads a line terminated by a CR LF pair or just by a LF. The CR and LF | 190 | * Reads a line terminated by a CR LF pair or just by a LF. The CR and LF |
| 190 | * are not returned by the function and are discarded from the buffer. | 191 | * are not returned by the function and are discarded from the buffer |
| 191 | \*-------------------------------------------------------------------------*/ | 192 | \*-------------------------------------------------------------------------*/ |
| 192 | static | 193 | static |
| 193 | int recvline(lua_State *L, p_buf buf) | 194 | int recvline(lua_State *L, p_buf buf) |
| 194 | { | 195 | { |
| 195 | int err = 0; | 196 | int err = IO_DONE; |
| 196 | luaL_Buffer b; | 197 | luaL_Buffer b; |
| 197 | luaL_buffinit(L, &b); | 198 | luaL_buffinit(L, &b); |
| 198 | while (err == IO_DONE) { | 199 | while (err == IO_DONE) { |
| @@ -215,7 +216,8 @@ int recvline(lua_State *L, p_buf buf) | |||
| 215 | } | 216 | } |
| 216 | 217 | ||
| 217 | /*-------------------------------------------------------------------------*\ | 218 | /*-------------------------------------------------------------------------*\ |
| 218 | * Skips a given number of bytes in read buffer | 219 | * Skips a given number of bytes from read buffer. No data is read from the |
| 220 | * transport layer | ||
| 219 | \*-------------------------------------------------------------------------*/ | 221 | \*-------------------------------------------------------------------------*/ |
| 220 | static | 222 | static |
| 221 | void buf_skip(p_buf buf, size_t count) | 223 | void buf_skip(p_buf buf, size_t count) |
| @@ -227,7 +229,7 @@ void buf_skip(p_buf buf, size_t count) | |||
| 227 | 229 | ||
| 228 | /*-------------------------------------------------------------------------*\ | 230 | /*-------------------------------------------------------------------------*\ |
| 229 | * Return any data available in buffer, or get more data from transport layer | 231 | * Return any data available in buffer, or get more data from transport layer |
| 230 | * if buffer is empty. | 232 | * if buffer is empty |
| 231 | \*-------------------------------------------------------------------------*/ | 233 | \*-------------------------------------------------------------------------*/ |
| 232 | static | 234 | static |
| 233 | int buf_get(p_buf buf, const char **data, size_t *count) | 235 | int buf_get(p_buf buf, const char **data, size_t *count) |
| @@ -245,3 +247,4 @@ int buf_get(p_buf buf, const char **data, size_t *count) | |||
| 245 | *data = buf->data + buf->first; | 247 | *data = buf->data + buf->first; |
| 246 | return err; | 248 | return err; |
| 247 | } | 249 | } |
| 250 | |||
diff --git a/src/buffer.h b/src/buffer.h index 1502ef0..12b90a0 100644 --- a/src/buffer.h +++ b/src/buffer.h | |||
| @@ -1,21 +1,31 @@ | |||
| 1 | #ifndef BUF_H | ||
| 2 | #define BUF_H | ||
| 1 | /*=========================================================================*\ | 3 | /*=========================================================================*\ |
| 2 | * Buffered input/output routines | 4 | * Input/Output interface for Lua programs |
| 5 | * LuaSocket toolkit | ||
| 6 | * | ||
| 7 | * Line patterns require buffering. Reading one character at a time involves | ||
| 8 | * too many system calls and is very slow. This module implements the | ||
| 9 | * LuaSocket interface for input/output on connected objects, as seen by | ||
| 10 | * Lua programs. | ||
| 11 | * | ||
| 12 | * Input is buffered. Output is *not* buffered because there was no simple | ||
| 13 | * way of making sure the buffered output data would ever be sent. | ||
| 14 | * | ||
| 15 | * The module is built on top of the I/O abstraction defined in io.h and the | ||
| 16 | * timeout management is done with the timeout.h interface. | ||
| 3 | * | 17 | * |
| 4 | * RCS ID: $Id$ | 18 | * RCS ID: $Id$ |
| 5 | \*=========================================================================*/ | 19 | \*=========================================================================*/ |
| 6 | #ifndef BUF_H | ||
| 7 | #define BUF_H | ||
| 8 | |||
| 9 | #include <lua.h> | 20 | #include <lua.h> |
| 21 | |||
| 10 | #include "io.h" | 22 | #include "io.h" |
| 11 | #include "timeout.h" | 23 | #include "timeout.h" |
| 12 | 24 | ||
| 13 | /* buffer size in bytes */ | 25 | /* buffer size in bytes */ |
| 14 | #define BUF_SIZE 8192 | 26 | #define BUF_SIZE 8192 |
| 15 | 27 | ||
| 16 | /*-------------------------------------------------------------------------*\ | 28 | /* buffer control structure */ |
| 17 | * Buffer control structure | ||
| 18 | \*-------------------------------------------------------------------------*/ | ||
| 19 | typedef struct t_buf_ { | 29 | typedef struct t_buf_ { |
| 20 | p_io io; /* IO driver used for this buffer */ | 30 | p_io io; /* IO driver used for this buffer */ |
| 21 | p_tm tm; /* timeout management for this buffer */ | 31 | p_tm tm; /* timeout management for this buffer */ |
| @@ -24,9 +34,6 @@ typedef struct t_buf_ { | |||
| 24 | } t_buf; | 34 | } t_buf; |
| 25 | typedef t_buf *p_buf; | 35 | typedef t_buf *p_buf; |
| 26 | 36 | ||
| 27 | /*-------------------------------------------------------------------------*\ | ||
| 28 | * Exported functions | ||
| 29 | \*-------------------------------------------------------------------------*/ | ||
| 30 | void buf_open(lua_State *L); | 37 | void buf_open(lua_State *L); |
| 31 | void buf_init(p_buf buf, p_io io, p_tm tm); | 38 | void buf_init(p_buf buf, p_io io, p_tm tm); |
| 32 | int buf_meth_send(lua_State *L, p_buf buf); | 39 | int buf_meth_send(lua_State *L, p_buf buf); |
diff --git a/src/ftp.lua b/src/ftp.lua index c48f2c7..9d75d2a 100644 --- a/src/ftp.lua +++ b/src/ftp.lua | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | ----------------------------------------------------------------------------- | 1 | ----------------------------------------------------------------------------- |
| 2 | -- FTP support for the Lua language | 2 | -- FTP support for the Lua language |
| 3 | -- LuaSocket 1.5 toolkit. | 3 | -- LuaSocket toolkit. |
| 4 | -- Author: Diego Nehab | 4 | -- Author: Diego Nehab |
| 5 | -- Conforming to: RFC 959, LTN7 | 5 | -- Conforming to: RFC 959, LTN7 |
| 6 | -- RCS ID: $Id$ | 6 | -- RCS ID: $Id$ |
diff --git a/src/http.lua b/src/http.lua index d531a2f..4ef2c87 100644 --- a/src/http.lua +++ b/src/http.lua | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | ----------------------------------------------------------------------------- | 1 | ----------------------------------------------------------------------------- |
| 2 | -- HTTP/1.1 client support for the Lua language. | 2 | -- HTTP/1.1 client support for the Lua language. |
| 3 | -- LuaSocket 1.5 toolkit. | 3 | -- LuaSocket toolkit. |
| 4 | -- Author: Diego Nehab | 4 | -- Author: Diego Nehab |
| 5 | -- Conforming to: RFC 2616, LTN7 | 5 | -- Conforming to: RFC 2616, LTN7 |
| 6 | -- RCS ID: $Id$ | 6 | -- RCS ID: $Id$ |
| @@ -1,8 +1,10 @@ | |||
| 1 | /*=========================================================================*\ | 1 | /*=========================================================================*\ |
| 2 | * Internet domain functions | 2 | * Internet domain functions |
| 3 | * LuaSocket toolkit | ||
| 3 | * | 4 | * |
| 4 | * RCS ID: $Id$ | 5 | * RCS ID: $Id$ |
| 5 | \*=========================================================================*/ | 6 | \*=========================================================================*/ |
| 7 | #include <stdio.h> | ||
| 6 | #include <string.h> | 8 | #include <string.h> |
| 7 | 9 | ||
| 8 | #include <lua.h> | 10 | #include <lua.h> |
| @@ -16,7 +18,6 @@ | |||
| 16 | \*=========================================================================*/ | 18 | \*=========================================================================*/ |
| 17 | static int inet_global_toip(lua_State *L); | 19 | static int inet_global_toip(lua_State *L); |
| 18 | static int inet_global_tohostname(lua_State *L); | 20 | static int inet_global_tohostname(lua_State *L); |
| 19 | |||
| 20 | static void inet_pushresolved(lua_State *L, struct hostent *hp); | 21 | static void inet_pushresolved(lua_State *L, struct hostent *hp); |
| 21 | 22 | ||
| 22 | static luaL_reg func[] = { | 23 | static luaL_reg func[] = { |
| @@ -43,11 +44,6 @@ void inet_open(lua_State *L) | |||
| 43 | /*-------------------------------------------------------------------------*\ | 44 | /*-------------------------------------------------------------------------*\ |
| 44 | * Returns all information provided by the resolver given a host name | 45 | * Returns all information provided by the resolver given a host name |
| 45 | * or ip address | 46 | * or ip address |
| 46 | * Lua Input: address | ||
| 47 | * address: ip address or hostname to dns lookup | ||
| 48 | * Lua Returns | ||
| 49 | * On success: first IP address followed by a resolved table | ||
| 50 | * On error: nil, followed by an error message | ||
| 51 | \*-------------------------------------------------------------------------*/ | 47 | \*-------------------------------------------------------------------------*/ |
| 52 | static int inet_global_toip(lua_State *L) | 48 | static int inet_global_toip(lua_State *L) |
| 53 | { | 49 | { |
| @@ -72,11 +68,6 @@ static int inet_global_toip(lua_State *L) | |||
| 72 | /*-------------------------------------------------------------------------*\ | 68 | /*-------------------------------------------------------------------------*\ |
| 73 | * Returns all information provided by the resolver given a host name | 69 | * Returns all information provided by the resolver given a host name |
| 74 | * or ip address | 70 | * or ip address |
| 75 | * Lua Input: address | ||
| 76 | * address: ip address or host name to reverse dns lookup | ||
| 77 | * Lua Returns | ||
| 78 | * On success: canonic name followed by a resolved table | ||
| 79 | * On error: nil, followed by an error message | ||
| 80 | \*-------------------------------------------------------------------------*/ | 71 | \*-------------------------------------------------------------------------*/ |
| 81 | static int inet_global_tohostname(lua_State *L) | 72 | static int inet_global_tohostname(lua_State *L) |
| 82 | { | 73 | { |
| @@ -102,11 +93,6 @@ static int inet_global_tohostname(lua_State *L) | |||
| 102 | \*=========================================================================*/ | 93 | \*=========================================================================*/ |
| 103 | /*-------------------------------------------------------------------------*\ | 94 | /*-------------------------------------------------------------------------*\ |
| 104 | * Retrieves socket peer name | 95 | * Retrieves socket peer name |
| 105 | * Input: | ||
| 106 | * sock: socket | ||
| 107 | * Lua Returns | ||
| 108 | * On success: ip address and port of peer | ||
| 109 | * On error: nil | ||
| 110 | \*-------------------------------------------------------------------------*/ | 96 | \*-------------------------------------------------------------------------*/ |
| 111 | int inet_meth_getpeername(lua_State *L, p_sock ps) | 97 | int inet_meth_getpeername(lua_State *L, p_sock ps) |
| 112 | { | 98 | { |
| @@ -123,11 +109,6 @@ int inet_meth_getpeername(lua_State *L, p_sock ps) | |||
| 123 | 109 | ||
| 124 | /*-------------------------------------------------------------------------*\ | 110 | /*-------------------------------------------------------------------------*\ |
| 125 | * Retrieves socket local name | 111 | * Retrieves socket local name |
| 126 | * Input: | ||
| 127 | * sock: socket | ||
| 128 | * Lua Returns | ||
| 129 | * On success: local ip address and port | ||
| 130 | * On error: nil | ||
| 131 | \*-------------------------------------------------------------------------*/ | 112 | \*-------------------------------------------------------------------------*/ |
| 132 | int inet_meth_getsockname(lua_State *L, p_sock ps) | 113 | int inet_meth_getsockname(lua_State *L, p_sock ps) |
| 133 | { | 114 | { |
| @@ -147,8 +128,6 @@ int inet_meth_getsockname(lua_State *L, p_sock ps) | |||
| 147 | \*=========================================================================*/ | 128 | \*=========================================================================*/ |
| 148 | /*-------------------------------------------------------------------------*\ | 129 | /*-------------------------------------------------------------------------*\ |
| 149 | * Passes all resolver information to Lua as a table | 130 | * Passes all resolver information to Lua as a table |
| 150 | * Input | ||
| 151 | * hp: hostent structure returned by resolver | ||
| 152 | \*-------------------------------------------------------------------------*/ | 131 | \*-------------------------------------------------------------------------*/ |
| 153 | static void inet_pushresolved(lua_State *L, struct hostent *hp) | 132 | static void inet_pushresolved(lua_State *L, struct hostent *hp) |
| 154 | { | 133 | { |
| @@ -185,12 +164,6 @@ static void inet_pushresolved(lua_State *L, struct hostent *hp) | |||
| 185 | 164 | ||
| 186 | /*-------------------------------------------------------------------------*\ | 165 | /*-------------------------------------------------------------------------*\ |
| 187 | * Tries to connect to remote address (address, port) | 166 | * Tries to connect to remote address (address, port) |
| 188 | * Input | ||
| 189 | * ps: pointer to socket | ||
| 190 | * address: host name or ip address | ||
| 191 | * port: port number to bind to | ||
| 192 | * Returns | ||
| 193 | * NULL in case of success, error message otherwise | ||
| 194 | \*-------------------------------------------------------------------------*/ | 167 | \*-------------------------------------------------------------------------*/ |
| 195 | const char *inet_tryconnect(p_sock ps, const char *address, | 168 | const char *inet_tryconnect(p_sock ps, const char *address, |
| 196 | unsigned short port) | 169 | unsigned short port) |
| @@ -224,12 +197,6 @@ const char *inet_tryconnect(p_sock ps, const char *address, | |||
| 224 | 197 | ||
| 225 | /*-------------------------------------------------------------------------*\ | 198 | /*-------------------------------------------------------------------------*\ |
| 226 | * Tries to bind socket to (address, port) | 199 | * Tries to bind socket to (address, port) |
| 227 | * Input | ||
| 228 | * sock: pointer to socket | ||
| 229 | * address: host name or ip address | ||
| 230 | * port: port number to bind to | ||
| 231 | * Returns | ||
| 232 | * NULL in case of success, error message otherwise | ||
| 233 | \*-------------------------------------------------------------------------*/ | 200 | \*-------------------------------------------------------------------------*/ |
| 234 | const char *inet_trybind(p_sock ps, const char *address, unsigned short port, | 201 | const char *inet_trybind(p_sock ps, const char *address, unsigned short port, |
| 235 | int backlog) | 202 | int backlog) |
| @@ -264,10 +231,6 @@ const char *inet_trybind(p_sock ps, const char *address, unsigned short port, | |||
| 264 | 231 | ||
| 265 | /*-------------------------------------------------------------------------*\ | 232 | /*-------------------------------------------------------------------------*\ |
| 266 | * Tries to create a new inet socket | 233 | * Tries to create a new inet socket |
| 267 | * Input | ||
| 268 | * sock: pointer to socket | ||
| 269 | * Returns | ||
| 270 | * NULL if successfull, error message on error | ||
| 271 | \*-------------------------------------------------------------------------*/ | 234 | \*-------------------------------------------------------------------------*/ |
| 272 | const char *inet_trycreate(p_sock ps, int type) | 235 | const char *inet_trycreate(p_sock ps, int type) |
| 273 | { | 236 | { |
| @@ -299,3 +262,5 @@ int inet_aton(const char *cp, struct in_addr *inp) | |||
| 299 | return 1; | 262 | return 1; |
| 300 | } | 263 | } |
| 301 | #endif | 264 | #endif |
| 265 | |||
| 266 | |||
| @@ -1,25 +1,30 @@ | |||
| 1 | #ifndef INET_H | ||
| 2 | #define INET_H | ||
| 1 | /*=========================================================================*\ | 3 | /*=========================================================================*\ |
| 2 | * Internet domain functions | 4 | * Internet domain functions |
| 5 | * LuaSocket toolkit | ||
| 6 | * | ||
| 7 | * This module implements the creation and connection of internet domain | ||
| 8 | * sockets, on top of the socket.h interface, and the interface of with the | ||
| 9 | * resolver. | ||
| 10 | * | ||
| 11 | * The function inet_aton is provided for the platforms where it is not | ||
| 12 | * available. The module also implements the interface of the internet | ||
| 13 | * getpeername and getsockname functions as seen by Lua programs. | ||
| 14 | * | ||
| 15 | * The Lua functions toip and tohostname are also implemented here. | ||
| 3 | * | 16 | * |
| 4 | * RCS ID: $Id$ | 17 | * RCS ID: $Id$ |
| 5 | \*=========================================================================*/ | 18 | \*=========================================================================*/ |
| 6 | #ifndef INET_H | ||
| 7 | #define INET_H | ||
| 8 | |||
| 9 | #include <lua.h> | 19 | #include <lua.h> |
| 10 | #include "socket.h" | 20 | #include "socket.h" |
| 11 | 21 | ||
| 12 | /*-------------------------------------------------------------------------*\ | ||
| 13 | * Exported functions | ||
| 14 | \*-------------------------------------------------------------------------*/ | ||
| 15 | void inet_open(lua_State *L); | 22 | void inet_open(lua_State *L); |
| 16 | |||
| 17 | const char *inet_tryconnect(p_sock ps, const char *address, | 23 | const char *inet_tryconnect(p_sock ps, const char *address, |
| 18 | unsigned short port); | 24 | unsigned short port); |
| 19 | const char *inet_trybind(p_sock ps, const char *address, | 25 | const char *inet_trybind(p_sock ps, const char *address, |
| 20 | unsigned short port, int backlog); | 26 | unsigned short port, int backlog); |
| 21 | const char *inet_trycreate(p_sock ps, int type); | 27 | const char *inet_trycreate(p_sock ps, int type); |
| 22 | |||
| 23 | int inet_meth_getpeername(lua_State *L, p_sock ps); | 28 | int inet_meth_getpeername(lua_State *L, p_sock ps); |
| 24 | int inet_meth_getsockname(lua_State *L, p_sock ps); | 29 | int inet_meth_getsockname(lua_State *L, p_sock ps); |
| 25 | 30 | ||
| @@ -27,4 +32,4 @@ int inet_meth_getsockname(lua_State *L, p_sock ps); | |||
| 27 | int inet_aton(const char *cp, struct in_addr *inp); | 32 | int inet_aton(const char *cp, struct in_addr *inp); |
| 28 | #endif | 33 | #endif |
| 29 | 34 | ||
| 30 | #endif /* INET_H_ */ | 35 | #endif /* INET_H */ |
| @@ -1,8 +1,48 @@ | |||
| 1 | /*=========================================================================*\ | ||
| 2 | * Input/Output abstraction | ||
| 3 | * LuaSocket toolkit | ||
| 4 | * | ||
| 5 | * RCS ID: $Id$ | ||
| 6 | \*=========================================================================*/ | ||
| 1 | #include "io.h" | 7 | #include "io.h" |
| 2 | 8 | ||
| 9 | /*=========================================================================*\ | ||
| 10 | * Exported functions | ||
| 11 | \*=========================================================================*/ | ||
| 12 | /*-------------------------------------------------------------------------*\ | ||
| 13 | * Initializes C structure | ||
| 14 | \*-------------------------------------------------------------------------*/ | ||
| 3 | void io_init(p_io io, p_send send, p_recv recv, void *ctx) | 15 | void io_init(p_io io, p_send send, p_recv recv, void *ctx) |
| 4 | { | 16 | { |
| 5 | io->send = send; | 17 | io->send = send; |
| 6 | io->recv = recv; | 18 | io->recv = recv; |
| 7 | io->ctx = ctx; | 19 | io->ctx = ctx; |
| 8 | } | 20 | } |
| 21 | |||
| 22 | /*-------------------------------------------------------------------------*\ | ||
| 23 | * Translate error codes to Lua | ||
| 24 | \*-------------------------------------------------------------------------*/ | ||
| 25 | void io_pusherror(lua_State *L, int code) | ||
| 26 | { | ||
| 27 | switch (code) { | ||
| 28 | case IO_DONE: | ||
| 29 | lua_pushnil(L); | ||
| 30 | break; | ||
| 31 | case IO_TIMEOUT: | ||
| 32 | lua_pushstring(L, "timeout"); | ||
| 33 | break; | ||
| 34 | case IO_LIMITED: | ||
| 35 | lua_pushstring(L, "limited"); | ||
| 36 | break; | ||
| 37 | case IO_CLOSED: | ||
| 38 | lua_pushstring(L, "closed"); | ||
| 39 | break; | ||
| 40 | case IO_REFUSED: | ||
| 41 | lua_pushstring(L, "refused"); | ||
| 42 | break; | ||
| 43 | default: | ||
| 44 | lua_pushstring(L, "unknown error"); | ||
| 45 | break; | ||
| 46 | } | ||
| 47 | } | ||
| 48 | |||
| @@ -1,16 +1,30 @@ | |||
| 1 | #ifndef IO_H | 1 | #ifndef IO_H |
| 2 | #define IO_H | 2 | #define IO_H |
| 3 | 3 | /*=========================================================================*\ | |
| 4 | * Input/Output abstraction | ||
| 5 | * LuaSocket toolkit | ||
| 6 | * | ||
| 7 | * This module defines the interface that LuaSocket expects from the | ||
| 8 | * transport layer for streamed input/output. The idea is that if any | ||
| 9 | * transport implements this interface, then the buffer.c functions | ||
| 10 | * automatically work on it. | ||
| 11 | * | ||
| 12 | * The module socket.h implements this interface, and thus the module tcp.h | ||
| 13 | * is very simple. | ||
| 14 | * | ||
| 15 | * RCS ID: $Id$ | ||
| 16 | \*=========================================================================*/ | ||
| 4 | #include <stdio.h> | 17 | #include <stdio.h> |
| 18 | #include <lua.h> | ||
| 5 | 19 | ||
| 6 | /* IO error codes */ | 20 | /* IO error codes */ |
| 7 | enum { | 21 | enum { |
| 8 | IO_DONE, /* operation completed successfully */ | 22 | IO_DONE, /* operation completed successfully */ |
| 9 | IO_TIMEOUT, /* operation timed out */ | 23 | IO_TIMEOUT, /* operation timed out */ |
| 10 | IO_CLOSED, /* the connection has been closed */ | 24 | IO_CLOSED, /* the connection has been closed */ |
| 11 | IO_ERROR, /* something wrong... */ | 25 | IO_ERROR, /* something wrong... */ |
| 12 | IO_REFUSED, /* transfer has been refused */ | 26 | IO_REFUSED, /* transfer has been refused */ |
| 13 | IO_LIMITED /* maximum number of bytes reached */ | 27 | IO_LIMITED /* maximum number of bytes reached */ |
| 14 | }; | 28 | }; |
| 15 | 29 | ||
| 16 | /* interface to send function */ | 30 | /* interface to send function */ |
| @@ -39,6 +53,7 @@ typedef struct t_io_ { | |||
| 39 | } t_io; | 53 | } t_io; |
| 40 | typedef t_io *p_io; | 54 | typedef t_io *p_io; |
| 41 | 55 | ||
| 56 | void io_pusherror(lua_State *L, int code); | ||
| 42 | void io_init(p_io io, p_send send, p_recv recv, void *ctx); | 57 | void io_init(p_io io, p_send send, p_recv recv, void *ctx); |
| 43 | 58 | ||
| 44 | #endif /* IO_H */ | 59 | #endif /* IO_H */ |
diff --git a/src/luasocket.c b/src/luasocket.c index 5541d7f..96deac1 100644 --- a/src/luasocket.c +++ b/src/luasocket.c | |||
| @@ -1,4 +1,5 @@ | |||
| 1 | /*=========================================================================*\ | 1 | /*=========================================================================*\ |
| 2 | * LuaSocket toolkit | ||
| 2 | * Networking support for the Lua language | 3 | * Networking support for the Lua language |
| 3 | * Diego Nehab | 4 | * Diego Nehab |
| 4 | * 26/11/1999 | 5 | * 26/11/1999 |
| @@ -7,7 +8,7 @@ | |||
| 7 | * connectivity of the Lua language. The Lua interface to networking | 8 | * connectivity of the Lua language. The Lua interface to networking |
| 8 | * functions follows the Sockets API closely, trying to simplify all tasks | 9 | * functions follows the Sockets API closely, trying to simplify all tasks |
| 9 | * involved in setting up both client and server connections. The provided | 10 | * involved in setting up both client and server connections. The provided |
| 10 | * IO routines, however, follow the Lua style, being very similar to the | 11 | * IO routines, however, follow the Lua style, being very similar to the |
| 11 | * standard Lua read and write functions. | 12 | * standard Lua read and write functions. |
| 12 | * | 13 | * |
| 13 | * RCS ID: $Id$ | 14 | * RCS ID: $Id$ |
| @@ -24,6 +25,7 @@ | |||
| 24 | \*=========================================================================*/ | 25 | \*=========================================================================*/ |
| 25 | #include "luasocket.h" | 26 | #include "luasocket.h" |
| 26 | 27 | ||
| 28 | #include "auxiliar.h" | ||
| 27 | #include "timeout.h" | 29 | #include "timeout.h" |
| 28 | #include "buffer.h" | 30 | #include "buffer.h" |
| 29 | #include "socket.h" | 31 | #include "socket.h" |
| @@ -38,23 +40,11 @@ | |||
| 38 | /*-------------------------------------------------------------------------*\ | 40 | /*-------------------------------------------------------------------------*\ |
| 39 | * Initializes all library modules. | 41 | * Initializes all library modules. |
| 40 | \*-------------------------------------------------------------------------*/ | 42 | \*-------------------------------------------------------------------------*/ |
| 41 | LUASOCKET_API int luaopen_socketlib(lua_State *L) | 43 | LUASOCKET_API int luaopen_socket(lua_State *L) |
| 42 | { | 44 | { |
| 43 | if (!sock_open()) return 0; | 45 | if (!sock_open()) return 0; |
| 44 | /* create namespace table */ | ||
| 45 | lua_pushstring(L, LUASOCKET_LIBNAME); | ||
| 46 | lua_newtable(L); | ||
| 47 | #ifdef LUASOCKET_DEBUG | ||
| 48 | lua_pushstring(L, "debug"); | ||
| 49 | lua_pushnumber(L, 1); | ||
| 50 | lua_settable(L, -3); | ||
| 51 | #endif | ||
| 52 | lua_settable(L, LUA_GLOBALSINDEX); | ||
| 53 | /* make sure modules know what is our namespace */ | ||
| 54 | lua_pushstring(L, "LUASOCKET_LIBNAME"); | ||
| 55 | lua_pushstring(L, LUASOCKET_LIBNAME); | ||
| 56 | lua_settable(L, LUA_GLOBALSINDEX); | ||
| 57 | /* initialize all modules */ | 46 | /* initialize all modules */ |
| 47 | aux_open(L); | ||
| 58 | tm_open(L); | 48 | tm_open(L); |
| 59 | buf_open(L); | 49 | buf_open(L); |
| 60 | inet_open(L); | 50 | inet_open(L); |
diff --git a/src/luasocket.h b/src/luasocket.h index 6c25af2..7756605 100644 --- a/src/luasocket.h +++ b/src/luasocket.h | |||
| @@ -1,17 +1,19 @@ | |||
| 1 | #ifndef LUASOCKET_H | ||
| 2 | #define LUASOCKET_H | ||
| 1 | /*=========================================================================*\ | 3 | /*=========================================================================*\ |
| 4 | * LuaSocket toolkit | ||
| 2 | * Networking support for the Lua language | 5 | * Networking support for the Lua language |
| 3 | * Diego Nehab | 6 | * Diego Nehab |
| 4 | * 9/11/1999 | 7 | * 9/11/1999 |
| 5 | * | 8 | * |
| 6 | * RCS ID: $Id$ | 9 | * RCS ID: $Id$ |
| 7 | \*=========================================================================*/ | 10 | \*=========================================================================*/ |
| 8 | #ifndef LUASOCKET_H | 11 | #include <lua.h> |
| 9 | #define LUASOCKET_H | ||
| 10 | 12 | ||
| 11 | /*-------------------------------------------------------------------------*\ | 13 | /*-------------------------------------------------------------------------*\ |
| 12 | * Current luasocket version | 14 | * Current luasocket version |
| 13 | \*-------------------------------------------------------------------------*/ | 15 | \*-------------------------------------------------------------------------*/ |
| 14 | #define LUASOCKET_VERSION "LuaSocket 1.5 (alpha)" | 16 | #define LUASOCKET_VERSION "LuaSocket 2.0 (alpha)" |
| 15 | 17 | ||
| 16 | /*-------------------------------------------------------------------------*\ | 18 | /*-------------------------------------------------------------------------*\ |
| 17 | * Library's namespace | 19 | * Library's namespace |
| @@ -28,6 +30,6 @@ | |||
| 28 | /*-------------------------------------------------------------------------*\ | 30 | /*-------------------------------------------------------------------------*\ |
| 29 | * Initializes the library. | 31 | * Initializes the library. |
| 30 | \*-------------------------------------------------------------------------*/ | 32 | \*-------------------------------------------------------------------------*/ |
| 31 | LUASOCKET_API int luaopen_socketlib(lua_State *L); | 33 | LUASOCKET_API int luaopen_socket(lua_State *L); |
| 32 | 34 | ||
| 33 | #endif /* LUASOCKET_H */ | 35 | #endif /* LUASOCKET_H */ |
diff --git a/src/select.c b/src/select.c index 3cabbd1..9769667 100644 --- a/src/select.c +++ b/src/select.c | |||
| @@ -1,5 +1,7 @@ | |||
| 1 | /*=========================================================================*\ | 1 | /*=========================================================================*\ |
| 2 | * Select implementation | 2 | * Select implementation |
| 3 | * LuaSocket toolkit | ||
| 4 | * | ||
| 3 | * RCS ID: $Id$ | 5 | * RCS ID: $Id$ |
| 4 | \*=========================================================================*/ | 6 | \*=========================================================================*/ |
| 5 | #include <string.h> | 7 | #include <string.h> |
| @@ -12,6 +14,9 @@ | |||
| 12 | #include "auxiliar.h" | 14 | #include "auxiliar.h" |
| 13 | #include "select.h" | 15 | #include "select.h" |
| 14 | 16 | ||
| 17 | /*=========================================================================*\ | ||
| 18 | * Internal function prototypes. | ||
| 19 | \*=========================================================================*/ | ||
| 15 | static int meth_set(lua_State *L); | 20 | static int meth_set(lua_State *L); |
| 16 | static int meth_isset(lua_State *L); | 21 | static int meth_isset(lua_State *L); |
| 17 | static int c_select(lua_State *L); | 22 | static int c_select(lua_State *L); |
| @@ -31,6 +36,12 @@ static luaL_reg func[] = { | |||
| 31 | {NULL, NULL} | 36 | {NULL, NULL} |
| 32 | }; | 37 | }; |
| 33 | 38 | ||
| 39 | /*=========================================================================*\ | ||
| 40 | * Internal function prototypes. | ||
| 41 | \*=========================================================================*/ | ||
| 42 | /*-------------------------------------------------------------------------*\ | ||
| 43 | * Initializes module | ||
| 44 | \*-------------------------------------------------------------------------*/ | ||
| 34 | void select_open(lua_State *L) | 45 | void select_open(lua_State *L) |
| 35 | { | 46 | { |
| 36 | /* get select auxiliar lua function from lua code and register | 47 | /* get select auxiliar lua function from lua code and register |
| @@ -45,6 +56,9 @@ void select_open(lua_State *L) | |||
| 45 | aux_newclass(L, "select{fd_set}", set); | 56 | aux_newclass(L, "select{fd_set}", set); |
| 46 | } | 57 | } |
| 47 | 58 | ||
| 59 | /*=========================================================================*\ | ||
| 60 | * Global Lua functions | ||
| 61 | \*=========================================================================*/ | ||
| 48 | /*-------------------------------------------------------------------------*\ | 62 | /*-------------------------------------------------------------------------*\ |
| 49 | * Waits for a set of sockets until a condition is met or timeout. | 63 | * Waits for a set of sockets until a condition is met or timeout. |
| 50 | \*-------------------------------------------------------------------------*/ | 64 | \*-------------------------------------------------------------------------*/ |
| @@ -63,10 +77,10 @@ static int global_select(lua_State *L) | |||
| 63 | lua_pushvalue(L, lua_upvalueindex(1)); | 77 | lua_pushvalue(L, lua_upvalueindex(1)); |
| 64 | lua_insert(L, 1); | 78 | lua_insert(L, 1); |
| 65 | /* pass fd_set objects */ | 79 | /* pass fd_set objects */ |
| 66 | read_fd_set = lua_newuserdata(L, sizeof(fd_set)); | 80 | read_fd_set = (fd_set *) lua_newuserdata(L, sizeof(fd_set)); |
| 67 | FD_ZERO(read_fd_set); | 81 | FD_ZERO(read_fd_set); |
| 68 | aux_setclass(L, "select{fd_set}", -1); | 82 | aux_setclass(L, "select{fd_set}", -1); |
| 69 | write_fd_set = lua_newuserdata(L, sizeof(fd_set)); | 83 | write_fd_set = (fd_set *) lua_newuserdata(L, sizeof(fd_set)); |
| 70 | FD_ZERO(write_fd_set); | 84 | FD_ZERO(write_fd_set); |
| 71 | aux_setclass(L, "select{fd_set}", -1); | 85 | aux_setclass(L, "select{fd_set}", -1); |
| 72 | /* pass select auxiliar C function */ | 86 | /* pass select auxiliar C function */ |
| @@ -76,20 +90,9 @@ static int global_select(lua_State *L) | |||
| 76 | return 3; | 90 | return 3; |
| 77 | } | 91 | } |
| 78 | 92 | ||
| 79 | static int c_select(lua_State *L) | 93 | /*=========================================================================*\ |
| 80 | { | 94 | * Lua methods |
| 81 | int max_fd = (int) lua_tonumber(L, 1); | 95 | \*=========================================================================*/ |
| 82 | fd_set *read_fd_set = (fd_set *) aux_checkclass(L, "select{fd_set}", 2); | ||
| 83 | fd_set *write_fd_set = (fd_set *) aux_checkclass(L, "select{fd_set}", 3); | ||
| 84 | int timeout = lua_isnil(L, 4) ? -1 : (int)(lua_tonumber(L, 4) * 1000); | ||
| 85 | struct timeval tv; | ||
| 86 | tv.tv_sec = timeout / 1000; | ||
| 87 | tv.tv_usec = (timeout % 1000) * 1000; | ||
| 88 | lua_pushnumber(L, select(max_fd, read_fd_set, write_fd_set, NULL, | ||
| 89 | timeout < 0 ? NULL : &tv)); | ||
| 90 | return 1; | ||
| 91 | } | ||
| 92 | |||
| 93 | static int meth_set(lua_State *L) | 96 | static int meth_set(lua_State *L) |
| 94 | { | 97 | { |
| 95 | fd_set *set = (fd_set *) aux_checkclass(L, "select{fd_set}", 1); | 98 | fd_set *set = (fd_set *) aux_checkclass(L, "select{fd_set}", 1); |
| @@ -107,6 +110,23 @@ static int meth_isset(lua_State *L) | |||
| 107 | return 1; | 110 | return 1; |
| 108 | } | 111 | } |
| 109 | 112 | ||
| 113 | /*=========================================================================*\ | ||
| 114 | * Internal functions | ||
| 115 | \*=========================================================================*/ | ||
| 116 | static int c_select(lua_State *L) | ||
| 117 | { | ||
| 118 | int max_fd = (int) lua_tonumber(L, 1); | ||
| 119 | fd_set *read_fd_set = (fd_set *) aux_checkclass(L, "select{fd_set}", 2); | ||
| 120 | fd_set *write_fd_set = (fd_set *) aux_checkclass(L, "select{fd_set}", 3); | ||
| 121 | int timeout = lua_isnil(L, 4) ? -1 : (int)(lua_tonumber(L, 4) * 1000); | ||
| 122 | struct timeval tv; | ||
| 123 | tv.tv_sec = timeout / 1000; | ||
| 124 | tv.tv_usec = (timeout % 1000) * 1000; | ||
| 125 | lua_pushnumber(L, select(max_fd, read_fd_set, write_fd_set, NULL, | ||
| 126 | timeout < 0 ? NULL : &tv)); | ||
| 127 | return 1; | ||
| 128 | } | ||
| 129 | |||
| 110 | static void check_obj_tab(lua_State *L, int tabidx) | 130 | static void check_obj_tab(lua_State *L, int tabidx) |
| 111 | { | 131 | { |
| 112 | if (tabidx < 0) tabidx = lua_gettop(L) + tabidx + 1; | 132 | if (tabidx < 0) tabidx = lua_gettop(L) + tabidx + 1; |
diff --git a/src/select.h b/src/select.h index 9521fae..0e1eeb4 100644 --- a/src/select.h +++ b/src/select.h | |||
| @@ -1,9 +1,19 @@ | |||
| 1 | #ifndef SELECT_H | ||
| 2 | #define SELECT_H | ||
| 1 | /*=========================================================================*\ | 3 | /*=========================================================================*\ |
| 2 | * Select implementation | 4 | * Select implementation |
| 5 | * LuaSocket toolkit | ||
| 6 | * | ||
| 7 | * To make the code as simple as possible, the select function is | ||
| 8 | * implemented int Lua, with a few helper functions written in C. | ||
| 9 | * | ||
| 10 | * Each object that can be passed to the select function has to be in the | ||
| 11 | * group select{able} and export two methods: fd() and dirty(). Fd returns | ||
| 12 | * the descriptor to be passed to the select function. Dirty() should return | ||
| 13 | * true if there is data ready for reading (required for buffered input). | ||
| 14 | * | ||
| 3 | * RCS ID: $Id$ | 15 | * RCS ID: $Id$ |
| 4 | \*=========================================================================*/ | 16 | \*=========================================================================*/ |
| 5 | #ifndef SELECT_H | ||
| 6 | #define SELECT_H | ||
| 7 | 17 | ||
| 8 | void select_open(lua_State *L); | 18 | void select_open(lua_State *L); |
| 9 | 19 | ||
diff --git a/src/smtp.lua b/src/smtp.lua index 604f79b..209825b 100644 --- a/src/smtp.lua +++ b/src/smtp.lua | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | ----------------------------------------------------------------------------- | 1 | ----------------------------------------------------------------------------- |
| 2 | -- SMTP support for the Lua language. | 2 | -- SMTP support for the Lua language. |
| 3 | -- LuaSocket 1.5 toolkit | 3 | -- LuaSocket toolkit |
| 4 | -- Author: Diego Nehab | 4 | -- Author: Diego Nehab |
| 5 | -- Conforming to: RFC 821, LTN7 | 5 | -- Conforming to: RFC 821, LTN7 |
| 6 | -- RCS ID: $Id$ | 6 | -- RCS ID: $Id$ |
diff --git a/src/socket.h b/src/socket.h index 70ebc52..c7db5f2 100644 --- a/src/socket.h +++ b/src/socket.h | |||
| @@ -1,11 +1,16 @@ | |||
| 1 | #ifndef SOCK_H | ||
| 2 | #define SOCK_H | ||
| 1 | /*=========================================================================*\ | 3 | /*=========================================================================*\ |
| 2 | * Socket compatibilization module | 4 | * Socket compatibilization module |
| 5 | * LuaSocket toolkit | ||
| 6 | * | ||
| 7 | * BSD Sockets and WinSock are similar, but there are a few irritating | ||
| 8 | * differences. Also, not all *nix platforms behave the same. This module | ||
| 9 | * (and the associated usocket.h and wsocket.h) factor these differences and | ||
| 10 | * creates a interface compatible with the io.h module. | ||
| 3 | * | 11 | * |
| 4 | * RCS ID: $Id$ | 12 | * RCS ID: $Id$ |
| 5 | \*=========================================================================*/ | 13 | \*=========================================================================*/ |
| 6 | #ifndef SOCK_H | ||
| 7 | #define SOCK_H | ||
| 8 | |||
| 9 | #include "io.h" | 14 | #include "io.h" |
| 10 | 15 | ||
| 11 | /*=========================================================================*\ | 16 | /*=========================================================================*\ |
| @@ -32,7 +37,6 @@ int sock_accept(p_sock ps, p_sock pa, SA *addr, socklen_t *addr_len, | |||
| 32 | const char *sock_connect(p_sock ps, SA *addr, socklen_t addr_len); | 37 | const char *sock_connect(p_sock ps, SA *addr, socklen_t addr_len); |
| 33 | const char *sock_bind(p_sock ps, SA *addr, socklen_t addr_len); | 38 | const char *sock_bind(p_sock ps, SA *addr, socklen_t addr_len); |
| 34 | void sock_listen(p_sock ps, int backlog); | 39 | void sock_listen(p_sock ps, int backlog); |
| 35 | |||
| 36 | int sock_send(p_sock ps, const char *data, size_t count, | 40 | int sock_send(p_sock ps, const char *data, size_t count, |
| 37 | size_t *sent, int timeout); | 41 | size_t *sent, int timeout); |
| 38 | int sock_recv(p_sock ps, char *data, size_t count, | 42 | int sock_recv(p_sock ps, char *data, size_t count, |
| @@ -41,11 +45,8 @@ int sock_sendto(p_sock ps, const char *data, size_t count, | |||
| 41 | size_t *sent, SA *addr, socklen_t addr_len, int timeout); | 45 | size_t *sent, SA *addr, socklen_t addr_len, int timeout); |
| 42 | int sock_recvfrom(p_sock ps, char *data, size_t count, | 46 | int sock_recvfrom(p_sock ps, char *data, size_t count, |
| 43 | size_t *got, SA *addr, socklen_t *addr_len, int timeout); | 47 | size_t *got, SA *addr, socklen_t *addr_len, int timeout); |
| 44 | |||
| 45 | void sock_setnonblocking(p_sock ps); | 48 | void sock_setnonblocking(p_sock ps); |
| 46 | void sock_setblocking(p_sock ps); | 49 | void sock_setblocking(p_sock ps); |
| 47 | void sock_setreuseaddr(p_sock ps); | ||
| 48 | |||
| 49 | const char *sock_hoststrerror(void); | 50 | const char *sock_hoststrerror(void); |
| 50 | const char *sock_createstrerror(void); | 51 | const char *sock_createstrerror(void); |
| 51 | const char *sock_bindstrerror(void); | 52 | const char *sock_bindstrerror(void); |
| @@ -1,5 +1,6 @@ | |||
| 1 | /*=========================================================================*\ | 1 | /*=========================================================================*\ |
| 2 | * TCP object | 2 | * TCP object |
| 3 | * LuaSocket toolkit | ||
| 3 | * | 4 | * |
| 4 | * RCS ID: $Id$ | 5 | * RCS ID: $Id$ |
| 5 | \*=========================================================================*/ | 6 | \*=========================================================================*/ |
| @@ -13,7 +14,6 @@ | |||
| 13 | #include "auxiliar.h" | 14 | #include "auxiliar.h" |
| 14 | #include "socket.h" | 15 | #include "socket.h" |
| 15 | #include "inet.h" | 16 | #include "inet.h" |
| 16 | #include "error.h" | ||
| 17 | #include "tcp.h" | 17 | #include "tcp.h" |
| 18 | 18 | ||
| 19 | /*=========================================================================*\ | 19 | /*=========================================================================*\ |
| @@ -28,9 +28,13 @@ static int meth_getpeername(lua_State *L); | |||
| 28 | static int meth_receive(lua_State *L); | 28 | static int meth_receive(lua_State *L); |
| 29 | static int meth_accept(lua_State *L); | 29 | static int meth_accept(lua_State *L); |
| 30 | static int meth_close(lua_State *L); | 30 | static int meth_close(lua_State *L); |
| 31 | static int meth_setoption(lua_State *L); | ||
| 31 | static int meth_timeout(lua_State *L); | 32 | static int meth_timeout(lua_State *L); |
| 32 | static int meth_fd(lua_State *L); | 33 | static int meth_fd(lua_State *L); |
| 33 | static int meth_dirty(lua_State *L); | 34 | static int meth_dirty(lua_State *L); |
| 35 | static int opt_nodelay(lua_State *L); | ||
| 36 | static int opt_keepalive(lua_State *L); | ||
| 37 | static int opt_linger(lua_State *L); | ||
| 34 | 38 | ||
| 35 | /* tcp object methods */ | 39 | /* tcp object methods */ |
| 36 | static luaL_reg tcp[] = { | 40 | static luaL_reg tcp[] = { |
| @@ -45,11 +49,21 @@ static luaL_reg tcp[] = { | |||
| 45 | {"getsockname", meth_getsockname}, | 49 | {"getsockname", meth_getsockname}, |
| 46 | {"timeout", meth_timeout}, | 50 | {"timeout", meth_timeout}, |
| 47 | {"close", meth_close}, | 51 | {"close", meth_close}, |
| 52 | {"setoption", meth_setoption}, | ||
| 53 | {"__gc", meth_close}, | ||
| 48 | {"fd", meth_fd}, | 54 | {"fd", meth_fd}, |
| 49 | {"dirty", meth_dirty}, | 55 | {"dirty", meth_dirty}, |
| 50 | {NULL, NULL} | 56 | {NULL, NULL} |
| 51 | }; | 57 | }; |
| 52 | 58 | ||
| 59 | /* socket option handlers */ | ||
| 60 | static luaL_reg opt[] = { | ||
| 61 | {"keepalive", opt_keepalive}, | ||
| 62 | {"nodelay", opt_nodelay}, | ||
| 63 | {"linger", opt_linger}, | ||
| 64 | {NULL, NULL} | ||
| 65 | }; | ||
| 66 | |||
| 53 | /* functions in library namespace */ | 67 | /* functions in library namespace */ |
| 54 | static luaL_reg func[] = { | 68 | static luaL_reg func[] = { |
| 55 | {"tcp", global_create}, | 69 | {"tcp", global_create}, |
| @@ -71,6 +85,7 @@ void tcp_open(lua_State *L) | |||
| 71 | aux_add2group(L, "tcp{server}", "tcp{any}"); | 85 | aux_add2group(L, "tcp{server}", "tcp{any}"); |
| 72 | aux_add2group(L, "tcp{client}", "tcp{client, server}"); | 86 | aux_add2group(L, "tcp{client}", "tcp{client, server}"); |
| 73 | aux_add2group(L, "tcp{server}", "tcp{client, server}"); | 87 | aux_add2group(L, "tcp{server}", "tcp{client, server}"); |
| 88 | /* both server and client objects are selectable */ | ||
| 74 | aux_add2group(L, "tcp{client}", "select{able}"); | 89 | aux_add2group(L, "tcp{client}", "select{able}"); |
| 75 | aux_add2group(L, "tcp{server}", "select{able}"); | 90 | aux_add2group(L, "tcp{server}", "select{able}"); |
| 76 | /* define library functions */ | 91 | /* define library functions */ |
| @@ -97,18 +112,80 @@ static int meth_receive(lua_State *L) | |||
| 97 | } | 112 | } |
| 98 | 113 | ||
| 99 | /*-------------------------------------------------------------------------*\ | 114 | /*-------------------------------------------------------------------------*\ |
| 115 | * Option handlers | ||
| 116 | \*-------------------------------------------------------------------------*/ | ||
| 117 | static int meth_setoption(lua_State *L) | ||
| 118 | { | ||
| 119 | return aux_meth_setoption(L, opt); | ||
| 120 | } | ||
| 121 | |||
| 122 | static int opt_boolean(lua_State *L, int level, int name) | ||
| 123 | { | ||
| 124 | p_tcp tcp = (p_tcp) aux_checkgroup(L, "tcp{any}", 1); | ||
| 125 | int val = aux_checkboolean(L, 2); | ||
| 126 | if (setsockopt(tcp->sock, level, name, (char *) &val, sizeof(val)) < 0) { | ||
| 127 | lua_pushnil(L); | ||
| 128 | lua_pushstring(L, "setsockopt failed"); | ||
| 129 | return 2; | ||
| 130 | } | ||
| 131 | lua_pushnumber(L, 1); | ||
| 132 | return 1; | ||
| 133 | } | ||
| 134 | |||
| 135 | /* disables the Nagle algorithm */ | ||
| 136 | static int opt_nodelay(lua_State *L) | ||
| 137 | { | ||
| 138 | struct protoent *pe = getprotobyname("TCP"); | ||
| 139 | if (!pe) { | ||
| 140 | lua_pushnil(L); | ||
| 141 | lua_pushstring(L, "getprotobyname"); | ||
| 142 | return 2; | ||
| 143 | } | ||
| 144 | return opt_boolean(L, pe->p_proto, TCP_NODELAY); | ||
| 145 | } | ||
| 146 | |||
| 147 | static int opt_keepalive(lua_State *L) | ||
| 148 | { | ||
| 149 | return opt_boolean(L, SOL_SOCKET, SO_KEEPALIVE); | ||
| 150 | } | ||
| 151 | |||
| 152 | int opt_linger(lua_State *L) | ||
| 153 | { | ||
| 154 | p_tcp tcp = (p_tcp) aux_checkclass(L, "tcp{client}", 1); | ||
| 155 | struct linger li; | ||
| 156 | if (!lua_istable(L, 2)) | ||
| 157 | luaL_typerror(L, 2, lua_typename(L, LUA_TTABLE)); | ||
| 158 | lua_pushstring(L, "onoff"); | ||
| 159 | lua_gettable(L, 2); | ||
| 160 | if (!lua_isnumber(L, -1)) luaL_argerror(L, 2, "invalid onoff field"); | ||
| 161 | li.l_onoff = (int) lua_tonumber(L, -1); | ||
| 162 | lua_pushstring(L, "linger"); | ||
| 163 | lua_gettable(L, 2); | ||
| 164 | if (!lua_isnumber(L, -1)) luaL_argerror(L, 2, "invalid linger field"); | ||
| 165 | li.l_linger = (int) lua_tonumber(L, -1); | ||
| 166 | if (setsockopt(tcp->sock, SOL_SOCKET, SO_LINGER, | ||
| 167 | (char *) &li, sizeof(li) < 0)) { | ||
| 168 | lua_pushnil(L); | ||
| 169 | lua_pushstring(L, "setsockopt failed"); | ||
| 170 | return 2; | ||
| 171 | } | ||
| 172 | lua_pushnumber(L, 1); | ||
| 173 | return 1; | ||
| 174 | } | ||
| 175 | |||
| 176 | /*-------------------------------------------------------------------------*\ | ||
| 100 | * Select support methods | 177 | * Select support methods |
| 101 | \*-------------------------------------------------------------------------*/ | 178 | \*-------------------------------------------------------------------------*/ |
| 102 | static int meth_fd(lua_State *L) | 179 | static int meth_fd(lua_State *L) |
| 103 | { | 180 | { |
| 104 | p_tcp tcp = (p_tcp) aux_checkclass(L, "tcp{client, server}", 1); | 181 | p_tcp tcp = (p_tcp) aux_checkgroup(L, "tcp{client, server}", 1); |
| 105 | lua_pushnumber(L, tcp->sock); | 182 | lua_pushnumber(L, tcp->sock); |
| 106 | return 1; | 183 | return 1; |
| 107 | } | 184 | } |
| 108 | 185 | ||
| 109 | static int meth_dirty(lua_State *L) | 186 | static int meth_dirty(lua_State *L) |
| 110 | { | 187 | { |
| 111 | p_tcp tcp = (p_tcp) aux_checkclass(L, "tcp{client, server}", 1); | 188 | p_tcp tcp = (p_tcp) aux_checkgroup(L, "tcp{client, server}", 1); |
| 112 | lua_pushboolean(L, !buf_isempty(&tcp->buf)); | 189 | lua_pushboolean(L, !buf_isempty(&tcp->buf)); |
| 113 | return 1; | 190 | return 1; |
| 114 | } | 191 | } |
| @@ -207,7 +284,7 @@ static int meth_accept(lua_State *L) | |||
| 207 | if (client->sock == SOCK_INVALID) { | 284 | if (client->sock == SOCK_INVALID) { |
| 208 | if (tm_get(tm) == 0) { | 285 | if (tm_get(tm) == 0) { |
| 209 | lua_pushnil(L); | 286 | lua_pushnil(L); |
| 210 | error_push(L, IO_TIMEOUT); | 287 | io_pusherror(L, IO_TIMEOUT); |
| 211 | return 2; | 288 | return 2; |
| 212 | } | 289 | } |
| 213 | } else break; | 290 | } else break; |
| @@ -1,6 +1,21 @@ | |||
| 1 | #ifndef TCP_H | 1 | #ifndef TCP_H |
| 2 | #define TCP_H | 2 | #define TCP_H |
| 3 | 3 | /*=========================================================================*\ | |
| 4 | * TCP object | ||
| 5 | * LuaSocket toolkit | ||
| 6 | * | ||
| 7 | * The tcp.h module is basicly a glue that puts together modules buffer.h, | ||
| 8 | * timeout.h socket.h and inet.h to provide the LuaSocket TCP (AF_INET, | ||
| 9 | * SOCK_STREAM) support. | ||
| 10 | * | ||
| 11 | * Three classes are defined: master, client and server. The master class is | ||
| 12 | * a newly created tcp object, that has not been bound or connected. Server | ||
| 13 | * objects are tcp objects bound to some local address. Client objects are | ||
| 14 | * tcp objects either connected to some address or returned by the accept | ||
| 15 | * method of a server object. | ||
| 16 | * | ||
| 17 | * RCS ID: $Id$ | ||
| 18 | \*=========================================================================*/ | ||
| 4 | #include <lua.h> | 19 | #include <lua.h> |
| 5 | 20 | ||
| 6 | #include "buffer.h" | 21 | #include "buffer.h" |
| @@ -17,4 +32,4 @@ typedef t_tcp *p_tcp; | |||
| 17 | 32 | ||
| 18 | void tcp_open(lua_State *L); | 33 | void tcp_open(lua_State *L); |
| 19 | 34 | ||
| 20 | #endif | 35 | #endif /* TCP_H */ |
diff --git a/src/timeout.c b/src/timeout.c index 1553069..6a30e3a 100644 --- a/src/timeout.c +++ b/src/timeout.c | |||
| @@ -1,8 +1,6 @@ | |||
| 1 | /*=========================================================================*\ | 1 | /*=========================================================================*\ |
| 2 | * Timeout management functions | 2 | * Timeout management functions |
| 3 | * Global Lua functions: | 3 | * LuaSocket toolkit |
| 4 | * _sleep | ||
| 5 | * _time | ||
| 6 | * | 4 | * |
| 7 | * RCS ID: $Id$ | 5 | * RCS ID: $Id$ |
| 8 | \*=========================================================================*/ | 6 | \*=========================================================================*/ |
diff --git a/src/timeout.h b/src/timeout.h index 43476cb..32eb836 100644 --- a/src/timeout.h +++ b/src/timeout.h | |||
| @@ -1,11 +1,11 @@ | |||
| 1 | #ifndef TM_H | ||
| 2 | #define TM_H | ||
| 1 | /*=========================================================================*\ | 3 | /*=========================================================================*\ |
| 2 | * Timeout management functions | 4 | * Timeout management functions |
| 5 | * LuaSocket toolkit | ||
| 3 | * | 6 | * |
| 4 | * RCS ID: $Id$ | 7 | * RCS ID: $Id$ |
| 5 | \*=========================================================================*/ | 8 | \*=========================================================================*/ |
| 6 | #ifndef TM_H | ||
| 7 | #define TM_H | ||
| 8 | |||
| 9 | #include <lua.h> | 9 | #include <lua.h> |
| 10 | 10 | ||
| 11 | /* timeout control structure */ | 11 | /* timeout control structure */ |
| @@ -28,4 +28,4 @@ int tm_get(p_tm tm); | |||
| 28 | int tm_gettime(void); | 28 | int tm_gettime(void); |
| 29 | int tm_meth_timeout(lua_State *L, p_tm tm); | 29 | int tm_meth_timeout(lua_State *L, p_tm tm); |
| 30 | 30 | ||
| 31 | #endif | 31 | #endif /* TM_H */ |
| @@ -1,5 +1,6 @@ | |||
| 1 | /*=========================================================================*\ | 1 | /*=========================================================================*\ |
| 2 | * UDP object | 2 | * UDP object |
| 3 | * LuaSocket toolkit | ||
| 3 | * | 4 | * |
| 4 | * RCS ID: $Id$ | 5 | * RCS ID: $Id$ |
| 5 | \*=========================================================================*/ | 6 | \*=========================================================================*/ |
| @@ -13,7 +14,6 @@ | |||
| 13 | #include "auxiliar.h" | 14 | #include "auxiliar.h" |
| 14 | #include "socket.h" | 15 | #include "socket.h" |
| 15 | #include "inet.h" | 16 | #include "inet.h" |
| 16 | #include "error.h" | ||
| 17 | #include "udp.h" | 17 | #include "udp.h" |
| 18 | 18 | ||
| 19 | /*=========================================================================*\ | 19 | /*=========================================================================*\ |
| @@ -29,9 +29,12 @@ static int meth_getpeername(lua_State *L); | |||
| 29 | static int meth_setsockname(lua_State *L); | 29 | static int meth_setsockname(lua_State *L); |
| 30 | static int meth_setpeername(lua_State *L); | 30 | static int meth_setpeername(lua_State *L); |
| 31 | static int meth_close(lua_State *L); | 31 | static int meth_close(lua_State *L); |
| 32 | static int meth_setoption(lua_State *L); | ||
| 32 | static int meth_timeout(lua_State *L); | 33 | static int meth_timeout(lua_State *L); |
| 33 | static int meth_fd(lua_State *L); | 34 | static int meth_fd(lua_State *L); |
| 34 | static int meth_dirty(lua_State *L); | 35 | static int meth_dirty(lua_State *L); |
| 36 | static int opt_dontroute(lua_State *L); | ||
| 37 | static int opt_broadcast(lua_State *L); | ||
| 35 | 38 | ||
| 36 | /* udp object methods */ | 39 | /* udp object methods */ |
| 37 | static luaL_reg udp[] = { | 40 | static luaL_reg udp[] = { |
| @@ -45,11 +48,20 @@ static luaL_reg udp[] = { | |||
| 45 | {"receivefrom", meth_receivefrom}, | 48 | {"receivefrom", meth_receivefrom}, |
| 46 | {"timeout", meth_timeout}, | 49 | {"timeout", meth_timeout}, |
| 47 | {"close", meth_close}, | 50 | {"close", meth_close}, |
| 51 | {"setoption", meth_setoption}, | ||
| 52 | {"__gc", meth_close}, | ||
| 48 | {"fd", meth_fd}, | 53 | {"fd", meth_fd}, |
| 49 | {"dirty", meth_dirty}, | 54 | {"dirty", meth_dirty}, |
| 50 | {NULL, NULL} | 55 | {NULL, NULL} |
| 51 | }; | 56 | }; |
| 52 | 57 | ||
| 58 | /* socket options */ | ||
| 59 | static luaL_reg opt[] = { | ||
| 60 | {"dontroute", opt_dontroute}, | ||
| 61 | {"broadcast", opt_broadcast}, | ||
| 62 | {NULL, NULL} | ||
| 63 | }; | ||
| 64 | |||
| 53 | /* functions in library namespace */ | 65 | /* functions in library namespace */ |
| 54 | static luaL_reg func[] = { | 66 | static luaL_reg func[] = { |
| 55 | {"udp", global_create}, | 67 | {"udp", global_create}, |
| @@ -91,7 +103,9 @@ static int meth_send(lua_State *L) | |||
| 91 | err = sock_send(&udp->sock, data, count, &sent, tm_get(tm)); | 103 | err = sock_send(&udp->sock, data, count, &sent, tm_get(tm)); |
| 92 | if (err == IO_DONE) lua_pushnumber(L, sent); | 104 | if (err == IO_DONE) lua_pushnumber(L, sent); |
| 93 | else lua_pushnil(L); | 105 | else lua_pushnil(L); |
| 94 | error_push(L, err); | 106 | /* a 'closed' error on an unconnected means the target address was not |
| 107 | * accepted by the transport layer */ | ||
| 108 | io_pusherror(L, err == IO_CLOSED ? IO_REFUSED : err); | ||
| 95 | return 2; | 109 | return 2; |
| 96 | } | 110 | } |
| 97 | 111 | ||
| @@ -118,7 +132,9 @@ static int meth_sendto(lua_State *L) | |||
| 118 | (SA *) &addr, sizeof(addr), tm_get(tm)); | 132 | (SA *) &addr, sizeof(addr), tm_get(tm)); |
| 119 | if (err == IO_DONE) lua_pushnumber(L, sent); | 133 | if (err == IO_DONE) lua_pushnumber(L, sent); |
| 120 | else lua_pushnil(L); | 134 | else lua_pushnil(L); |
| 121 | error_push(L, err == IO_CLOSED ? IO_REFUSED : err); | 135 | /* a 'closed' error on an unconnected means the target address was not |
| 136 | * accepted by the transport layer */ | ||
| 137 | io_pusherror(L, err == IO_CLOSED ? IO_REFUSED : err); | ||
| 122 | return 2; | 138 | return 2; |
| 123 | } | 139 | } |
| 124 | 140 | ||
| @@ -137,7 +153,7 @@ static int meth_receive(lua_State *L) | |||
| 137 | err = sock_recv(&udp->sock, buffer, count, &got, tm_get(tm)); | 153 | err = sock_recv(&udp->sock, buffer, count, &got, tm_get(tm)); |
| 138 | if (err == IO_DONE) lua_pushlstring(L, buffer, got); | 154 | if (err == IO_DONE) lua_pushlstring(L, buffer, got); |
| 139 | else lua_pushnil(L); | 155 | else lua_pushnil(L); |
| 140 | error_push(L, err); | 156 | io_pusherror(L, err); |
| 141 | return 2; | 157 | return 2; |
| 142 | } | 158 | } |
| 143 | 159 | ||
| @@ -164,7 +180,7 @@ static int meth_receivefrom(lua_State *L) | |||
| 164 | return 3; | 180 | return 3; |
| 165 | } else { | 181 | } else { |
| 166 | lua_pushnil(L); | 182 | lua_pushnil(L); |
| 167 | error_push(L, err); | 183 | io_pusherror(L, err); |
| 168 | return 2; | 184 | return 2; |
| 169 | } | 185 | } |
| 170 | } | 186 | } |
| @@ -174,14 +190,14 @@ static int meth_receivefrom(lua_State *L) | |||
| 174 | \*-------------------------------------------------------------------------*/ | 190 | \*-------------------------------------------------------------------------*/ |
| 175 | static int meth_fd(lua_State *L) | 191 | static int meth_fd(lua_State *L) |
| 176 | { | 192 | { |
| 177 | p_udp udp = (p_udp) aux_checkclass(L, "udp{any}", 1); | 193 | p_udp udp = (p_udp) aux_checkgroup(L, "udp{any}", 1); |
| 178 | lua_pushnumber(L, udp->sock); | 194 | lua_pushnumber(L, udp->sock); |
| 179 | return 1; | 195 | return 1; |
| 180 | } | 196 | } |
| 181 | 197 | ||
| 182 | static int meth_dirty(lua_State *L) | 198 | static int meth_dirty(lua_State *L) |
| 183 | { | 199 | { |
| 184 | p_udp udp = (p_udp) aux_checkclass(L, "udp{any}", 1); | 200 | p_udp udp = (p_udp) aux_checkgroup(L, "udp{any}", 1); |
| 185 | (void) udp; | 201 | (void) udp; |
| 186 | lua_pushboolean(L, 0); | 202 | lua_pushboolean(L, 0); |
| 187 | return 1; | 203 | return 1; |
| @@ -203,6 +219,37 @@ static int meth_getsockname(lua_State *L) | |||
| 203 | } | 219 | } |
| 204 | 220 | ||
| 205 | /*-------------------------------------------------------------------------*\ | 221 | /*-------------------------------------------------------------------------*\ |
| 222 | * Option handlers | ||
| 223 | \*-------------------------------------------------------------------------*/ | ||
| 224 | static int meth_setoption(lua_State *L) | ||
| 225 | { | ||
| 226 | return aux_meth_setoption(L, opt); | ||
| 227 | } | ||
| 228 | |||
| 229 | static int opt_boolean(lua_State *L, int level, int name) | ||
| 230 | { | ||
| 231 | p_udp udp = (p_udp) aux_checkgroup(L, "udp{any}", 1); | ||
| 232 | int val = aux_checkboolean(L, 2); | ||
| 233 | if (setsockopt(udp->sock, level, name, (char *) &val, sizeof(val)) < 0) { | ||
| 234 | lua_pushnil(L); | ||
| 235 | lua_pushstring(L, "setsockopt failed"); | ||
| 236 | return 2; | ||
| 237 | } | ||
| 238 | lua_pushnumber(L, 1); | ||
| 239 | return 1; | ||
| 240 | } | ||
| 241 | |||
| 242 | static int opt_dontroute(lua_State *L) | ||
| 243 | { | ||
| 244 | return opt_boolean(L, SOL_SOCKET, SO_DONTROUTE); | ||
| 245 | } | ||
| 246 | |||
| 247 | static int opt_broadcast(lua_State *L) | ||
| 248 | { | ||
| 249 | return opt_boolean(L, SOL_SOCKET, SO_BROADCAST); | ||
| 250 | } | ||
| 251 | |||
| 252 | /*-------------------------------------------------------------------------*\ | ||
| 206 | * Just call tm methods | 253 | * Just call tm methods |
| 207 | \*-------------------------------------------------------------------------*/ | 254 | \*-------------------------------------------------------------------------*/ |
| 208 | static int meth_timeout(lua_State *L) | 255 | static int meth_timeout(lua_State *L) |
| @@ -1,6 +1,19 @@ | |||
| 1 | #ifndef UDP_H | 1 | #ifndef UDP_H |
| 2 | #define UDP_H | 2 | #define UDP_H |
| 3 | 3 | /*=========================================================================*\ | |
| 4 | * UDP object | ||
| 5 | * LuaSocket toolkit | ||
| 6 | * | ||
| 7 | * The udp.h module provides LuaSocket with support for UDP protocol | ||
| 8 | * (AF_INET, SOCK_DGRAM). | ||
| 9 | * | ||
| 10 | * Two classes are defined: connected and unconnected. UDP objects are | ||
| 11 | * originally unconnected. They can be "connected" to a given address | ||
| 12 | * with a call to the setpeername function. The same function can be used to | ||
| 13 | * break the connection. | ||
| 14 | * | ||
| 15 | * RCS ID: $Id$ | ||
| 16 | \*=========================================================================*/ | ||
| 4 | #include <lua.h> | 17 | #include <lua.h> |
| 5 | 18 | ||
| 6 | #include "timeout.h" | 19 | #include "timeout.h" |
| @@ -16,4 +29,4 @@ typedef t_udp *p_udp; | |||
| 16 | 29 | ||
| 17 | void udp_open(lua_State *L); | 30 | void udp_open(lua_State *L); |
| 18 | 31 | ||
| 19 | #endif | 32 | #endif /* UDP_H */ |
diff --git a/src/url.lua b/src/url.lua index 06de9d3..65da57a 100644 --- a/src/url.lua +++ b/src/url.lua | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | ----------------------------------------------------------------------------- | 1 | ----------------------------------------------------------------------------- |
| 2 | -- URI parsing, composition and relative URL resolution | 2 | -- URI parsing, composition and relative URL resolution |
| 3 | -- LuaSocket 1.5 toolkit. | 3 | -- LuaSocket toolkit. |
| 4 | -- Author: Diego Nehab | 4 | -- Author: Diego Nehab |
| 5 | -- Conforming to: RFC 2396, LTN7 | 5 | -- Conforming to: RFC 2396, LTN7 |
| 6 | -- RCS ID: $Id$ | 6 | -- RCS ID: $Id$ |
diff --git a/src/usocket.c b/src/usocket.c index 062a0ff..cdd550c 100644 --- a/src/usocket.c +++ b/src/usocket.c | |||
| @@ -1,49 +1,78 @@ | |||
| 1 | /*=========================================================================*\ | ||
| 2 | * Socket compatibilization module for Unix | ||
| 3 | * LuaSocket toolkit | ||
| 4 | * | ||
| 5 | * RCS ID: $Id$ | ||
| 6 | \*=========================================================================*/ | ||
| 1 | #include <string.h> | 7 | #include <string.h> |
| 2 | 8 | ||
| 3 | #include "socket.h" | 9 | #include "socket.h" |
| 4 | 10 | ||
| 11 | /*-------------------------------------------------------------------------*\ | ||
| 12 | * Initializes module | ||
| 13 | \*-------------------------------------------------------------------------*/ | ||
| 5 | int sock_open(void) | 14 | int sock_open(void) |
| 6 | { | 15 | { |
| 7 | /* instals a handler to ignore sigpipe. */ | 16 | /* instals a handler to ignore sigpipe or it will crash us */ |
| 8 | struct sigaction new; | 17 | struct sigaction ignore; |
| 9 | memset(&new, 0, sizeof(new)); | 18 | memset(&ignore, 0, sizeof(ignore)); |
| 10 | new.sa_handler = SIG_IGN; | 19 | ignore.sa_handler = SIG_IGN; |
| 11 | sigaction(SIGPIPE, &new, NULL); | 20 | sigaction(SIGPIPE, &ignore, NULL); |
| 12 | return 1; | 21 | return 1; |
| 13 | } | 22 | } |
| 14 | 23 | ||
| 24 | /*-------------------------------------------------------------------------*\ | ||
| 25 | * Close and inutilize socket | ||
| 26 | \*-------------------------------------------------------------------------*/ | ||
| 15 | void sock_destroy(p_sock ps) | 27 | void sock_destroy(p_sock ps) |
| 16 | { | 28 | { |
| 17 | close(*ps); | 29 | close(*ps); |
| 30 | *ps = SOCK_INVALID; | ||
| 18 | } | 31 | } |
| 19 | 32 | ||
| 33 | /*-------------------------------------------------------------------------*\ | ||
| 34 | * Creates and sets up a socket | ||
| 35 | \*-------------------------------------------------------------------------*/ | ||
| 20 | const char *sock_create(p_sock ps, int domain, int type, int protocol) | 36 | const char *sock_create(p_sock ps, int domain, int type, int protocol) |
| 21 | { | 37 | { |
| 38 | int val = 1; | ||
| 22 | t_sock sock = socket(domain, type, protocol); | 39 | t_sock sock = socket(domain, type, protocol); |
| 23 | if (sock == SOCK_INVALID) return sock_createstrerror(); | 40 | if (sock == SOCK_INVALID) return sock_createstrerror(); |
| 24 | *ps = sock; | 41 | *ps = sock; |
| 25 | sock_setnonblocking(ps); | 42 | sock_setnonblocking(ps); |
| 26 | sock_setreuseaddr(ps); | 43 | setsockopt(*ps, SOL_SOCKET, SO_REUSEADDR, (char *) &val, sizeof(val)); |
| 27 | return NULL; | 44 | return NULL; |
| 28 | } | 45 | } |
| 29 | 46 | ||
| 47 | /*-------------------------------------------------------------------------*\ | ||
| 48 | * Connects or returns error message | ||
| 49 | \*-------------------------------------------------------------------------*/ | ||
| 30 | const char *sock_connect(p_sock ps, SA *addr, socklen_t addr_len) | 50 | const char *sock_connect(p_sock ps, SA *addr, socklen_t addr_len) |
| 31 | { | 51 | { |
| 32 | if (connect(*ps, addr, addr_len) < 0) return sock_connectstrerror(); | 52 | if (connect(*ps, addr, addr_len) < 0) return sock_connectstrerror(); |
| 33 | else return NULL; | 53 | else return NULL; |
| 34 | } | 54 | } |
| 35 | 55 | ||
| 56 | /*-------------------------------------------------------------------------*\ | ||
| 57 | * Binds or returns error message | ||
| 58 | \*-------------------------------------------------------------------------*/ | ||
| 36 | const char *sock_bind(p_sock ps, SA *addr, socklen_t addr_len) | 59 | const char *sock_bind(p_sock ps, SA *addr, socklen_t addr_len) |
| 37 | { | 60 | { |
| 38 | if (bind(*ps, addr, addr_len) < 0) return sock_bindstrerror(); | 61 | if (bind(*ps, addr, addr_len) < 0) return sock_bindstrerror(); |
| 39 | else return NULL; | 62 | else return NULL; |
| 40 | } | 63 | } |
| 41 | 64 | ||
| 65 | /*-------------------------------------------------------------------------*\ | ||
| 66 | * | ||
| 67 | \*-------------------------------------------------------------------------*/ | ||
| 42 | void sock_listen(p_sock ps, int backlog) | 68 | void sock_listen(p_sock ps, int backlog) |
| 43 | { | 69 | { |
| 44 | listen(*ps, backlog); | 70 | listen(*ps, backlog); |
| 45 | } | 71 | } |
| 46 | 72 | ||
| 73 | /*-------------------------------------------------------------------------*\ | ||
| 74 | * Accept with timeout | ||
| 75 | \*-------------------------------------------------------------------------*/ | ||
| 47 | int sock_accept(p_sock ps, p_sock pa, SA *addr, socklen_t *addr_len, | 76 | int sock_accept(p_sock ps, p_sock pa, SA *addr, socklen_t *addr_len, |
| 48 | int timeout) | 77 | int timeout) |
| 49 | { | 78 | { |
| @@ -65,6 +94,9 @@ int sock_accept(p_sock ps, p_sock pa, SA *addr, socklen_t *addr_len, | |||
| 65 | else return IO_DONE; | 94 | else return IO_DONE; |
| 66 | } | 95 | } |
| 67 | 96 | ||
| 97 | /*-------------------------------------------------------------------------*\ | ||
| 98 | * Send with timeout | ||
| 99 | \*-------------------------------------------------------------------------*/ | ||
| 68 | int sock_send(p_sock ps, const char *data, size_t count, size_t *sent, | 100 | int sock_send(p_sock ps, const char *data, size_t count, size_t *sent, |
| 69 | int timeout) | 101 | int timeout) |
| 70 | { | 102 | { |
| @@ -99,6 +131,9 @@ int sock_send(p_sock ps, const char *data, size_t count, size_t *sent, | |||
| 99 | } | 131 | } |
| 100 | } | 132 | } |
| 101 | 133 | ||
| 134 | /*-------------------------------------------------------------------------*\ | ||
| 135 | * Sendto with timeout | ||
| 136 | \*-------------------------------------------------------------------------*/ | ||
| 102 | int sock_sendto(p_sock ps, const char *data, size_t count, size_t *sent, | 137 | int sock_sendto(p_sock ps, const char *data, size_t count, size_t *sent, |
| 103 | SA *addr, socklen_t addr_len, int timeout) | 138 | SA *addr, socklen_t addr_len, int timeout) |
| 104 | { | 139 | { |
| @@ -133,6 +168,9 @@ int sock_sendto(p_sock ps, const char *data, size_t count, size_t *sent, | |||
| 133 | } | 168 | } |
| 134 | } | 169 | } |
| 135 | 170 | ||
| 171 | /*-------------------------------------------------------------------------*\ | ||
| 172 | * Receive with timeout | ||
| 173 | \*-------------------------------------------------------------------------*/ | ||
| 136 | int sock_recv(p_sock ps, char *data, size_t count, size_t *got, int timeout) | 174 | int sock_recv(p_sock ps, char *data, size_t count, size_t *got, int timeout) |
| 137 | { | 175 | { |
| 138 | t_sock sock = *ps; | 176 | t_sock sock = *ps; |
| @@ -160,6 +198,9 @@ int sock_recv(p_sock ps, char *data, size_t count, size_t *got, int timeout) | |||
| 160 | } | 198 | } |
| 161 | } | 199 | } |
| 162 | 200 | ||
| 201 | /*-------------------------------------------------------------------------*\ | ||
| 202 | * Recvfrom with timeout | ||
| 203 | \*-------------------------------------------------------------------------*/ | ||
| 163 | int sock_recvfrom(p_sock ps, char *data, size_t count, size_t *got, | 204 | int sock_recvfrom(p_sock ps, char *data, size_t count, size_t *got, |
| 164 | SA *addr, socklen_t *addr_len, int timeout) | 205 | SA *addr, socklen_t *addr_len, int timeout) |
| 165 | { | 206 | { |
| @@ -188,6 +229,29 @@ int sock_recvfrom(p_sock ps, char *data, size_t count, size_t *got, | |||
| 188 | } | 229 | } |
| 189 | } | 230 | } |
| 190 | 231 | ||
| 232 | /*-------------------------------------------------------------------------*\ | ||
| 233 | * Put socket into blocking mode | ||
| 234 | \*-------------------------------------------------------------------------*/ | ||
| 235 | void sock_setblocking(p_sock ps) | ||
| 236 | { | ||
| 237 | int flags = fcntl(*ps, F_GETFL, 0); | ||
| 238 | flags &= (~(O_NONBLOCK)); | ||
| 239 | fcntl(*ps, F_SETFL, flags); | ||
| 240 | } | ||
| 241 | |||
| 242 | /*-------------------------------------------------------------------------*\ | ||
| 243 | * Put socket into non-blocking mode | ||
| 244 | \*-------------------------------------------------------------------------*/ | ||
| 245 | void sock_setnonblocking(p_sock ps) | ||
| 246 | { | ||
| 247 | int flags = fcntl(*ps, F_GETFL, 0); | ||
| 248 | flags |= O_NONBLOCK; | ||
| 249 | fcntl(*ps, F_SETFL, flags); | ||
| 250 | } | ||
| 251 | |||
| 252 | /*-------------------------------------------------------------------------*\ | ||
| 253 | * Error translation functions | ||
| 254 | \*-------------------------------------------------------------------------*/ | ||
| 191 | const char *sock_hoststrerror(void) | 255 | const char *sock_hoststrerror(void) |
| 192 | { | 256 | { |
| 193 | switch (h_errno) { | 257 | switch (h_errno) { |
| @@ -238,23 +302,3 @@ const char *sock_connectstrerror(void) | |||
| 238 | default: return "unknown error"; | 302 | default: return "unknown error"; |
| 239 | } | 303 | } |
| 240 | } | 304 | } |
| 241 | |||
| 242 | void sock_setreuseaddr(p_sock ps) | ||
| 243 | { | ||
| 244 | int val = 1; | ||
| 245 | setsockopt(*ps, SOL_SOCKET, SO_REUSEADDR, (char *)&val, sizeof(val)); | ||
| 246 | } | ||
| 247 | |||
| 248 | void sock_setblocking(p_sock ps) | ||
| 249 | { | ||
| 250 | int flags = fcntl(*ps, F_GETFL, 0); | ||
| 251 | flags &= (~(O_NONBLOCK)); | ||
| 252 | fcntl(*ps, F_SETFL, flags); | ||
| 253 | } | ||
| 254 | |||
| 255 | void sock_setnonblocking(p_sock ps) | ||
| 256 | { | ||
| 257 | int flags = fcntl(*ps, F_GETFL, 0); | ||
| 258 | flags |= O_NONBLOCK; | ||
| 259 | fcntl(*ps, F_SETFL, flags); | ||
| 260 | } | ||
diff --git a/src/usocket.h b/src/usocket.h index 034ae74..85b7caa 100644 --- a/src/usocket.h +++ b/src/usocket.h | |||
| @@ -1,10 +1,11 @@ | |||
| 1 | #ifndef USOCKET_H | ||
| 2 | #define USOCKET_H | ||
| 1 | /*=========================================================================*\ | 3 | /*=========================================================================*\ |
| 2 | * Socket compatibilization module for Unix | 4 | * Socket compatibilization module for Unix |
| 5 | * LuaSocket toolkit | ||
| 3 | * | 6 | * |
| 4 | * RCS ID: $Id$ | 7 | * RCS ID: $Id$ |
| 5 | \*=========================================================================*/ | 8 | \*=========================================================================*/ |
| 6 | #ifndef USOCKET_H | ||
| 7 | #define USOCKET_H | ||
| 8 | 9 | ||
| 9 | /*=========================================================================*\ | 10 | /*=========================================================================*\ |
| 10 | * BSD include files | 11 | * BSD include files |
| @@ -30,9 +31,11 @@ | |||
| 30 | /* IP stuff*/ | 31 | /* IP stuff*/ |
| 31 | #include <netinet/in.h> | 32 | #include <netinet/in.h> |
| 32 | #include <arpa/inet.h> | 33 | #include <arpa/inet.h> |
| 34 | /* TCP options (nagle algorithm disable) */ | ||
| 35 | #include <netinet/tcp.h> | ||
| 33 | 36 | ||
| 34 | #ifdef __APPLE__ | 37 | #ifdef __APPLE__ |
| 35 | /* for some reason socklen_t is not defined in mac os x */ | 38 | /* for some reason socklen_t is not defined in Mac Os X */ |
| 36 | typedef int socklen_t; | 39 | typedef int socklen_t; |
| 37 | #endif | 40 | #endif |
| 38 | 41 | ||
diff --git a/src/wsocket.c b/src/wsocket.c index 56e65ec..2ce828e 100644 --- a/src/wsocket.c +++ b/src/wsocket.c | |||
| @@ -1,14 +1,21 @@ | |||
| 1 | /*=========================================================================*\ | ||
| 2 | * Socket compatibilization module for Win32 | ||
| 3 | * LuaSocket toolkit | ||
| 4 | * | ||
| 5 | * RCS ID: $Id$ | ||
| 6 | \*=========================================================================*/ | ||
| 1 | #include <string.h> | 7 | #include <string.h> |
| 2 | 8 | ||
| 3 | #include "socket.h" | 9 | #include "socket.h" |
| 4 | 10 | ||
| 11 | /*-------------------------------------------------------------------------*\ | ||
| 12 | * Initializes module | ||
| 13 | \*-------------------------------------------------------------------------*/ | ||
| 5 | int sock_open(void) | 14 | int sock_open(void) |
| 6 | { | 15 | { |
| 7 | WORD wVersionRequested; | ||
| 8 | WSADATA wsaData; | 16 | WSADATA wsaData; |
| 9 | int err; | 17 | WORD wVersionRequested = MAKEWORD(2, 0); |
| 10 | wVersionRequested = MAKEWORD(2, 0); | 18 | int err = WSAStartup(wVersionRequested, &wsaData ); |
| 11 | err = WSAStartup(wVersionRequested, &wsaData ); | ||
| 12 | if (err != 0) return 0; | 19 | if (err != 0) return 0; |
| 13 | if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 0) { | 20 | if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 0) { |
| 14 | WSACleanup(); | 21 | WSACleanup(); |
| @@ -17,38 +24,58 @@ int sock_open(void) | |||
| 17 | return 1; | 24 | return 1; |
| 18 | } | 25 | } |
| 19 | 26 | ||
| 27 | /*-------------------------------------------------------------------------*\ | ||
| 28 | * Close and inutilize socket | ||
| 29 | \*-------------------------------------------------------------------------*/ | ||
| 20 | void sock_destroy(p_sock ps) | 30 | void sock_destroy(p_sock ps) |
| 21 | { | 31 | { |
| 22 | closesocket(*ps); | 32 | closesocket(*ps); |
| 33 | *ps = SOCK_INVALID; | ||
| 23 | } | 34 | } |
| 24 | 35 | ||
| 36 | /*-------------------------------------------------------------------------*\ | ||
| 37 | * Creates and sets up a socket | ||
| 38 | \*-------------------------------------------------------------------------*/ | ||
| 25 | const char *sock_create(p_sock ps, int domain, int type, int protocol) | 39 | const char *sock_create(p_sock ps, int domain, int type, int protocol) |
| 26 | { | 40 | { |
| 41 | int val = 1; | ||
| 27 | t_sock sock = socket(domain, type, protocol); | 42 | t_sock sock = socket(domain, type, protocol); |
| 28 | if (sock == SOCK_INVALID) return sock_createstrerror(); | 43 | if (sock == SOCK_INVALID) return sock_createstrerror(); |
| 29 | *ps = sock; | 44 | *ps = sock; |
| 30 | sock_setnonblocking(ps); | 45 | sock_setnonblocking(ps); |
| 31 | sock_setreuseaddr(ps); | 46 | setsockopt(*ps, SOL_SOCKET, SO_REUSEADDR, (char *) &val, sizeof(val)); |
| 32 | return NULL; | 47 | return NULL; |
| 33 | } | 48 | } |
| 34 | 49 | ||
| 50 | /*-------------------------------------------------------------------------*\ | ||
| 51 | * Connects or returns error message | ||
| 52 | \*-------------------------------------------------------------------------*/ | ||
| 35 | const char *sock_connect(p_sock ps, SA *addr, socklen_t addr_len) | 53 | const char *sock_connect(p_sock ps, SA *addr, socklen_t addr_len) |
| 36 | { | 54 | { |
| 37 | if (connect(*ps, addr, addr_len) < 0) return sock_connectstrerror(); | 55 | if (connect(*ps, addr, addr_len) < 0) return sock_connectstrerror(); |
| 38 | else return NULL; | 56 | else return NULL; |
| 39 | } | 57 | } |
| 40 | 58 | ||
| 59 | /*-------------------------------------------------------------------------*\ | ||
| 60 | * Binds or returns error message | ||
| 61 | \*-------------------------------------------------------------------------*/ | ||
| 41 | const char *sock_bind(p_sock ps, SA *addr, socklen_t addr_len) | 62 | const char *sock_bind(p_sock ps, SA *addr, socklen_t addr_len) |
| 42 | { | 63 | { |
| 43 | if (bind(*ps, addr, addr_len) < 0) return sock_bindstrerror(); | 64 | if (bind(*ps, addr, addr_len) < 0) return sock_bindstrerror(); |
| 44 | else return NULL; | 65 | else return NULL; |
| 45 | } | 66 | } |
| 46 | 67 | ||
| 68 | /*-------------------------------------------------------------------------*\ | ||
| 69 | * | ||
| 70 | \*-------------------------------------------------------------------------*/ | ||
| 47 | void sock_listen(p_sock ps, int backlog) | 71 | void sock_listen(p_sock ps, int backlog) |
| 48 | { | 72 | { |
| 49 | listen(*ps, backlog); | 73 | listen(*ps, backlog); |
| 50 | } | 74 | } |
| 51 | 75 | ||
| 76 | /*-------------------------------------------------------------------------*\ | ||
| 77 | * Accept with timeout | ||
| 78 | \*-------------------------------------------------------------------------*/ | ||
| 52 | int sock_accept(p_sock ps, p_sock pa, SA *addr, socklen_t *addr_len, | 79 | int sock_accept(p_sock ps, p_sock pa, SA *addr, socklen_t *addr_len, |
| 53 | int timeout) | 80 | int timeout) |
| 54 | { | 81 | { |
| @@ -70,6 +97,9 @@ int sock_accept(p_sock ps, p_sock pa, SA *addr, socklen_t *addr_len, | |||
| 70 | else return IO_DONE; | 97 | else return IO_DONE; |
| 71 | } | 98 | } |
| 72 | 99 | ||
| 100 | /*-------------------------------------------------------------------------*\ | ||
| 101 | * Send with timeout | ||
| 102 | \*-------------------------------------------------------------------------*/ | ||
| 73 | int sock_send(p_sock ps, const char *data, size_t count, size_t *sent, | 103 | int sock_send(p_sock ps, const char *data, size_t count, size_t *sent, |
| 74 | int timeout) | 104 | int timeout) |
| 75 | { | 105 | { |
| @@ -104,6 +134,9 @@ int sock_send(p_sock ps, const char *data, size_t count, size_t *sent, | |||
| 104 | } | 134 | } |
| 105 | } | 135 | } |
| 106 | 136 | ||
| 137 | /*-------------------------------------------------------------------------*\ | ||
| 138 | * Sendto with timeout | ||
| 139 | \*-------------------------------------------------------------------------*/ | ||
| 107 | int sock_sendto(p_sock ps, const char *data, size_t count, size_t *sent, | 140 | int sock_sendto(p_sock ps, const char *data, size_t count, size_t *sent, |
| 108 | SA *addr, socklen_t addr_len, int timeout) | 141 | SA *addr, socklen_t addr_len, int timeout) |
| 109 | { | 142 | { |
| @@ -138,6 +171,9 @@ int sock_sendto(p_sock ps, const char *data, size_t count, size_t *sent, | |||
| 138 | } | 171 | } |
| 139 | } | 172 | } |
| 140 | 173 | ||
| 174 | /*-------------------------------------------------------------------------*\ | ||
| 175 | * Receive with timeout | ||
| 176 | \*-------------------------------------------------------------------------*/ | ||
| 141 | int sock_recv(p_sock ps, char *data, size_t count, size_t *got, int timeout) | 177 | int sock_recv(p_sock ps, char *data, size_t count, size_t *got, int timeout) |
| 142 | { | 178 | { |
| 143 | t_sock sock = *ps; | 179 | t_sock sock = *ps; |
| @@ -165,6 +201,9 @@ int sock_recv(p_sock ps, char *data, size_t count, size_t *got, int timeout) | |||
| 165 | } | 201 | } |
| 166 | } | 202 | } |
| 167 | 203 | ||
| 204 | /*-------------------------------------------------------------------------*\ | ||
| 205 | * Recvfrom with timeout | ||
| 206 | \*-------------------------------------------------------------------------*/ | ||
| 168 | int sock_recvfrom(p_sock ps, char *data, size_t count, size_t *got, | 207 | int sock_recvfrom(p_sock ps, char *data, size_t count, size_t *got, |
| 169 | SA *addr, socklen_t *addr_len, int timeout) | 208 | SA *addr, socklen_t *addr_len, int timeout) |
| 170 | { | 209 | { |
| @@ -193,6 +232,27 @@ int sock_recvfrom(p_sock ps, char *data, size_t count, size_t *got, | |||
| 193 | } | 232 | } |
| 194 | } | 233 | } |
| 195 | 234 | ||
| 235 | /*-------------------------------------------------------------------------*\ | ||
| 236 | * Put socket into blocking mode | ||
| 237 | \*-------------------------------------------------------------------------*/ | ||
| 238 | void sock_setblocking(p_sock ps) | ||
| 239 | { | ||
| 240 | u_long argp = 0; | ||
| 241 | ioctlsocket(*ps, FIONBIO, &argp); | ||
| 242 | } | ||
| 243 | |||
| 244 | /*-------------------------------------------------------------------------*\ | ||
| 245 | * Put socket into non-blocking mode | ||
| 246 | \*-------------------------------------------------------------------------*/ | ||
| 247 | void sock_setnonblocking(p_sock ps) | ||
| 248 | { | ||
| 249 | u_long argp = 1; | ||
| 250 | ioctlsocket(*ps, FIONBIO, &argp); | ||
| 251 | } | ||
| 252 | |||
| 253 | /*-------------------------------------------------------------------------*\ | ||
| 254 | * Error translation functions | ||
| 255 | \*-------------------------------------------------------------------------*/ | ||
| 196 | const char *sock_hoststrerror(void) | 256 | const char *sock_hoststrerror(void) |
| 197 | { | 257 | { |
| 198 | switch (WSAGetLastError()) { | 258 | switch (WSAGetLastError()) { |
| @@ -241,21 +301,3 @@ const char *sock_connectstrerror(void) | |||
| 241 | default: return "unknown error"; | 301 | default: return "unknown error"; |
| 242 | } | 302 | } |
| 243 | } | 303 | } |
| 244 | |||
| 245 | void sock_setreuseaddr(p_sock ps) | ||
| 246 | { | ||
| 247 | int val = 1; | ||
| 248 | setsockopt(*ps, SOL_SOCKET, SO_REUSEADDR, (char *)&val, sizeof(val)); | ||
| 249 | } | ||
| 250 | |||
| 251 | void sock_setblocking(p_sock ps) | ||
| 252 | { | ||
| 253 | u_long argp = 0; | ||
| 254 | ioctlsocket(*ps, FIONBIO, &argp); | ||
| 255 | } | ||
| 256 | |||
| 257 | void sock_setnonblocking(p_sock ps) | ||
| 258 | { | ||
| 259 | u_long argp = 1; | ||
| 260 | ioctlsocket(*ps, FIONBIO, &argp); | ||
| 261 | } | ||
diff --git a/src/wsocket.h b/src/wsocket.h index ceecae7..d77841e 100644 --- a/src/wsocket.h +++ b/src/wsocket.h | |||
| @@ -1,16 +1,16 @@ | |||
| 1 | #ifndef WSOCKET_H | ||
| 2 | #define WSOCKET_H | ||
| 1 | /*=========================================================================*\ | 3 | /*=========================================================================*\ |
| 2 | * Socket compatibilization module for Win32 | 4 | * Socket compatibilization module for Win32 |
| 5 | * LuaSocket toolkit | ||
| 3 | * | 6 | * |
| 4 | * RCS ID: $Id$ | 7 | * RCS ID: $Id$ |
| 5 | \*=========================================================================*/ | 8 | \*=========================================================================*/ |
| 6 | #ifndef WSOCKET_H | ||
| 7 | #define WSOCKET_H | ||
| 8 | 9 | ||
| 9 | /*=========================================================================*\ | 10 | /*=========================================================================*\ |
| 10 | * WinSock2 include files | 11 | * WinSock include files |
| 11 | \*=========================================================================*/ | 12 | \*=========================================================================*/ |
| 12 | #include <winsock2.h> | 13 | #include <winsock.h> |
| 13 | #include <winbase.h> | ||
| 14 | 14 | ||
| 15 | typedef int socklen_t; | 15 | typedef int socklen_t; |
| 16 | typedef int ssize_t; | 16 | typedef int ssize_t; |
diff --git a/test/testclnt.lua b/test/testclnt.lua index b2b4b18..e38c248 100644 --- a/test/testclnt.lua +++ b/test/testclnt.lua | |||
| @@ -17,12 +17,14 @@ function warn(...) | |||
| 17 | io.write("WARNING: ", s, "\n") | 17 | io.write("WARNING: ", s, "\n") |
| 18 | end | 18 | end |
| 19 | 19 | ||
| 20 | pad = string.rep(" ", 8192) | ||
| 21 | |||
| 20 | function remote(...) | 22 | function remote(...) |
| 21 | local s = string.format(unpack(arg)) | 23 | local s = string.format(unpack(arg)) |
| 22 | s = string.gsub(s, "\n", ";") | 24 | s = string.gsub(s, "\n", ";") |
| 23 | s = string.gsub(s, "%s+", " ") | 25 | s = string.gsub(s, "%s+", " ") |
| 24 | s = string.gsub(s, "^%s*", "") | 26 | s = string.gsub(s, "^%s*", "") |
| 25 | control:send(s, "\n") | 27 | control:send(pad, s, "\n") |
| 26 | control:receive() | 28 | control:receive() |
| 27 | end | 29 | end |
| 28 | 30 | ||
| @@ -82,16 +84,19 @@ function reconnect() | |||
| 82 | remote [[ | 84 | remote [[ |
| 83 | if data then data:close() data = nil end | 85 | if data then data:close() data = nil end |
| 84 | data = server:accept() | 86 | data = server:accept() |
| 87 | data:setoption("nodelay", true) | ||
| 85 | ]] | 88 | ]] |
| 86 | data, err = socket.connect(host, port) | 89 | data, err = socket.connect(host, port) |
| 87 | if not data then fail(err) | 90 | if not data then fail(err) |
| 88 | else pass("connected!") end | 91 | else pass("connected!") end |
| 92 | data:setoption("nodelay", true) | ||
| 89 | end | 93 | end |
| 90 | 94 | ||
| 91 | pass("attempting control connection...") | 95 | pass("attempting control connection...") |
| 92 | control, err = socket.connect(host, port) | 96 | control, err = socket.connect(host, port) |
| 93 | if err then fail(err) | 97 | if err then fail(err) |
| 94 | else pass("connected!") end | 98 | else pass("connected!") end |
| 99 | control:setoption("nodelay", true) | ||
| 95 | 100 | ||
| 96 | ------------------------------------------------------------------------ | 101 | ------------------------------------------------------------------------ |
| 97 | test("method registration") | 102 | test("method registration") |
| @@ -157,16 +162,21 @@ remote "data:send(str); data:close()" | |||
| 157 | end | 162 | end |
| 158 | 163 | ||
| 159 | 164 | ||
| 160 | test_mixed(1) | 165 | --test_mixed(1) |
| 161 | test_mixed(17) | 166 | --test_mixed(17) |
| 162 | test_mixed(200) | 167 | --test_mixed(200) |
| 168 | --test_mixed(4091) | ||
| 169 | --test_mixed(80199) | ||
| 170 | --test_mixed(4091) | ||
| 171 | --test_mixed(200) | ||
| 172 | --test_mixed(17) | ||
| 173 | --test_mixed(1) | ||
| 174 | |||
| 175 | test_mixed(4091) | ||
| 176 | test_mixed(4091) | ||
| 177 | test_mixed(4091) | ||
| 163 | test_mixed(4091) | 178 | test_mixed(4091) |
| 164 | test_mixed(80199) | ||
| 165 | test_mixed(4091) | 179 | test_mixed(4091) |
| 166 | test_mixed(200) | ||
| 167 | test_mixed(17) | ||
| 168 | test_mixed(1) | ||
| 169 | |||
| 170 | ------------------------------------------------------------------------ | 180 | ------------------------------------------------------------------------ |
| 171 | test("character line") | 181 | test("character line") |
| 172 | reconnect() | 182 | reconnect() |
diff --git a/test/testsrvr.lua b/test/testsrvr.lua index 3c40840..39fe274 100644 --- a/test/testsrvr.lua +++ b/test/testsrvr.lua | |||
| @@ -3,9 +3,11 @@ port = port or "8080" | |||
| 3 | 3 | ||
| 4 | server, error = socket.bind(host, port) | 4 | server, error = socket.bind(host, port) |
| 5 | if not server then print("server: " .. tostring(error)) os.exit() end | 5 | if not server then print("server: " .. tostring(error)) os.exit() end |
| 6 | ack = "\n" | ||
| 6 | while 1 do | 7 | while 1 do |
| 7 | print("server: waiting for client connection..."); | 8 | print("server: waiting for client connection..."); |
| 8 | control = server:accept() | 9 | control = server:accept() |
| 10 | control:setoption("nodelay", true) | ||
| 9 | while 1 do | 11 | while 1 do |
| 10 | command, error = control:receive() | 12 | command, error = control:receive() |
| 11 | if error then | 13 | if error then |
| @@ -13,13 +15,12 @@ while 1 do | |||
| 13 | print("server: closing connection...") | 15 | print("server: closing connection...") |
| 14 | break | 16 | break |
| 15 | end | 17 | end |
| 16 | sent, error = control:send("\n") | 18 | sent, error = control:send(ack) |
| 17 | if error then | 19 | if error then |
| 18 | control:close() | 20 | control:close() |
| 19 | print("server: closing connection...") | 21 | print("server: closing connection...") |
| 20 | break | 22 | break |
| 21 | end | 23 | end |
| 22 | print(command); | ||
| 23 | (loadstring(command))() | 24 | (loadstring(command))() |
| 24 | end | 25 | end |
| 25 | end | 26 | end |
