diff options
| author | Caleb Maclennan <caleb@alerque.com> | 2023-11-10 09:12:04 +0300 |
|---|---|---|
| committer | Caleb Maclennan <caleb@alerque.com> | 2023-11-10 09:12:04 +0300 |
| commit | 5c4fc93d5f4137bf4c22ddf1a048c907a4a26727 (patch) | |
| tree | a9a68e1f6a9c3bfe2b64fa1c3a4098865b7d3b5d /src | |
| parent | ccef3bc4e2aa6ee5b997a80aabb58f4ff0b0e98f (diff) | |
| parent | 43a97b7f0053313b43906371dbdc226271e6c8ab (diff) | |
| download | luasocket-hjelmeland-patch-1.tar.gz luasocket-hjelmeland-patch-1.tar.bz2 luasocket-hjelmeland-patch-1.zip | |
Merge branch 'master' into hjelmeland-patch-1hjelmeland-patch-1
Diffstat (limited to '')
| -rw-r--r-- | src/auxiliar.c | 10 | ||||
| -rw-r--r-- | src/auxiliar.h | 20 | ||||
| -rw-r--r-- | src/buffer.c | 10 | ||||
| -rw-r--r-- | src/buffer.h | 15 | ||||
| -rw-r--r-- | src/compat.c | 22 | ||||
| -rw-r--r-- | src/compat.h | 19 | ||||
| -rw-r--r-- | src/except.c | 62 | ||||
| -rw-r--r-- | src/except.h | 33 | ||||
| -rw-r--r-- | src/ftp.lua | 92 | ||||
| -rw-r--r-- | src/http.lua | 131 | ||||
| -rwxr-xr-x[-rw-r--r--] | src/inet.c | 20 | ||||
| -rw-r--r-- | src/inet.h | 26 | ||||
| -rw-r--r-- | src/io.c | 4 | ||||
| -rw-r--r-- | src/io.h | 13 | ||||
| -rw-r--r-- | src/ltn12.lua | 15 | ||||
| -rwxr-xr-x[-rw-r--r--] | src/luasocket.c | 12 | ||||
| -rw-r--r-- | src/luasocket.h | 15 | ||||
| -rwxr-xr-x[-rw-r--r--] | src/makefile | 174 | ||||
| -rw-r--r-- | src/mbox.lua | 15 | ||||
| -rwxr-xr-x[-rw-r--r--] | src/mime.c | 165 | ||||
| -rw-r--r-- | src/mime.h | 11 | ||||
| -rw-r--r-- | src/mime.lua | 15 | ||||
| -rw-r--r-- | src/options.c | 175 | ||||
| -rw-r--r-- | src/options.h | 110 | ||||
| -rw-r--r-- | src/select.c | 17 | ||||
| -rw-r--r-- | src/select.h | 8 | ||||
| -rw-r--r-- | src/serial.c | 7 | ||||
| -rwxr-xr-x[-rw-r--r--] | src/socket.h | 57 | ||||
| -rw-r--r-- | src/tcp.c | 55 | ||||
| -rw-r--r-- | src/tcp.h | 10 | ||||
| -rw-r--r-- | src/timeout.c | 22 | ||||
| -rw-r--r-- | src/timeout.h | 18 | ||||
| -rw-r--r-- | src/tp.lua | 12 | ||||
| -rwxr-xr-x[-rw-r--r--] | src/udp.c | 111 | ||||
| -rw-r--r-- | src/udp.h | 13 | ||||
| -rw-r--r-- | src/unix.c | 349 | ||||
| -rw-r--r-- | src/unix.h | 8 | ||||
| -rw-r--r-- | src/unixdgram.c | 405 | ||||
| -rw-r--r-- | src/unixdgram.h | 28 | ||||
| -rw-r--r-- | src/unixstream.c | 355 | ||||
| -rw-r--r-- | src/unixstream.h | 29 | ||||
| -rw-r--r-- | src/url.lua | 98 | ||||
| -rw-r--r-- | src/usocket.c | 15 | ||||
| -rwxr-xr-x[-rw-r--r--] | src/wsocket.c | 29 |
44 files changed, 2035 insertions, 795 deletions
diff --git a/src/auxiliar.c b/src/auxiliar.c index 18fa8e4..93a66a0 100644 --- a/src/auxiliar.c +++ b/src/auxiliar.c | |||
| @@ -2,14 +2,11 @@ | |||
| 2 | * Auxiliar routines for class hierarchy manipulation | 2 | * Auxiliar routines for class hierarchy manipulation |
| 3 | * LuaSocket toolkit | 3 | * LuaSocket toolkit |
| 4 | \*=========================================================================*/ | 4 | \*=========================================================================*/ |
| 5 | #include "luasocket.h" | ||
| 6 | #include "auxiliar.h" | ||
| 5 | #include <string.h> | 7 | #include <string.h> |
| 6 | #include <stdio.h> | 8 | #include <stdio.h> |
| 7 | 9 | ||
| 8 | #include "auxiliar.h" | ||
| 9 | |||
| 10 | /*=========================================================================*\ | ||
| 11 | * Exported functions | ||
| 12 | \*=========================================================================*/ | ||
| 13 | /*-------------------------------------------------------------------------*\ | 10 | /*-------------------------------------------------------------------------*\ |
| 14 | * Initializes the module | 11 | * Initializes the module |
| 15 | \*-------------------------------------------------------------------------*/ | 12 | \*-------------------------------------------------------------------------*/ |
| @@ -143,7 +140,7 @@ void *auxiliar_getgroupudata(lua_State *L, const char *groupname, int objidx) { | |||
| 143 | * otherwise | 140 | * otherwise |
| 144 | \*-------------------------------------------------------------------------*/ | 141 | \*-------------------------------------------------------------------------*/ |
| 145 | void *auxiliar_getclassudata(lua_State *L, const char *classname, int objidx) { | 142 | void *auxiliar_getclassudata(lua_State *L, const char *classname, int objidx) { |
| 146 | return luaL_checkudata(L, objidx, classname); | 143 | return luaL_testudata(L, objidx, classname); |
| 147 | } | 144 | } |
| 148 | 145 | ||
| 149 | /*-------------------------------------------------------------------------*\ | 146 | /*-------------------------------------------------------------------------*\ |
| @@ -155,4 +152,3 @@ int auxiliar_typeerror (lua_State *L, int narg, const char *tname) { | |||
| 155 | luaL_typename(L, narg)); | 152 | luaL_typename(L, narg)); |
| 156 | return luaL_argerror(L, narg, msg); | 153 | return luaL_argerror(L, narg, msg); |
| 157 | } | 154 | } |
| 158 | |||
diff --git a/src/auxiliar.h b/src/auxiliar.h index 65511d4..e8c3ead 100644 --- a/src/auxiliar.h +++ b/src/auxiliar.h | |||
| @@ -29,20 +29,26 @@ | |||
| 29 | * reverse mapping are done using lauxlib. | 29 | * reverse mapping are done using lauxlib. |
| 30 | \*=========================================================================*/ | 30 | \*=========================================================================*/ |
| 31 | 31 | ||
| 32 | #include "lua.h" | 32 | #include "luasocket.h" |
| 33 | #include "lauxlib.h" | 33 | |
| 34 | #include "compat.h" | 34 | #ifndef _WIN32 |
| 35 | #pragma GCC visibility push(hidden) | ||
| 36 | #endif | ||
| 35 | 37 | ||
| 36 | int auxiliar_open(lua_State *L); | 38 | int auxiliar_open(lua_State *L); |
| 37 | void auxiliar_newclass(lua_State *L, const char *classname, luaL_Reg *func); | 39 | void auxiliar_newclass(lua_State *L, const char *classname, luaL_Reg *func); |
| 40 | int auxiliar_tostring(lua_State *L); | ||
| 38 | void auxiliar_add2group(lua_State *L, const char *classname, const char *group); | 41 | void auxiliar_add2group(lua_State *L, const char *classname, const char *group); |
| 39 | void auxiliar_setclass(lua_State *L, const char *classname, int objidx); | 42 | int auxiliar_checkboolean(lua_State *L, int objidx); |
| 40 | void *auxiliar_checkclass(lua_State *L, const char *classname, int objidx); | 43 | void *auxiliar_checkclass(lua_State *L, const char *classname, int objidx); |
| 41 | void *auxiliar_checkgroup(lua_State *L, const char *groupname, int objidx); | 44 | void *auxiliar_checkgroup(lua_State *L, const char *groupname, int objidx); |
| 42 | void *auxiliar_getclassudata(lua_State *L, const char *groupname, int objidx); | 45 | void auxiliar_setclass(lua_State *L, const char *classname, int objidx); |
| 43 | void *auxiliar_getgroupudata(lua_State *L, const char *groupname, int objidx); | 46 | void *auxiliar_getgroupudata(lua_State *L, const char *groupname, int objidx); |
| 44 | int auxiliar_checkboolean(lua_State *L, int objidx); | 47 | void *auxiliar_getclassudata(lua_State *L, const char *groupname, int objidx); |
| 45 | int auxiliar_tostring(lua_State *L); | ||
| 46 | int auxiliar_typeerror(lua_State *L, int narg, const char *tname); | 48 | int auxiliar_typeerror(lua_State *L, int narg, const char *tname); |
| 47 | 49 | ||
| 50 | #ifndef _WIN32 | ||
| 51 | #pragma GCC visibility pop | ||
| 52 | #endif | ||
| 53 | |||
| 48 | #endif /* AUXILIAR_H */ | 54 | #endif /* AUXILIAR_H */ |
diff --git a/src/buffer.c b/src/buffer.c index fff1634..7148be3 100644 --- a/src/buffer.c +++ b/src/buffer.c | |||
| @@ -2,10 +2,7 @@ | |||
| 2 | * Input/Output interface for Lua programs | 2 | * Input/Output interface for Lua programs |
| 3 | * LuaSocket toolkit | 3 | * LuaSocket toolkit |
| 4 | \*=========================================================================*/ | 4 | \*=========================================================================*/ |
| 5 | #include "lua.h" | 5 | #include "luasocket.h" |
| 6 | #include "lauxlib.h" | ||
| 7 | #include "compat.h" | ||
| 8 | |||
| 9 | #include "buffer.h" | 6 | #include "buffer.h" |
| 10 | 7 | ||
| 11 | /*=========================================================================*\ | 8 | /*=========================================================================*\ |
| @@ -106,11 +103,14 @@ int buffer_meth_send(lua_State *L, p_buffer buf) { | |||
| 106 | * object:receive() interface | 103 | * object:receive() interface |
| 107 | \*-------------------------------------------------------------------------*/ | 104 | \*-------------------------------------------------------------------------*/ |
| 108 | int buffer_meth_receive(lua_State *L, p_buffer buf) { | 105 | int buffer_meth_receive(lua_State *L, p_buffer buf) { |
| 109 | int err = IO_DONE, top = lua_gettop(L); | 106 | int err = IO_DONE, top; |
| 110 | luaL_Buffer b; | 107 | luaL_Buffer b; |
| 111 | size_t size; | 108 | size_t size; |
| 112 | const char *part = luaL_optlstring(L, 3, "", &size); | 109 | const char *part = luaL_optlstring(L, 3, "", &size); |
| 113 | timeout_markstart(buf->tm); | 110 | timeout_markstart(buf->tm); |
| 111 | /* make sure we don't confuse buffer stuff with arguments */ | ||
| 112 | lua_settop(L, 3); | ||
| 113 | top = lua_gettop(L); | ||
| 114 | /* initialize buffer with optional extra prefix | 114 | /* initialize buffer with optional extra prefix |
| 115 | * (useful for concatenating previous partial results) */ | 115 | * (useful for concatenating previous partial results) */ |
| 116 | luaL_buffinit(L, &b); | 116 | luaL_buffinit(L, &b); |
diff --git a/src/buffer.h b/src/buffer.h index 1281bb3..a0901fc 100644 --- a/src/buffer.h +++ b/src/buffer.h | |||
| @@ -15,8 +15,7 @@ | |||
| 15 | * The module is built on top of the I/O abstraction defined in io.h and the | 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. | 16 | * timeout management is done with the timeout.h interface. |
| 17 | \*=========================================================================*/ | 17 | \*=========================================================================*/ |
| 18 | #include "lua.h" | 18 | #include "luasocket.h" |
| 19 | |||
| 20 | #include "io.h" | 19 | #include "io.h" |
| 21 | #include "timeout.h" | 20 | #include "timeout.h" |
| 22 | 21 | ||
| @@ -34,12 +33,20 @@ typedef struct t_buffer_ { | |||
| 34 | } t_buffer; | 33 | } t_buffer; |
| 35 | typedef t_buffer *p_buffer; | 34 | typedef t_buffer *p_buffer; |
| 36 | 35 | ||
| 36 | #ifndef _WIN32 | ||
| 37 | #pragma GCC visibility push(hidden) | ||
| 38 | #endif | ||
| 39 | |||
| 37 | int buffer_open(lua_State *L); | 40 | int buffer_open(lua_State *L); |
| 38 | void buffer_init(p_buffer buf, p_io io, p_timeout tm); | 41 | void buffer_init(p_buffer buf, p_io io, p_timeout tm); |
| 39 | int buffer_meth_send(lua_State *L, p_buffer buf); | ||
| 40 | int buffer_meth_receive(lua_State *L, p_buffer buf); | ||
| 41 | int buffer_meth_getstats(lua_State *L, p_buffer buf); | 42 | int buffer_meth_getstats(lua_State *L, p_buffer buf); |
| 42 | int buffer_meth_setstats(lua_State *L, p_buffer buf); | 43 | int buffer_meth_setstats(lua_State *L, p_buffer buf); |
| 44 | int buffer_meth_send(lua_State *L, p_buffer buf); | ||
| 45 | int buffer_meth_receive(lua_State *L, p_buffer buf); | ||
| 43 | int buffer_isempty(p_buffer buf); | 46 | int buffer_isempty(p_buffer buf); |
| 44 | 47 | ||
| 48 | #ifndef _WIN32 | ||
| 49 | #pragma GCC visibility pop | ||
| 50 | #endif | ||
| 51 | |||
| 45 | #endif /* BUF_H */ | 52 | #endif /* BUF_H */ |
diff --git a/src/compat.c b/src/compat.c index c2d99cb..34ffdaf 100644 --- a/src/compat.c +++ b/src/compat.c | |||
| @@ -1,10 +1,12 @@ | |||
| 1 | #include "luasocket.h" | ||
| 1 | #include "compat.h" | 2 | #include "compat.h" |
| 2 | 3 | ||
| 3 | #if LUA_VERSION_NUM==501 | 4 | #if LUA_VERSION_NUM==501 |
| 5 | |||
| 4 | /* | 6 | /* |
| 5 | ** Adapted from Lua 5.2 | 7 | ** Adapted from Lua 5.2 |
| 6 | */ | 8 | */ |
| 7 | void luaL_setfuncs (lua_State *L, const luaL_Reg *l, int nup) { | 9 | void luasocket_setfuncs (lua_State *L, const luaL_Reg *l, int nup) { |
| 8 | luaL_checkstack(L, nup+1, "too many upvalues"); | 10 | luaL_checkstack(L, nup+1, "too many upvalues"); |
| 9 | for (; l->name != NULL; l++) { /* fill the table with given functions */ | 11 | for (; l->name != NULL; l++) { /* fill the table with given functions */ |
| 10 | int i; | 12 | int i; |
| @@ -16,4 +18,22 @@ void luaL_setfuncs (lua_State *L, const luaL_Reg *l, int nup) { | |||
| 16 | } | 18 | } |
| 17 | lua_pop(L, nup); /* remove upvalues */ | 19 | lua_pop(L, nup); /* remove upvalues */ |
| 18 | } | 20 | } |
| 21 | |||
| 22 | /* | ||
| 23 | ** Duplicated from Lua 5.2 | ||
| 24 | */ | ||
| 25 | void *luasocket_testudata (lua_State *L, int ud, const char *tname) { | ||
| 26 | void *p = lua_touserdata(L, ud); | ||
| 27 | if (p != NULL) { /* value is a userdata? */ | ||
| 28 | if (lua_getmetatable(L, ud)) { /* does it have a metatable? */ | ||
| 29 | luaL_getmetatable(L, tname); /* get correct metatable */ | ||
| 30 | if (!lua_rawequal(L, -1, -2)) /* not the same? */ | ||
| 31 | p = NULL; /* value is a userdata with wrong metatable */ | ||
| 32 | lua_pop(L, 2); /* remove both metatables */ | ||
| 33 | return p; | ||
| 34 | } | ||
| 35 | } | ||
| 36 | return NULL; /* value is not a userdata with a metatable */ | ||
| 37 | } | ||
| 38 | |||
| 19 | #endif | 39 | #endif |
diff --git a/src/compat.h b/src/compat.h index 7bf8010..fa2d7d7 100644 --- a/src/compat.h +++ b/src/compat.h | |||
| @@ -1,11 +1,22 @@ | |||
| 1 | #ifndef COMPAT_H | 1 | #ifndef COMPAT_H |
| 2 | #define COMPAT_H | 2 | #define COMPAT_H |
| 3 | 3 | ||
| 4 | #include "lua.h" | ||
| 5 | #include "lauxlib.h" | ||
| 6 | |||
| 7 | #if LUA_VERSION_NUM==501 | 4 | #if LUA_VERSION_NUM==501 |
| 8 | void luaL_setfuncs (lua_State *L, const luaL_Reg *l, int nup); | 5 | |
| 6 | #ifndef _WIN32 | ||
| 7 | #pragma GCC visibility push(hidden) | ||
| 8 | #endif | ||
| 9 | |||
| 10 | void luasocket_setfuncs (lua_State *L, const luaL_Reg *l, int nup); | ||
| 11 | void *luasocket_testudata ( lua_State *L, int arg, const char *tname); | ||
| 12 | |||
| 13 | #ifndef _WIN32 | ||
| 14 | #pragma GCC visibility pop | ||
| 15 | #endif | ||
| 16 | |||
| 17 | #define luaL_setfuncs luasocket_setfuncs | ||
| 18 | #define luaL_testudata luasocket_testudata | ||
| 19 | |||
| 9 | #endif | 20 | #endif |
| 10 | 21 | ||
| 11 | #endif | 22 | #endif |
diff --git a/src/except.c b/src/except.c index 261ac98..9c3317f 100644 --- a/src/except.c +++ b/src/except.c | |||
| @@ -2,17 +2,13 @@ | |||
| 2 | * Simple exception support | 2 | * Simple exception support |
| 3 | * LuaSocket toolkit | 3 | * LuaSocket toolkit |
| 4 | \*=========================================================================*/ | 4 | \*=========================================================================*/ |
| 5 | #include <stdio.h> | 5 | #include "luasocket.h" |
| 6 | |||
| 7 | #include "lua.h" | ||
| 8 | #include "lauxlib.h" | ||
| 9 | #include "compat.h" | ||
| 10 | |||
| 11 | #include "except.h" | 6 | #include "except.h" |
| 7 | #include <stdio.h> | ||
| 12 | 8 | ||
| 13 | #if LUA_VERSION_NUM < 502 | 9 | #if LUA_VERSION_NUM < 502 |
| 14 | #define lua_pcallk(L, na, nr, err, ctx, cont) \ | 10 | #define lua_pcallk(L, na, nr, err, ctx, cont) \ |
| 15 | ((void)ctx,(void)cont,lua_pcall(L, na, nr, err)) | 11 | (((void)ctx),((void)cont),lua_pcall(L, na, nr, err)) |
| 16 | #endif | 12 | #endif |
| 17 | 13 | ||
| 18 | #if LUA_VERSION_NUM < 503 | 14 | #if LUA_VERSION_NUM < 503 |
| @@ -39,18 +35,17 @@ static luaL_Reg func[] = { | |||
| 39 | * Try factory | 35 | * Try factory |
| 40 | \*-------------------------------------------------------------------------*/ | 36 | \*-------------------------------------------------------------------------*/ |
| 41 | static void wrap(lua_State *L) { | 37 | static void wrap(lua_State *L) { |
| 42 | lua_newtable(L); | 38 | lua_createtable(L, 1, 0); |
| 43 | lua_pushnumber(L, 1); | 39 | lua_pushvalue(L, -2); |
| 44 | lua_pushvalue(L, -3); | 40 | lua_rawseti(L, -2, 1); |
| 45 | lua_settable(L, -3); | 41 | lua_pushvalue(L, lua_upvalueindex(1)); |
| 46 | lua_insert(L, -2); | 42 | lua_setmetatable(L, -2); |
| 47 | lua_pop(L, 1); | ||
| 48 | } | 43 | } |
| 49 | 44 | ||
| 50 | static int finalize(lua_State *L) { | 45 | static int finalize(lua_State *L) { |
| 51 | if (!lua_toboolean(L, 1)) { | 46 | if (!lua_toboolean(L, 1)) { |
| 52 | lua_pushvalue(L, lua_upvalueindex(1)); | 47 | lua_pushvalue(L, lua_upvalueindex(2)); |
| 53 | lua_pcall(L, 0, 0, 0); | 48 | lua_call(L, 0, 0); |
| 54 | lua_settop(L, 2); | 49 | lua_settop(L, 2); |
| 55 | wrap(L); | 50 | wrap(L); |
| 56 | lua_error(L); | 51 | lua_error(L); |
| @@ -58,15 +53,17 @@ static int finalize(lua_State *L) { | |||
| 58 | } else return lua_gettop(L); | 53 | } else return lua_gettop(L); |
| 59 | } | 54 | } |
| 60 | 55 | ||
| 61 | static int do_nothing(lua_State *L) { | 56 | static int do_nothing(lua_State *L) { |
| 62 | (void) L; | 57 | (void) L; |
| 63 | return 0; | 58 | return 0; |
| 64 | } | 59 | } |
| 65 | 60 | ||
| 66 | static int global_newtry(lua_State *L) { | 61 | static int global_newtry(lua_State *L) { |
| 67 | lua_settop(L, 1); | 62 | lua_settop(L, 1); |
| 68 | if (lua_isnil(L, 1)) lua_pushcfunction(L, do_nothing); | 63 | if (lua_isnil(L, 1)) lua_pushcfunction(L, do_nothing); |
| 69 | lua_pushcclosure(L, finalize, 1); | 64 | lua_pushvalue(L, lua_upvalueindex(1)); |
| 65 | lua_insert(L, -2); | ||
| 66 | lua_pushcclosure(L, finalize, 2); | ||
| 70 | return 1; | 67 | return 1; |
| 71 | } | 68 | } |
| 72 | 69 | ||
| @@ -74,13 +71,16 @@ static int global_newtry(lua_State *L) { | |||
| 74 | * Protect factory | 71 | * Protect factory |
| 75 | \*-------------------------------------------------------------------------*/ | 72 | \*-------------------------------------------------------------------------*/ |
| 76 | static int unwrap(lua_State *L) { | 73 | static int unwrap(lua_State *L) { |
| 77 | if (lua_istable(L, -1)) { | 74 | if (lua_istable(L, -1) && lua_getmetatable(L, -1)) { |
| 78 | lua_pushnumber(L, 1); | 75 | int r = lua_rawequal(L, -1, lua_upvalueindex(1)); |
| 79 | lua_gettable(L, -2); | 76 | lua_pop(L, 1); |
| 80 | lua_pushnil(L); | 77 | if (r) { |
| 81 | lua_insert(L, -2); | 78 | lua_pushnil(L); |
| 82 | return 1; | 79 | lua_rawgeti(L, -2, 1); |
| 83 | } else return 0; | 80 | return 1; |
| 81 | } | ||
| 82 | } | ||
| 83 | return 0; | ||
| 84 | } | 84 | } |
| 85 | 85 | ||
| 86 | static int protected_finish(lua_State *L, int status, lua_KContext ctx) { | 86 | static int protected_finish(lua_State *L, int status, lua_KContext ctx) { |
| @@ -103,14 +103,17 @@ static int protected_cont(lua_State *L) { | |||
| 103 | 103 | ||
| 104 | static int protected_(lua_State *L) { | 104 | static int protected_(lua_State *L) { |
| 105 | int status; | 105 | int status; |
| 106 | lua_pushvalue(L, lua_upvalueindex(1)); | 106 | lua_pushvalue(L, lua_upvalueindex(2)); |
| 107 | lua_insert(L, 1); | 107 | lua_insert(L, 1); |
| 108 | status = lua_pcallk(L, lua_gettop(L) - 1, LUA_MULTRET, 0, 0, protected_cont); | 108 | status = lua_pcallk(L, lua_gettop(L) - 1, LUA_MULTRET, 0, 0, protected_cont); |
| 109 | return protected_finish(L, status, 0); | 109 | return protected_finish(L, status, 0); |
| 110 | } | 110 | } |
| 111 | 111 | ||
| 112 | static int global_protect(lua_State *L) { | 112 | static int global_protect(lua_State *L) { |
| 113 | lua_pushcclosure(L, protected_, 1); | 113 | lua_settop(L, 1); |
| 114 | lua_pushvalue(L, lua_upvalueindex(1)); | ||
| 115 | lua_insert(L, 1); | ||
| 116 | lua_pushcclosure(L, protected_, 2); | ||
| 114 | return 1; | 117 | return 1; |
| 115 | } | 118 | } |
| 116 | 119 | ||
| @@ -118,6 +121,9 @@ static int global_protect(lua_State *L) { | |||
| 118 | * Init module | 121 | * Init module |
| 119 | \*-------------------------------------------------------------------------*/ | 122 | \*-------------------------------------------------------------------------*/ |
| 120 | int except_open(lua_State *L) { | 123 | int except_open(lua_State *L) { |
| 121 | luaL_setfuncs(L, func, 0); | 124 | lua_newtable(L); /* metatable for wrapped exceptions */ |
| 125 | lua_pushboolean(L, 0); | ||
| 126 | lua_setfield(L, -2, "__metatable"); | ||
| 127 | luaL_setfuncs(L, func, 1); | ||
| 122 | return 0; | 128 | return 0; |
| 123 | } | 129 | } |
diff --git a/src/except.h b/src/except.h index 1e7a245..71c31fd 100644 --- a/src/except.h +++ b/src/except.h | |||
| @@ -9,25 +9,38 @@ | |||
| 9 | * error checking was taking a substantial amount of the coding. These | 9 | * error checking was taking a substantial amount of the coding. These |
| 10 | * function greatly simplify the task of checking errors. | 10 | * function greatly simplify the task of checking errors. |
| 11 | * | 11 | * |
| 12 | * The main idea is that functions should return nil as its first return | 12 | * The main idea is that functions should return nil as their first return |
| 13 | * value when it finds an error, and return an error message (or value) | 13 | * values when they find an error, and return an error message (or value) |
| 14 | * following nil. In case of success, as long as the first value is not nil, | 14 | * following nil. In case of success, as long as the first value is not nil, |
| 15 | * the other values don't matter. | 15 | * the other values don't matter. |
| 16 | * | 16 | * |
| 17 | * The idea is to nest function calls with the "try" function. This function | 17 | * The idea is to nest function calls with the "try" function. This function |
| 18 | * checks the first value, and calls "error" on the second if the first is | 18 | * checks the first value, and, if it's falsy, wraps the second value in a |
| 19 | * nil. Otherwise, it returns all values it received. | 19 | * table with metatable and calls "error" on it. Otherwise, it returns all |
| 20 | * values it received. Basically, it works like the Lua "assert" function, | ||
| 21 | * but it creates errors targeted specifically at "protect". | ||
| 20 | * | 22 | * |
| 21 | * The protect function returns a new function that behaves exactly like the | 23 | * The "newtry" function is a factory for "try" functions that call a |
| 22 | * function it receives, but the new function doesn't throw exceptions: it | 24 | * finalizer in protected mode before calling "error". |
| 23 | * returns nil followed by the error message instead. | ||
| 24 | * | 25 | * |
| 25 | * With these two function, it's easy to write functions that throw | 26 | * The "protect" function returns a new function that behaves exactly like |
| 26 | * exceptions on error, but that don't interrupt the user script. | 27 | * the function it receives, but the new function catches exceptions thrown |
| 28 | * by "try" functions and returns nil followed by the error message instead. | ||
| 29 | * | ||
| 30 | * With these three functions, it's easy to write functions that throw | ||
| 31 | * exceptions on error, but that don't interrupt the user script. | ||
| 27 | \*=========================================================================*/ | 32 | \*=========================================================================*/ |
| 28 | 33 | ||
| 29 | #include "lua.h" | 34 | #include "luasocket.h" |
| 35 | |||
| 36 | #ifndef _WIN32 | ||
| 37 | #pragma GCC visibility push(hidden) | ||
| 38 | #endif | ||
| 30 | 39 | ||
| 31 | int except_open(lua_State *L); | 40 | int except_open(lua_State *L); |
| 32 | 41 | ||
| 42 | #ifndef _WIN32 | ||
| 43 | #pragma GCC visibility pop | ||
| 44 | #endif | ||
| 45 | |||
| 33 | #endif | 46 | #endif |
diff --git a/src/ftp.lua b/src/ftp.lua index 917cd89..0ebc508 100644 --- a/src/ftp.lua +++ b/src/ftp.lua | |||
| @@ -23,7 +23,7 @@ local _M = socket.ftp | |||
| 23 | -- timeout in seconds before the program gives up on a connection | 23 | -- timeout in seconds before the program gives up on a connection |
| 24 | _M.TIMEOUT = 60 | 24 | _M.TIMEOUT = 60 |
| 25 | -- default port for ftp service | 25 | -- default port for ftp service |
| 26 | _M.PORT = 21 | 26 | local PORT = 21 |
| 27 | -- this is the default anonymous password. used when no password is | 27 | -- this is the default anonymous password. used when no password is |
| 28 | -- provided in url. should be changed to your e-mail. | 28 | -- provided in url. should be changed to your e-mail. |
| 29 | _M.USER = "ftp" | 29 | _M.USER = "ftp" |
| @@ -35,7 +35,7 @@ _M.PASSWORD = "anonymous@anonymous.org" | |||
| 35 | local metat = { __index = {} } | 35 | local metat = { __index = {} } |
| 36 | 36 | ||
| 37 | function _M.open(server, port, create) | 37 | function _M.open(server, port, create) |
| 38 | local tp = socket.try(tp.connect(server, port or _M.PORT, _M.TIMEOUT, create)) | 38 | local tp = socket.try(tp.connect(server, port or PORT, _M.TIMEOUT, create)) |
| 39 | local f = base.setmetatable({ tp = tp }, metat) | 39 | local f = base.setmetatable({ tp = tp }, metat) |
| 40 | -- make sure everything gets closed in an exception | 40 | -- make sure everything gets closed in an exception |
| 41 | f.try = socket.newtry(function() f:close() end) | 41 | f.try = socket.newtry(function() f:close() end) |
| @@ -51,12 +51,12 @@ end | |||
| 51 | function metat.__index:pasvconnect() | 51 | function metat.__index:pasvconnect() |
| 52 | self.data = self.try(socket.tcp()) | 52 | self.data = self.try(socket.tcp()) |
| 53 | self.try(self.data:settimeout(_M.TIMEOUT)) | 53 | self.try(self.data:settimeout(_M.TIMEOUT)) |
| 54 | self.try(self.data:connect(self.pasvt.ip, self.pasvt.port)) | 54 | self.try(self.data:connect(self.pasvt.address, self.pasvt.port)) |
| 55 | end | 55 | end |
| 56 | 56 | ||
| 57 | function metat.__index:login(user, password) | 57 | function metat.__index:login(user, password) |
| 58 | self.try(self.tp:command("user", user or _M.USER)) | 58 | self.try(self.tp:command("user", user or _M.USER)) |
| 59 | local code, reply = self.try(self.tp:check{"2..", 331}) | 59 | local code, _ = self.try(self.tp:check{"2..", 331}) |
| 60 | if code == 331 then | 60 | if code == 331 then |
| 61 | self.try(self.tp:command("pass", password or _M.PASSWORD)) | 61 | self.try(self.tp:command("pass", password or _M.PASSWORD)) |
| 62 | self.try(self.tp:check("2..")) | 62 | self.try(self.tp:check("2..")) |
| @@ -66,37 +66,70 @@ end | |||
| 66 | 66 | ||
| 67 | function metat.__index:pasv() | 67 | function metat.__index:pasv() |
| 68 | self.try(self.tp:command("pasv")) | 68 | self.try(self.tp:command("pasv")) |
| 69 | local code, reply = self.try(self.tp:check("2..")) | 69 | local _, reply = self.try(self.tp:check("2..")) |
| 70 | local pattern = "(%d+)%D(%d+)%D(%d+)%D(%d+)%D(%d+)%D(%d+)" | 70 | local pattern = "(%d+)%D(%d+)%D(%d+)%D(%d+)%D(%d+)%D(%d+)" |
| 71 | local a, b, c, d, p1, p2 = socket.skip(2, string.find(reply, pattern)) | 71 | local a, b, c, d, p1, p2 = socket.skip(2, string.find(reply, pattern)) |
| 72 | self.try(a and b and c and d and p1 and p2, reply) | 72 | self.try(a and b and c and d and p1 and p2, reply) |
| 73 | self.pasvt = { | 73 | self.pasvt = { |
| 74 | ip = string.format("%d.%d.%d.%d", a, b, c, d), | 74 | address = string.format("%d.%d.%d.%d", a, b, c, d), |
| 75 | port = p1*256 + p2 | 75 | port = p1*256 + p2 |
| 76 | } | 76 | } |
| 77 | if self.server then | 77 | if self.server then |
| 78 | self.server:close() | 78 | self.server:close() |
| 79 | self.server = nil | 79 | self.server = nil |
| 80 | end | 80 | end |
| 81 | return self.pasvt.ip, self.pasvt.port | 81 | return self.pasvt.address, self.pasvt.port |
| 82 | end | 82 | end |
| 83 | 83 | ||
| 84 | function metat.__index:port(ip, port) | 84 | function metat.__index:epsv() |
| 85 | self.try(self.tp:command("epsv")) | ||
| 86 | local _, reply = self.try(self.tp:check("229")) | ||
| 87 | local pattern = "%((.)(.-)%1(.-)%1(.-)%1%)" | ||
| 88 | local _, _, _, port = string.match(reply, pattern) | ||
| 89 | self.try(port, "invalid epsv response") | ||
| 90 | self.pasvt = { | ||
| 91 | address = self.tp:getpeername(), | ||
| 92 | port = port | ||
| 93 | } | ||
| 94 | if self.server then | ||
| 95 | self.server:close() | ||
| 96 | self.server = nil | ||
| 97 | end | ||
| 98 | return self.pasvt.address, self.pasvt.port | ||
| 99 | end | ||
| 100 | |||
| 101 | |||
| 102 | function metat.__index:port(address, port) | ||
| 85 | self.pasvt = nil | 103 | self.pasvt = nil |
| 86 | if not ip then | 104 | if not address then |
| 87 | ip, port = self.try(self.tp:getcontrol():getsockname()) | 105 | address = self.try(self.tp:getsockname()) |
| 88 | self.server = self.try(socket.bind(ip, 0)) | 106 | self.server = self.try(socket.bind(address, 0)) |
| 89 | ip, port = self.try(self.server:getsockname()) | 107 | address, port = self.try(self.server:getsockname()) |
| 90 | self.try(self.server:settimeout(_M.TIMEOUT)) | 108 | self.try(self.server:settimeout(_M.TIMEOUT)) |
| 91 | end | 109 | end |
| 92 | local pl = math.mod(port, 256) | 110 | local pl = math.mod(port, 256) |
| 93 | local ph = (port - pl)/256 | 111 | local ph = (port - pl)/256 |
| 94 | local arg = string.gsub(string.format("%s,%d,%d", ip, ph, pl), "%.", ",") | 112 | local arg = string.gsub(string.format("%s,%d,%d", address, ph, pl), "%.", ",") |
| 95 | self.try(self.tp:command("port", arg)) | 113 | self.try(self.tp:command("port", arg)) |
| 96 | self.try(self.tp:check("2..")) | 114 | self.try(self.tp:check("2..")) |
| 97 | return 1 | 115 | return 1 |
| 98 | end | 116 | end |
| 99 | 117 | ||
| 118 | function metat.__index:eprt(family, address, port) | ||
| 119 | self.pasvt = nil | ||
| 120 | if not address then | ||
| 121 | address = self.try(self.tp:getsockname()) | ||
| 122 | self.server = self.try(socket.bind(address, 0)) | ||
| 123 | address, port = self.try(self.server:getsockname()) | ||
| 124 | self.try(self.server:settimeout(_M.TIMEOUT)) | ||
| 125 | end | ||
| 126 | local arg = string.format("|%s|%s|%d|", family, address, port) | ||
| 127 | self.try(self.tp:command("eprt", arg)) | ||
| 128 | self.try(self.tp:check("2..")) | ||
| 129 | return 1 | ||
| 130 | end | ||
| 131 | |||
| 132 | |||
| 100 | function metat.__index:send(sendt) | 133 | function metat.__index:send(sendt) |
| 101 | self.try(self.pasvt or self.server, "need port or pasv first") | 134 | self.try(self.pasvt or self.server, "need port or pasv first") |
| 102 | -- if there is a pasvt table, we already sent a PASV command | 135 | -- if there is a pasvt table, we already sent a PASV command |
| @@ -109,13 +142,13 @@ function metat.__index:send(sendt) | |||
| 109 | local command = sendt.command or "stor" | 142 | local command = sendt.command or "stor" |
| 110 | -- send the transfer command and check the reply | 143 | -- send the transfer command and check the reply |
| 111 | self.try(self.tp:command(command, argument)) | 144 | self.try(self.tp:command(command, argument)) |
| 112 | local code, reply = self.try(self.tp:check{"2..", "1.."}) | 145 | local code, _ = self.try(self.tp:check{"2..", "1.."}) |
| 113 | -- if there is not a a pasvt table, then there is a server | 146 | -- if there is not a pasvt table, then there is a server |
| 114 | -- and we already sent a PORT command | 147 | -- and we already sent a PORT command |
| 115 | if not self.pasvt then self:portconnect() end | 148 | if not self.pasvt then self:portconnect() end |
| 116 | -- get the sink, source and step for the transfer | 149 | -- get the sink, source and step for the transfer |
| 117 | local step = sendt.step or ltn12.pump.step | 150 | local step = sendt.step or ltn12.pump.step |
| 118 | local readt = {self.tp.c} | 151 | local readt = { self.tp } |
| 119 | local checkstep = function(src, snk) | 152 | local checkstep = function(src, snk) |
| 120 | -- check status in control connection while downloading | 153 | -- check status in control connection while downloading |
| 121 | local readyt = socket.select(readt, nil, 0) | 154 | local readyt = socket.select(readt, nil, 0) |
| @@ -207,7 +240,7 @@ local function tput(putt) | |||
| 207 | f:greet() | 240 | f:greet() |
| 208 | f:login(putt.user, putt.password) | 241 | f:login(putt.user, putt.password) |
| 209 | if putt.type then f:type(putt.type) end | 242 | if putt.type then f:type(putt.type) end |
| 210 | f:pasv() | 243 | f:epsv() |
| 211 | local sent = f:send(putt) | 244 | local sent = f:send(putt) |
| 212 | f:quit() | 245 | f:quit() |
| 213 | f:close() | 246 | f:close() |
| @@ -219,7 +252,7 @@ local default = { | |||
| 219 | scheme = "ftp" | 252 | scheme = "ftp" |
| 220 | } | 253 | } |
| 221 | 254 | ||
| 222 | local function parse(u) | 255 | local function genericform(u) |
| 223 | local t = socket.try(url.parse(u, default)) | 256 | local t = socket.try(url.parse(u, default)) |
| 224 | socket.try(t.scheme == "ftp", "wrong scheme '" .. t.scheme .. "'") | 257 | socket.try(t.scheme == "ftp", "wrong scheme '" .. t.scheme .. "'") |
| 225 | socket.try(t.host, "missing hostname") | 258 | socket.try(t.host, "missing hostname") |
| @@ -232,8 +265,10 @@ local function parse(u) | |||
| 232 | return t | 265 | return t |
| 233 | end | 266 | end |
| 234 | 267 | ||
| 268 | _M.genericform = genericform | ||
| 269 | |||
| 235 | local function sput(u, body) | 270 | local function sput(u, body) |
| 236 | local putt = parse(u) | 271 | local putt = genericform(u) |
| 237 | putt.source = ltn12.source.string(body) | 272 | putt.source = ltn12.source.string(body) |
| 238 | return tput(putt) | 273 | return tput(putt) |
| 239 | end | 274 | end |
| @@ -250,14 +285,14 @@ local function tget(gett) | |||
| 250 | f:greet() | 285 | f:greet() |
| 251 | f:login(gett.user, gett.password) | 286 | f:login(gett.user, gett.password) |
| 252 | if gett.type then f:type(gett.type) end | 287 | if gett.type then f:type(gett.type) end |
| 253 | f:pasv() | 288 | f:epsv() |
| 254 | f:receive(gett) | 289 | f:receive(gett) |
| 255 | f:quit() | 290 | f:quit() |
| 256 | return f:close() | 291 | return f:close() |
| 257 | end | 292 | end |
| 258 | 293 | ||
| 259 | local function sget(u) | 294 | local function sget(u) |
| 260 | local gett = parse(u) | 295 | local gett = genericform(u) |
| 261 | local t = {} | 296 | local t = {} |
| 262 | gett.sink = ltn12.sink.table(t) | 297 | gett.sink = ltn12.sink.table(t) |
| 263 | tget(gett) | 298 | tget(gett) |
| @@ -271,8 +306,17 @@ _M.command = socket.protect(function(cmdt) | |||
| 271 | local f = _M.open(cmdt.host, cmdt.port, cmdt.create) | 306 | local f = _M.open(cmdt.host, cmdt.port, cmdt.create) |
| 272 | f:greet() | 307 | f:greet() |
| 273 | f:login(cmdt.user, cmdt.password) | 308 | f:login(cmdt.user, cmdt.password) |
| 274 | f.try(f.tp:command(cmdt.command, cmdt.argument)) | 309 | if type(cmdt.command) == "table" then |
| 275 | if cmdt.check then f.try(f.tp:check(cmdt.check)) end | 310 | local argument = cmdt.argument or {} |
| 311 | local check = cmdt.check or {} | ||
| 312 | for i,cmd in ipairs(cmdt.command) do | ||
| 313 | f.try(f.tp:command(cmd, argument[i])) | ||
| 314 | if check[i] then f.try(f.tp:check(check[i])) end | ||
| 315 | end | ||
| 316 | else | ||
| 317 | f.try(f.tp:command(cmdt.command, cmdt.argument)) | ||
| 318 | if cmdt.check then f.try(f.tp:check(cmdt.check)) end | ||
| 319 | end | ||
| 276 | f:quit() | 320 | f:quit() |
| 277 | return f:close() | 321 | return f:close() |
| 278 | end) | 322 | end) |
| @@ -282,4 +326,4 @@ _M.get = socket.protect(function(gett) | |||
| 282 | else return tget(gett) end | 326 | else return tget(gett) end |
| 283 | end) | 327 | end) |
| 284 | 328 | ||
| 285 | return _M \ No newline at end of file | 329 | return _M |
diff --git a/src/http.lua b/src/http.lua index 45ffa15..fbd5ff6 100644 --- a/src/http.lua +++ b/src/http.lua | |||
| @@ -23,11 +23,24 @@ local _M = socket.http | |||
| 23 | ----------------------------------------------------------------------------- | 23 | ----------------------------------------------------------------------------- |
| 24 | -- connection timeout in seconds | 24 | -- connection timeout in seconds |
| 25 | _M.TIMEOUT = 60 | 25 | _M.TIMEOUT = 60 |
| 26 | -- default port for document retrieval | ||
| 27 | _M.PORT = 80 | ||
| 28 | -- user agent field sent in request | 26 | -- user agent field sent in request |
| 29 | _M.USERAGENT = socket._VERSION | 27 | _M.USERAGENT = socket._VERSION |
| 30 | 28 | ||
| 29 | -- supported schemes and their particulars | ||
| 30 | local SCHEMES = { | ||
| 31 | http = { | ||
| 32 | port = 80 | ||
| 33 | , create = function(t) | ||
| 34 | return socket.tcp end } | ||
| 35 | , https = { | ||
| 36 | port = 443 | ||
| 37 | , create = function(t) | ||
| 38 | local https = assert( | ||
| 39 | require("ssl.https"), 'LuaSocket: LuaSec not found') | ||
| 40 | local tcp = assert( | ||
| 41 | https.tcp, 'LuaSocket: Function tcp() not available from LuaSec') | ||
| 42 | return tcp(t) end }} | ||
| 43 | |||
| 31 | ----------------------------------------------------------------------------- | 44 | ----------------------------------------------------------------------------- |
| 32 | -- Reads MIME headers from a connection, unfolding where needed | 45 | -- Reads MIME headers from a connection, unfolding where needed |
| 33 | ----------------------------------------------------------------------------- | 46 | ----------------------------------------------------------------------------- |
| @@ -76,7 +89,7 @@ socket.sourcet["http-chunked"] = function(sock, headers) | |||
| 76 | -- was it the last chunk? | 89 | -- was it the last chunk? |
| 77 | if size > 0 then | 90 | if size > 0 then |
| 78 | -- if not, get chunk and skip terminating CRLF | 91 | -- if not, get chunk and skip terminating CRLF |
| 79 | local chunk, err, part = sock:receive(size) | 92 | local chunk, err, _ = sock:receive(size) |
| 80 | if chunk then sock:receive() end | 93 | if chunk then sock:receive() end |
| 81 | return chunk, err | 94 | return chunk, err |
| 82 | else | 95 | else |
| @@ -108,13 +121,13 @@ local metat = { __index = {} } | |||
| 108 | 121 | ||
| 109 | function _M.open(host, port, create) | 122 | function _M.open(host, port, create) |
| 110 | -- create socket with user connect function, or with default | 123 | -- create socket with user connect function, or with default |
| 111 | local c = socket.try((create or socket.tcp)()) | 124 | local c = socket.try(create()) |
| 112 | local h = base.setmetatable({ c = c }, metat) | 125 | local h = base.setmetatable({ c = c }, metat) |
| 113 | -- create finalized try | 126 | -- create finalized try |
| 114 | h.try = socket.newtry(function() h:close() end) | 127 | h.try = socket.newtry(function() h:close() end) |
| 115 | -- set timeout before connecting | 128 | -- set timeout before connecting |
| 116 | h.try(c:settimeout(_M.TIMEOUT)) | 129 | h.try(c:settimeout(_M.TIMEOUT)) |
| 117 | h.try(c:connect(host, port or _M.PORT)) | 130 | h.try(c:connect(host, port)) |
| 118 | -- here everything worked | 131 | -- here everything worked |
| 119 | return h | 132 | return h |
| 120 | end | 133 | end |
| @@ -144,10 +157,15 @@ function metat.__index:sendbody(headers, source, step) | |||
| 144 | end | 157 | end |
| 145 | 158 | ||
| 146 | function metat.__index:receivestatusline() | 159 | function metat.__index:receivestatusline() |
| 147 | local status = self.try(self.c:receive(5)) | 160 | local status,ec = self.try(self.c:receive(5)) |
| 148 | -- identify HTTP/0.9 responses, which do not contain a status line | 161 | -- identify HTTP/0.9 responses, which do not contain a status line |
| 149 | -- this is just a heuristic, but is what the RFC recommends | 162 | -- this is just a heuristic, but is what the RFC recommends |
| 150 | if status ~= "HTTP/" then return nil, status end | 163 | if status ~= "HTTP/" then |
| 164 | if ec == "timeout" then | ||
| 165 | return 408 | ||
| 166 | end | ||
| 167 | return nil, status | ||
| 168 | end | ||
| 151 | -- otherwise proceed reading a status line | 169 | -- otherwise proceed reading a status line |
| 152 | status = self.try(self.c:receive("*l", status)) | 170 | status = self.try(self.c:receive("*l", status)) |
| 153 | local code = socket.skip(2, string.find(status, "HTTP/%d*%.%d* (%d%d%d)")) | 171 | local code = socket.skip(2, string.find(status, "HTTP/%d*%.%d* (%d%d%d)")) |
| @@ -209,7 +227,10 @@ end | |||
| 209 | 227 | ||
| 210 | local function adjustheaders(reqt) | 228 | local function adjustheaders(reqt) |
| 211 | -- default headers | 229 | -- default headers |
| 212 | local host = string.gsub(reqt.authority, "^.-@", "") | 230 | local host = reqt.host |
| 231 | local port = tostring(reqt.port) | ||
| 232 | if port ~= tostring(SCHEMES[reqt.scheme].port) then | ||
| 233 | host = host .. ':' .. port end | ||
| 213 | local lower = { | 234 | local lower = { |
| 214 | ["user-agent"] = _M.USERAGENT, | 235 | ["user-agent"] = _M.USERAGENT, |
| 215 | ["host"] = host, | 236 | ["host"] = host, |
| @@ -218,15 +239,16 @@ local function adjustheaders(reqt) | |||
| 218 | } | 239 | } |
| 219 | -- if we have authentication information, pass it along | 240 | -- if we have authentication information, pass it along |
| 220 | if reqt.user and reqt.password then | 241 | if reqt.user and reqt.password then |
| 221 | lower["authorization"] = | 242 | lower["authorization"] = |
| 222 | "Basic " .. (mime.b64(reqt.user .. ":" .. reqt.password)) | 243 | "Basic " .. (mime.b64(reqt.user .. ":" .. |
| 244 | url.unescape(reqt.password))) | ||
| 223 | end | 245 | end |
| 224 | -- if we have proxy authentication information, pass it along | 246 | -- if we have proxy authentication information, pass it along |
| 225 | local proxy = reqt.proxy or _M.PROXY | 247 | local proxy = reqt.proxy or _M.PROXY |
| 226 | if proxy then | 248 | if proxy then |
| 227 | proxy = url.parse(proxy) | 249 | proxy = url.parse(proxy) |
| 228 | if proxy.user and proxy.password then | 250 | if proxy.user and proxy.password then |
| 229 | lower["proxy-authorization"] = | 251 | lower["proxy-authorization"] = |
| 230 | "Basic " .. (mime.b64(proxy.user .. ":" .. proxy.password)) | 252 | "Basic " .. (mime.b64(proxy.user .. ":" .. proxy.password)) |
| 231 | end | 253 | end |
| 232 | end | 254 | end |
| @@ -239,10 +261,8 @@ end | |||
| 239 | 261 | ||
| 240 | -- default url parts | 262 | -- default url parts |
| 241 | local default = { | 263 | local default = { |
| 242 | host = "", | 264 | path ="/" |
| 243 | port = _M.PORT, | 265 | , scheme = "http" |
| 244 | path ="/", | ||
| 245 | scheme = "http" | ||
| 246 | } | 266 | } |
| 247 | 267 | ||
| 248 | local function adjustrequest(reqt) | 268 | local function adjustrequest(reqt) |
| @@ -250,25 +270,48 @@ local function adjustrequest(reqt) | |||
| 250 | local nreqt = reqt.url and url.parse(reqt.url, default) or {} | 270 | local nreqt = reqt.url and url.parse(reqt.url, default) or {} |
| 251 | -- explicit components override url | 271 | -- explicit components override url |
| 252 | for i,v in base.pairs(reqt) do nreqt[i] = v end | 272 | for i,v in base.pairs(reqt) do nreqt[i] = v end |
| 253 | if nreqt.port == "" then nreqt.port = 80 end | 273 | -- default to scheme particulars |
| 254 | socket.try(nreqt.host and nreqt.host ~= "", | 274 | local schemedefs, host, port, method |
| 255 | "invalid host '" .. base.tostring(nreqt.host) .. "'") | 275 | = SCHEMES[nreqt.scheme], nreqt.host, nreqt.port, nreqt.method |
| 276 | if not nreqt.create then nreqt.create = schemedefs.create(nreqt) end | ||
| 277 | if not (port and port ~= '') then nreqt.port = schemedefs.port end | ||
| 278 | if not (method and method ~= '') then nreqt.method = 'GET' end | ||
| 279 | if not (host and host ~= "") then | ||
| 280 | socket.try(nil, "invalid host '" .. base.tostring(nreqt.host) .. "'") | ||
| 281 | end | ||
| 256 | -- compute uri if user hasn't overriden | 282 | -- compute uri if user hasn't overriden |
| 257 | nreqt.uri = reqt.uri or adjusturi(nreqt) | 283 | nreqt.uri = reqt.uri or adjusturi(nreqt) |
| 258 | -- adjust headers in request | 284 | -- adjust headers in request |
| 259 | nreqt.headers = adjustheaders(nreqt) | 285 | nreqt.headers = adjustheaders(nreqt) |
| 286 | if nreqt.source | ||
| 287 | and not nreqt.headers["content-length"] | ||
| 288 | and not nreqt.headers["transfer-encoding"] | ||
| 289 | then | ||
| 290 | nreqt.headers["transfer-encoding"] = "chunked" | ||
| 291 | end | ||
| 292 | |||
| 260 | -- ajust host and port if there is a proxy | 293 | -- ajust host and port if there is a proxy |
| 261 | nreqt.host, nreqt.port = adjustproxy(nreqt) | 294 | nreqt.host, nreqt.port = adjustproxy(nreqt) |
| 262 | return nreqt | 295 | return nreqt |
| 263 | end | 296 | end |
| 264 | 297 | ||
| 265 | local function shouldredirect(reqt, code, headers) | 298 | local function shouldredirect(reqt, code, headers) |
| 266 | return headers.location and | 299 | local location = headers.location |
| 267 | string.gsub(headers.location, "%s", "") ~= "" and | 300 | if not location then return false end |
| 268 | (reqt.redirect ~= false) and | 301 | location = string.gsub(location, "%s", "") |
| 302 | if location == "" then return false end | ||
| 303 | -- the RFC says the redirect URL may be relative | ||
| 304 | location = url.absolute(reqt.url, location) | ||
| 305 | local scheme = url.parse(location).scheme | ||
| 306 | if scheme and (not SCHEMES[scheme]) then return false end | ||
| 307 | -- avoid https downgrades | ||
| 308 | if ('https' == reqt.scheme) and ('https' ~= scheme) then return false end | ||
| 309 | return (reqt.redirect ~= false) and | ||
| 269 | (code == 301 or code == 302 or code == 303 or code == 307) and | 310 | (code == 301 or code == 302 or code == 303 or code == 307) and |
| 270 | (not reqt.method or reqt.method == "GET" or reqt.method == "HEAD") | 311 | (not reqt.method or reqt.method == "GET" or reqt.method == "HEAD") |
| 271 | and (not reqt.nredirects or reqt.nredirects < 5) | 312 | and ((false == reqt.maxredirects) |
| 313 | or ((reqt.nredirects or 0) | ||
| 314 | < (reqt.maxredirects or 5))) | ||
| 272 | end | 315 | end |
| 273 | 316 | ||
| 274 | local function shouldreceivebody(reqt, code) | 317 | local function shouldreceivebody(reqt, code) |
| @@ -282,17 +325,23 @@ end | |||
| 282 | local trequest, tredirect | 325 | local trequest, tredirect |
| 283 | 326 | ||
| 284 | --[[local]] function tredirect(reqt, location) | 327 | --[[local]] function tredirect(reqt, location) |
| 328 | -- the RFC says the redirect URL may be relative | ||
| 329 | local newurl = url.absolute(reqt.url, location) | ||
| 330 | -- if switching schemes, reset port and create function | ||
| 331 | if url.parse(newurl).scheme ~= reqt.scheme then | ||
| 332 | reqt.port = nil | ||
| 333 | reqt.create = nil end | ||
| 334 | -- make new request | ||
| 285 | local result, code, headers, status = trequest { | 335 | local result, code, headers, status = trequest { |
| 286 | -- the RFC says the redirect URL has to be absolute, but some | 336 | url = newurl, |
| 287 | -- servers do not respect that | ||
| 288 | url = url.absolute(reqt.url, location), | ||
| 289 | source = reqt.source, | 337 | source = reqt.source, |
| 290 | sink = reqt.sink, | 338 | sink = reqt.sink, |
| 291 | headers = reqt.headers, | 339 | headers = reqt.headers, |
| 292 | proxy = reqt.proxy, | 340 | proxy = reqt.proxy, |
| 341 | maxredirects = reqt.maxredirects, | ||
| 293 | nredirects = (reqt.nredirects or 0) + 1, | 342 | nredirects = (reqt.nredirects or 0) + 1, |
| 294 | create = reqt.create | 343 | create = reqt.create |
| 295 | } | 344 | } |
| 296 | -- pass location header back as a hint we redirected | 345 | -- pass location header back as a hint we redirected |
| 297 | headers = headers or {} | 346 | headers = headers or {} |
| 298 | headers.location = headers.location or location | 347 | headers.location = headers.location or location |
| @@ -309,23 +358,25 @@ end | |||
| 309 | h:sendheaders(nreqt.headers) | 358 | h:sendheaders(nreqt.headers) |
| 310 | -- if there is a body, send it | 359 | -- if there is a body, send it |
| 311 | if nreqt.source then | 360 | if nreqt.source then |
| 312 | h:sendbody(nreqt.headers, nreqt.source, nreqt.step) | 361 | h:sendbody(nreqt.headers, nreqt.source, nreqt.step) |
| 313 | end | 362 | end |
| 314 | local code, status = h:receivestatusline() | 363 | local code, status = h:receivestatusline() |
| 315 | -- if it is an HTTP/0.9 server, simply get the body and we are done | 364 | -- if it is an HTTP/0.9 server, simply get the body and we are done |
| 316 | if not code then | 365 | if not code then |
| 317 | h:receive09body(status, nreqt.sink, nreqt.step) | 366 | h:receive09body(status, nreqt.sink, nreqt.step) |
| 318 | return 1, 200 | 367 | return 1, 200 |
| 368 | elseif code == 408 then | ||
| 369 | return 1, code | ||
| 319 | end | 370 | end |
| 320 | local headers | 371 | local headers |
| 321 | -- ignore any 100-continue messages | 372 | -- ignore any 100-continue messages |
| 322 | while code == 100 do | 373 | while code == 100 do |
| 323 | headers = h:receiveheaders() | 374 | h:receiveheaders() |
| 324 | code, status = h:receivestatusline() | 375 | code, status = h:receivestatusline() |
| 325 | end | 376 | end |
| 326 | headers = h:receiveheaders() | 377 | headers = h:receiveheaders() |
| 327 | -- at this point we should have a honest reply from the server | 378 | -- at this point we should have a honest reply from the server |
| 328 | -- we can't redirect if we already used the source, so we report the error | 379 | -- we can't redirect if we already used the source, so we report the error |
| 329 | if shouldredirect(nreqt, code, headers) and not nreqt.source then | 380 | if shouldredirect(nreqt, code, headers) and not nreqt.source then |
| 330 | h:close() | 381 | h:close() |
| 331 | return tredirect(reqt, headers.location) | 382 | return tredirect(reqt, headers.location) |
| @@ -338,11 +389,13 @@ end | |||
| 338 | return 1, code, headers, status | 389 | return 1, code, headers, status |
| 339 | end | 390 | end |
| 340 | 391 | ||
| 341 | local function srequest(u, b) | 392 | -- turns an url and a body into a generic request |
| 393 | local function genericform(u, b) | ||
| 342 | local t = {} | 394 | local t = {} |
| 343 | local reqt = { | 395 | local reqt = { |
| 344 | url = u, | 396 | url = u, |
| 345 | sink = ltn12.sink.table(t) | 397 | sink = ltn12.sink.table(t), |
| 398 | target = t | ||
| 346 | } | 399 | } |
| 347 | if b then | 400 | if b then |
| 348 | reqt.source = ltn12.source.string(b) | 401 | reqt.source = ltn12.source.string(b) |
| @@ -352,8 +405,15 @@ local function srequest(u, b) | |||
| 352 | } | 405 | } |
| 353 | reqt.method = "POST" | 406 | reqt.method = "POST" |
| 354 | end | 407 | end |
| 355 | local code, headers, status = socket.skip(1, trequest(reqt)) | 408 | return reqt |
| 356 | return table.concat(t), code, headers, status | 409 | end |
| 410 | |||
| 411 | _M.genericform = genericform | ||
| 412 | |||
| 413 | local function srequest(u, b) | ||
| 414 | local reqt = genericform(u, b) | ||
| 415 | local _, code, headers, status = trequest(reqt) | ||
| 416 | return table.concat(reqt.target), code, headers, status | ||
| 357 | end | 417 | end |
| 358 | 418 | ||
| 359 | _M.request = socket.protect(function(reqt, body) | 419 | _M.request = socket.protect(function(reqt, body) |
| @@ -361,4 +421,5 @@ _M.request = socket.protect(function(reqt, body) | |||
| 361 | else return trequest(reqt) end | 421 | else return trequest(reqt) end |
| 362 | end) | 422 | end) |
| 363 | 423 | ||
| 424 | _M.schemes = SCHEMES | ||
| 364 | return _M | 425 | return _M |
diff --git a/src/inet.c b/src/inet.c index 331b800..138c9ab 100644..100755 --- a/src/inet.c +++ b/src/inet.c | |||
| @@ -2,16 +2,13 @@ | |||
| 2 | * Internet domain functions | 2 | * Internet domain functions |
| 3 | * LuaSocket toolkit | 3 | * LuaSocket toolkit |
| 4 | \*=========================================================================*/ | 4 | \*=========================================================================*/ |
| 5 | #include "luasocket.h" | ||
| 6 | #include "inet.h" | ||
| 7 | |||
| 5 | #include <stdio.h> | 8 | #include <stdio.h> |
| 6 | #include <stdlib.h> | 9 | #include <stdlib.h> |
| 7 | #include <string.h> | 10 | #include <string.h> |
| 8 | 11 | ||
| 9 | #include "lua.h" | ||
| 10 | #include "lauxlib.h" | ||
| 11 | #include "compat.h" | ||
| 12 | |||
| 13 | #include "inet.h" | ||
| 14 | |||
| 15 | /*=========================================================================*\ | 12 | /*=========================================================================*\ |
| 16 | * Internal function prototypes. | 13 | * Internal function prototypes. |
| 17 | \*=========================================================================*/ | 14 | \*=========================================================================*/ |
| @@ -32,9 +29,6 @@ static luaL_Reg func[] = { | |||
| 32 | { NULL, NULL} | 29 | { NULL, NULL} |
| 33 | }; | 30 | }; |
| 34 | 31 | ||
| 35 | /*=========================================================================*\ | ||
| 36 | * Exported functions | ||
| 37 | \*=========================================================================*/ | ||
| 38 | /*-------------------------------------------------------------------------*\ | 32 | /*-------------------------------------------------------------------------*\ |
| 39 | * Initializes module | 33 | * Initializes module |
| 40 | \*-------------------------------------------------------------------------*/ | 34 | \*-------------------------------------------------------------------------*/ |
| @@ -259,7 +253,7 @@ int inet_meth_getpeername(lua_State *L, p_socket ps, int family) | |||
| 259 | port, sizeof(port), NI_NUMERICHOST | NI_NUMERICSERV); | 253 | port, sizeof(port), NI_NUMERICHOST | NI_NUMERICSERV); |
| 260 | if (err) { | 254 | if (err) { |
| 261 | lua_pushnil(L); | 255 | lua_pushnil(L); |
| 262 | lua_pushstring(L, gai_strerror(err)); | 256 | lua_pushstring(L, LUA_GAI_STRERROR(err)); |
| 263 | return 2; | 257 | return 2; |
| 264 | } | 258 | } |
| 265 | lua_pushstring(L, name); | 259 | lua_pushstring(L, name); |
| @@ -292,7 +286,7 @@ int inet_meth_getsockname(lua_State *L, p_socket ps, int family) | |||
| 292 | name, INET6_ADDRSTRLEN, port, 6, NI_NUMERICHOST | NI_NUMERICSERV); | 286 | name, INET6_ADDRSTRLEN, port, 6, NI_NUMERICHOST | NI_NUMERICSERV); |
| 293 | if (err) { | 287 | if (err) { |
| 294 | lua_pushnil(L); | 288 | lua_pushnil(L); |
| 295 | lua_pushstring(L, gai_strerror(err)); | 289 | lua_pushstring(L, LUA_GAI_STRERROR(err)); |
| 296 | return 2; | 290 | return 2; |
| 297 | } | 291 | } |
| 298 | lua_pushstring(L, name); | 292 | lua_pushstring(L, name); |
| @@ -423,8 +417,8 @@ const char *inet_tryconnect(p_socket ps, int *family, const char *address, | |||
| 423 | /* try connecting to remote address */ | 417 | /* try connecting to remote address */ |
| 424 | err = socket_strerror(socket_connect(ps, (SA *) iterator->ai_addr, | 418 | err = socket_strerror(socket_connect(ps, (SA *) iterator->ai_addr, |
| 425 | (socklen_t) iterator->ai_addrlen, tm)); | 419 | (socklen_t) iterator->ai_addrlen, tm)); |
| 426 | /* if success, break out of loop */ | 420 | /* if success or timeout is zero, break out of loop */ |
| 427 | if (err == NULL) { | 421 | if (err == NULL || timeout_iszero(tm)) { |
| 428 | *family = current_family; | 422 | *family = current_family; |
| 429 | break; | 423 | break; |
| 430 | } | 424 | } |
| @@ -14,7 +14,7 @@ | |||
| 14 | * | 14 | * |
| 15 | * The Lua functions toip and tohostname are also implemented here. | 15 | * The Lua functions toip and tohostname are also implemented here. |
| 16 | \*=========================================================================*/ | 16 | \*=========================================================================*/ |
| 17 | #include "lua.h" | 17 | #include "luasocket.h" |
| 18 | #include "socket.h" | 18 | #include "socket.h" |
| 19 | #include "timeout.h" | 19 | #include "timeout.h" |
| 20 | 20 | ||
| @@ -22,21 +22,23 @@ | |||
| 22 | #define LUASOCKET_INET_ATON | 22 | #define LUASOCKET_INET_ATON |
| 23 | #endif | 23 | #endif |
| 24 | 24 | ||
| 25 | #ifndef _WIN32 | ||
| 26 | #pragma GCC visibility push(hidden) | ||
| 27 | #endif | ||
| 28 | |||
| 25 | int inet_open(lua_State *L); | 29 | int inet_open(lua_State *L); |
| 26 | 30 | ||
| 27 | const char *inet_trycreate(p_socket ps, int family, int type, int protocol); | 31 | int inet_optfamily(lua_State* L, int narg, const char* def); |
| 28 | const char *inet_tryconnect(p_socket ps, int *family, const char *address, | 32 | int inet_optsocktype(lua_State* L, int narg, const char* def); |
| 29 | const char *serv, p_timeout tm, struct addrinfo *connecthints); | ||
| 30 | const char *inet_trybind(p_socket ps, int *family, const char *address, | ||
| 31 | const char *serv, struct addrinfo *bindhints); | ||
| 32 | const char *inet_trydisconnect(p_socket ps, int family, p_timeout tm); | ||
| 33 | const char *inet_tryaccept(p_socket server, int family, p_socket client, p_timeout tm); | ||
| 34 | 33 | ||
| 35 | int inet_meth_getpeername(lua_State *L, p_socket ps, int family); | 34 | int inet_meth_getpeername(lua_State *L, p_socket ps, int family); |
| 36 | int inet_meth_getsockname(lua_State *L, p_socket ps, int family); | 35 | int inet_meth_getsockname(lua_State *L, p_socket ps, int family); |
| 37 | 36 | ||
| 38 | int inet_optfamily(lua_State* L, int narg, const char* def); | 37 | const char *inet_trycreate(p_socket ps, int family, int type, int protocol); |
| 39 | int inet_optsocktype(lua_State* L, int narg, const char* def); | 38 | const char *inet_trydisconnect(p_socket ps, int family, p_timeout tm); |
| 39 | const char *inet_tryconnect(p_socket ps, int *family, const char *address, const char *serv, p_timeout tm, struct addrinfo *connecthints); | ||
| 40 | const char *inet_tryaccept(p_socket server, int family, p_socket client, p_timeout tm); | ||
| 41 | const char *inet_trybind(p_socket ps, int *family, const char *address, const char *serv, struct addrinfo *bindhints); | ||
| 40 | 42 | ||
| 41 | #ifdef LUASOCKET_INET_ATON | 43 | #ifdef LUASOCKET_INET_ATON |
| 42 | int inet_aton(const char *cp, struct in_addr *inp); | 44 | int inet_aton(const char *cp, struct in_addr *inp); |
| @@ -47,4 +49,8 @@ const char *inet_ntop(int af, const void *src, char *dst, socklen_t cnt); | |||
| 47 | int inet_pton(int af, const char *src, void *dst); | 49 | int inet_pton(int af, const char *src, void *dst); |
| 48 | #endif | 50 | #endif |
| 49 | 51 | ||
| 52 | #ifndef _WIN32 | ||
| 53 | #pragma GCC visibility pop | ||
| 54 | #endif | ||
| 55 | |||
| 50 | #endif /* INET_H */ | 56 | #endif /* INET_H */ |
| @@ -2,11 +2,9 @@ | |||
| 2 | * Input/Output abstraction | 2 | * Input/Output abstraction |
| 3 | * LuaSocket toolkit | 3 | * LuaSocket toolkit |
| 4 | \*=========================================================================*/ | 4 | \*=========================================================================*/ |
| 5 | #include "luasocket.h" | ||
| 5 | #include "io.h" | 6 | #include "io.h" |
| 6 | 7 | ||
| 7 | /*=========================================================================*\ | ||
| 8 | * Exported functions | ||
| 9 | \*=========================================================================*/ | ||
| 10 | /*-------------------------------------------------------------------------*\ | 8 | /*-------------------------------------------------------------------------*\ |
| 11 | * Initializes C structure | 9 | * Initializes C structure |
| 12 | \*-------------------------------------------------------------------------*/ | 10 | \*-------------------------------------------------------------------------*/ |
| @@ -12,9 +12,7 @@ | |||
| 12 | * The module socket.h implements this interface, and thus the module tcp.h | 12 | * The module socket.h implements this interface, and thus the module tcp.h |
| 13 | * is very simple. | 13 | * is very simple. |
| 14 | \*=========================================================================*/ | 14 | \*=========================================================================*/ |
| 15 | #include <stdio.h> | 15 | #include "luasocket.h" |
| 16 | #include "lua.h" | ||
| 17 | |||
| 18 | #include "timeout.h" | 16 | #include "timeout.h" |
| 19 | 17 | ||
| 20 | /* IO error codes */ | 18 | /* IO error codes */ |
| @@ -58,8 +56,15 @@ typedef struct t_io_ { | |||
| 58 | } t_io; | 56 | } t_io; |
| 59 | typedef t_io *p_io; | 57 | typedef t_io *p_io; |
| 60 | 58 | ||
| 59 | #ifndef _WIN32 | ||
| 60 | #pragma GCC visibility push(hidden) | ||
| 61 | #endif | ||
| 62 | |||
| 61 | void io_init(p_io io, p_send send, p_recv recv, p_error error, void *ctx); | 63 | void io_init(p_io io, p_send send, p_recv recv, p_error error, void *ctx); |
| 62 | const char *io_strerror(int err); | 64 | const char *io_strerror(int err); |
| 63 | 65 | ||
| 64 | #endif /* IO_H */ | 66 | #ifndef _WIN32 |
| 67 | #pragma GCC visibility pop | ||
| 68 | #endif | ||
| 65 | 69 | ||
| 70 | #endif /* IO_H */ | ||
diff --git a/src/ltn12.lua b/src/ltn12.lua index 1014de2..4cb17f5 100644 --- a/src/ltn12.lua +++ b/src/ltn12.lua | |||
| @@ -9,10 +9,13 @@ | |||
| 9 | ----------------------------------------------------------------------------- | 9 | ----------------------------------------------------------------------------- |
| 10 | local string = require("string") | 10 | local string = require("string") |
| 11 | local table = require("table") | 11 | local table = require("table") |
| 12 | local unpack = unpack or table.unpack | ||
| 12 | local base = _G | 13 | local base = _G |
| 14 | local select = select | ||
| 15 | |||
| 13 | local _M = {} | 16 | local _M = {} |
| 14 | if module then -- heuristic for exporting a global package table | 17 | if module then -- heuristic for exporting a global package table |
| 15 | ltn12 = _M | 18 | ltn12 = _M -- luacheck: ignore |
| 16 | end | 19 | end |
| 17 | local filter,source,sink,pump = {},{},{},{} | 20 | local filter,source,sink,pump = {},{},{},{} |
| 18 | 21 | ||
| @@ -124,6 +127,16 @@ function source.string(s) | |||
| 124 | else return source.empty() end | 127 | else return source.empty() end |
| 125 | end | 128 | end |
| 126 | 129 | ||
| 130 | -- creates table source | ||
| 131 | function source.table(t) | ||
| 132 | base.assert('table' == type(t)) | ||
| 133 | local i = 0 | ||
| 134 | return function() | ||
| 135 | i = i + 1 | ||
| 136 | return t[i] | ||
| 137 | end | ||
| 138 | end | ||
| 139 | |||
| 127 | -- creates rewindable source | 140 | -- creates rewindable source |
| 128 | function source.rewind(src) | 141 | function source.rewind(src) |
| 129 | base.assert(src) | 142 | base.assert(src) |
diff --git a/src/luasocket.c b/src/luasocket.c index 7d9c802..0fd99f7 100644..100755 --- a/src/luasocket.c +++ b/src/luasocket.c | |||
| @@ -12,16 +12,6 @@ | |||
| 12 | * standard Lua read and write functions. | 12 | * standard Lua read and write functions. |
| 13 | \*=========================================================================*/ | 13 | \*=========================================================================*/ |
| 14 | 14 | ||
| 15 | /*=========================================================================*\ | ||
| 16 | * Standard include files | ||
| 17 | \*=========================================================================*/ | ||
| 18 | #include "lua.h" | ||
| 19 | #include "lauxlib.h" | ||
| 20 | #include "compat.h" | ||
| 21 | |||
| 22 | /*=========================================================================*\ | ||
| 23 | * LuaSocket includes | ||
| 24 | \*=========================================================================*/ | ||
| 25 | #include "luasocket.h" | 15 | #include "luasocket.h" |
| 26 | #include "auxiliar.h" | 16 | #include "auxiliar.h" |
| 27 | #include "except.h" | 17 | #include "except.h" |
| @@ -64,7 +54,7 @@ static luaL_Reg func[] = { | |||
| 64 | * Skip a few arguments | 54 | * Skip a few arguments |
| 65 | \*-------------------------------------------------------------------------*/ | 55 | \*-------------------------------------------------------------------------*/ |
| 66 | static int global_skip(lua_State *L) { | 56 | static int global_skip(lua_State *L) { |
| 67 | int amount = luaL_checkinteger(L, 1); | 57 | int amount = (int) luaL_checkinteger(L, 1); |
| 68 | int ret = lua_gettop(L) - amount - 1; | 58 | int ret = lua_gettop(L) - amount - 1; |
| 69 | return ret >= 0 ? ret : 0; | 59 | return ret >= 0 ? ret : 0; |
| 70 | } | 60 | } |
diff --git a/src/luasocket.h b/src/luasocket.h index f75d21f..1017fba 100644 --- a/src/luasocket.h +++ b/src/luasocket.h | |||
| @@ -6,21 +6,28 @@ | |||
| 6 | * Diego Nehab | 6 | * Diego Nehab |
| 7 | * 9/11/1999 | 7 | * 9/11/1999 |
| 8 | \*=========================================================================*/ | 8 | \*=========================================================================*/ |
| 9 | #include "lua.h" | ||
| 10 | 9 | ||
| 11 | /*-------------------------------------------------------------------------*\ | 10 | /*-------------------------------------------------------------------------* \ |
| 12 | * Current socket library version | 11 | * Current socket library version |
| 13 | \*-------------------------------------------------------------------------*/ | 12 | \*-------------------------------------------------------------------------*/ |
| 14 | #define LUASOCKET_VERSION "LuaSocket 3.0-rc1" | 13 | #define LUASOCKET_VERSION "LuaSocket 3.0.0" |
| 15 | #define LUASOCKET_COPYRIGHT "Copyright (C) 1999-2013 Diego Nehab" | 14 | #define LUASOCKET_COPYRIGHT "Copyright (C) 1999-2013 Diego Nehab" |
| 16 | 15 | ||
| 17 | /*-------------------------------------------------------------------------*\ | 16 | /*-------------------------------------------------------------------------*\ |
| 18 | * This macro prefixes all exported API functions | 17 | * This macro prefixes all exported API functions |
| 19 | \*-------------------------------------------------------------------------*/ | 18 | \*-------------------------------------------------------------------------*/ |
| 20 | #ifndef LUASOCKET_API | 19 | #ifndef LUASOCKET_API |
| 21 | #define LUASOCKET_API extern | 20 | #ifdef _WIN32 |
| 21 | #define LUASOCKET_API __declspec(dllexport) | ||
| 22 | #else | ||
| 23 | #define LUASOCKET_API __attribute__ ((visibility ("default"))) | ||
| 24 | #endif | ||
| 22 | #endif | 25 | #endif |
| 23 | 26 | ||
| 27 | #include "lua.h" | ||
| 28 | #include "lauxlib.h" | ||
| 29 | #include "compat.h" | ||
| 30 | |||
| 24 | /*-------------------------------------------------------------------------*\ | 31 | /*-------------------------------------------------------------------------*\ |
| 25 | * Initializes the library. | 32 | * Initializes the library. |
| 26 | \*-------------------------------------------------------------------------*/ | 33 | \*-------------------------------------------------------------------------*/ |
diff --git a/src/makefile b/src/makefile index 2704a92..06f4d19 100644..100755 --- a/src/makefile +++ b/src/makefile | |||
| @@ -12,34 +12,31 @@ | |||
| 12 | # | 12 | # |
| 13 | # make PLAT=linux DEBUG=DEBUG LUAV=5.2 prefix=/sw | 13 | # make PLAT=linux DEBUG=DEBUG LUAV=5.2 prefix=/sw |
| 14 | 14 | ||
| 15 | # PLAT: linux macosx win32 mingw | 15 | # PLAT: linux macosx win32 win64 mingw |
| 16 | # platform to build for | 16 | # platform to build for |
| 17 | PLAT?=linux | 17 | PLAT?=linux |
| 18 | 18 | ||
| 19 | # LUAV: 5.1 5.2 | 19 | # LUAV: 5.1 5.2 5.3 5.4 |
| 20 | # lua version to build against | 20 | # lua version to build against |
| 21 | LUAV?=5.1 | 21 | LUAV?=5.1 |
| 22 | 22 | ||
| 23 | # MYCFLAGS: to be set by user if needed | 23 | # MYCFLAGS: to be set by user if needed |
| 24 | MYCFLAGS= | 24 | MYCFLAGS?= |
| 25 | 25 | ||
| 26 | # MYLDFLAGS: to be set by user if needed | 26 | # MYLDFLAGS: to be set by user if needed |
| 27 | MYLDFLAGS= | 27 | MYLDFLAGS?= |
| 28 | 28 | ||
| 29 | # DEBUG: NODEBUG DEBUG | 29 | # DEBUG: NODEBUG DEBUG |
| 30 | # debug mode causes luasocket to collect and returns timing information useful | 30 | # debug mode causes luasocket to collect and returns timing information useful |
| 31 | # for testing and debugging luasocket itself | 31 | # for testing and debugging luasocket itself |
| 32 | DEBUG?=NODEBUG | 32 | DEBUG?=NODEBUG |
| 33 | 33 | ||
| 34 | # COMPAT: COMPAT NOCOMPAT | ||
| 35 | # when compiling for 5.2, use LUA_COMPAT_MODULE | ||
| 36 | COMPAT?=NOCOMPAT | ||
| 37 | |||
| 38 | # where lua headers are found for macosx builds | 34 | # where lua headers are found for macosx builds |
| 39 | # LUAINC_macosx: | 35 | # LUAINC_macosx: |
| 40 | # /opt/local/include | 36 | # /opt/local/include |
| 41 | LUAINC_macosx_base?=/opt/local/include | 37 | LUAINC_macosx_base?=/opt/local/include |
| 42 | LUAINC_macosx?=$(LUAINC_macosx_base)/lua/$(LUAV) | 38 | LUAINC_macosx?=$(LUAINC_macosx_base)/lua/$(LUAV) $(LUAINC_macosx_base)/lua$(LUAV) $(LUAINC_macosx_base)/lua-$(LUAV) |
| 39 | |||
| 43 | # FIXME default should this default to fink or to macports? | 40 | # FIXME default should this default to fink or to macports? |
| 44 | # What happens when more than one Lua version is installed? | 41 | # What happens when more than one Lua version is installed? |
| 45 | LUAPREFIX_macosx?=/opt/local | 42 | LUAPREFIX_macosx?=/opt/local |
| @@ -52,16 +49,16 @@ LDIR_macosx?=share/lua/$(LUAV) | |||
| 52 | # /usr/local/include/lua$(LUAV) | 49 | # /usr/local/include/lua$(LUAV) |
| 53 | # where lua headers are found for linux builds | 50 | # where lua headers are found for linux builds |
| 54 | LUAINC_linux_base?=/usr/include | 51 | LUAINC_linux_base?=/usr/include |
| 55 | LUAINC_linux?=$(LUAINC_linux_base)/lua/$(LUAV) | 52 | LUAINC_linux?=$(LUAINC_linux_base)/lua/$(LUAV) $(LUAINC_linux_base)/lua$(LUAV) |
| 56 | LUAPREFIX_linux?=/usr/local | 53 | LUAPREFIX_linux?=/usr/local |
| 57 | CDIR_linux?=lib/lua/$(LUAV) | 54 | CDIR_linux?=lib/lua/$(LUAV) |
| 58 | LDIR_linux?=share/lua/$(LUAV) | 55 | LDIR_linux?=share/lua/$(LUAV) |
| 59 | 56 | ||
| 60 | # LUAINC_freebsd: | 57 | # LUAINC_freebsd: |
| 61 | # /usr/local/include/lua$(LUAV) | 58 | # /usr/local/include/lua$(LUAV) |
| 62 | # where lua headers are found for linux builds | 59 | # where lua headers are found for freebsd builds |
| 63 | LUAINC_freebsd_base?=/usr/local/include/ | 60 | LUAINC_freebsd_base?=/usr/local/include/ |
| 64 | LUAINC_freebsd?=$(LUAINC_freebsd_base)/lua$(LUAV) | 61 | LUAINC_freebsd?=$(LUAINC_freebsd_base)/lua/$(LUAV) $(LUAINC_freebsd_base)/lua$(LUAV) |
| 65 | LUAPREFIX_freebsd?=/usr/local/ | 62 | LUAPREFIX_freebsd?=/usr/local/ |
| 66 | CDIR_freebsd?=lib/lua/$(LUAV) | 63 | CDIR_freebsd?=lib/lua/$(LUAV) |
| 67 | LDIR_freebsd?=share/lua/$(LUAV) | 64 | LDIR_freebsd?=share/lua/$(LUAV) |
| @@ -70,7 +67,7 @@ LDIR_freebsd?=share/lua/$(LUAV) | |||
| 70 | # LUAINC_mingw: | 67 | # LUAINC_mingw: |
| 71 | # /opt/local/include | 68 | # /opt/local/include |
| 72 | LUAINC_mingw_base?=/usr/include | 69 | LUAINC_mingw_base?=/usr/include |
| 73 | LUAINC_mingw?=$(LUAINC_mingw_base)/lua/$(LUAV) | 70 | LUAINC_mingw?=$(LUAINC_mingw_base)/lua/$(LUAV) $(LUAINC_mingw_base)/lua$(LUAV) |
| 74 | LUALIB_mingw_base?=/usr/bin | 71 | LUALIB_mingw_base?=/usr/bin |
| 75 | LUALIB_mingw?=$(LUALIB_mingw_base)/lua/$(LUAV)/lua$(subst .,,$(LUAV)).dll | 72 | LUALIB_mingw?=$(LUALIB_mingw_base)/lua/$(LUAV)/lua$(subst .,,$(LUAV)).dll |
| 76 | LUAPREFIX_mingw?=/usr | 73 | LUAPREFIX_mingw?=/usr |
| @@ -81,13 +78,32 @@ LDIR_mingw?=lua/$(LUAV)/lua | |||
| 81 | # LUAINC_win32: | 78 | # LUAINC_win32: |
| 82 | # LUALIB_win32: | 79 | # LUALIB_win32: |
| 83 | # where lua headers and libraries are found for win32 builds | 80 | # where lua headers and libraries are found for win32 builds |
| 84 | LUAINC_win32_base?= | ||
| 85 | LUAINC_win32?=$(LUAINC_win32_base)/lua/$(LUAV) | ||
| 86 | PLATFORM_win32?=Release | ||
| 87 | LUAPREFIX_win32?= | 81 | LUAPREFIX_win32?= |
| 88 | CDIR_win32?=lua/$(LUAV)/$(PLATFORM_win32) | 82 | LUAINC_win32?=$(LUAPREFIX_win32)/include/lua/$(LUAV) $(LUAPREFIX_win32)/include/lua$(LUAV) |
| 89 | LDIR_win32?=lua/$(LUAV)/$(PLATFORM_win32)/lua | 83 | PLATFORM_win32?=Release |
| 90 | LUALIB_win32?=$(LUAPREFIX_win32)/lua/$(LUAV)/$(PLATFORM_win32) | 84 | CDIR_win32?=bin/lua/$(LUAV)/$(PLATFORM_win32) |
| 85 | LDIR_win32?=bin/lua/$(LUAV)/$(PLATFORM_win32)/lua | ||
| 86 | LUALIB_win32?=$(LUAPREFIX_win32)/lib/lua/$(LUAV)/$(PLATFORM_win32) | ||
| 87 | LUALIBNAME_win32?=lua$(subst .,,$(LUAV)).lib | ||
| 88 | |||
| 89 | # LUAINC_win64: | ||
| 90 | # LUALIB_win64: | ||
| 91 | # where lua headers and libraries are found for win64 builds | ||
| 92 | LUAPREFIX_win64?= | ||
| 93 | LUAINC_win64?=$(LUAPREFIX_win64)/include/lua/$(LUAV) $(LUAPREFIX_win64)/include/lua$(LUAV) | ||
| 94 | PLATFORM_win64?=x64/Release | ||
| 95 | CDIR_win64?=bin/lua/$(LUAV)/$(PLATFORM_win64) | ||
| 96 | LDIR_win64?=bin/lua/$(LUAV)/$(PLATFORM_win64)/lua | ||
| 97 | LUALIB_win64?=$(LUAPREFIX_win64)/lib/lua/$(LUAV)/$(PLATFORM_win64) | ||
| 98 | LUALIBNAME_win64?=lua$(subst .,,$(LUAV)).lib | ||
| 99 | |||
| 100 | |||
| 101 | # LUAINC_solaris: | ||
| 102 | LUAINC_solaris_base?=/usr/include | ||
| 103 | LUAINC_solaris?=$(LUAINC_solaris_base)/lua/$(LUAV) $(LUAINC_solaris_base)/lua$(LUAV) | ||
| 104 | LUAPREFIX_solaris?=/usr/local | ||
| 105 | CDIR_solaris?=lib/lua/$(LUAV) | ||
| 106 | LDIR_solaris?=share/lua/$(LUAV) | ||
| 91 | 107 | ||
| 92 | # prefix: /usr/local /usr /opt/local /sw | 108 | # prefix: /usr/local /usr /opt/local /sw |
| 93 | # the top of the default install tree | 109 | # the top of the default install tree |
| @@ -98,7 +114,7 @@ LDIR?=$(LDIR_$(PLAT)) | |||
| 98 | 114 | ||
| 99 | # DESTDIR: (no default) | 115 | # DESTDIR: (no default) |
| 100 | # used by package managers to install into a temporary destination | 116 | # used by package managers to install into a temporary destination |
| 101 | DESTDIR= | 117 | DESTDIR?= |
| 102 | 118 | ||
| 103 | #------ | 119 | #------ |
| 104 | # Definitions below can be overridden on the make command line, but | 120 | # Definitions below can be overridden on the make command line, but |
| @@ -131,11 +147,13 @@ print: | |||
| 131 | @echo LUALIB_$(PLAT)=$(LUALIB_$(PLAT)) | 147 | @echo LUALIB_$(PLAT)=$(LUALIB_$(PLAT)) |
| 132 | @echo INSTALL_TOP_CDIR=$(INSTALL_TOP_CDIR) | 148 | @echo INSTALL_TOP_CDIR=$(INSTALL_TOP_CDIR) |
| 133 | @echo INSTALL_TOP_LDIR=$(INSTALL_TOP_LDIR) | 149 | @echo INSTALL_TOP_LDIR=$(INSTALL_TOP_LDIR) |
| 150 | @echo CFLAGS=$(CFLAGS) | ||
| 151 | @echo LDFLAGS=$(LDFLAGS) | ||
| 134 | 152 | ||
| 135 | #------ | 153 | #------ |
| 136 | # Supported platforms | 154 | # Supported platforms |
| 137 | # | 155 | # |
| 138 | PLATS= macosx linux win32 mingw | 156 | PLATS= macosx linux win32 win64 mingw solaris |
| 139 | 157 | ||
| 140 | #------ | 158 | #------ |
| 141 | # Compiler and linker settings | 159 | # Compiler and linker settings |
| @@ -143,14 +161,10 @@ PLATS= macosx linux win32 mingw | |||
| 143 | SO_macosx=so | 161 | SO_macosx=so |
| 144 | O_macosx=o | 162 | O_macosx=o |
| 145 | CC_macosx=gcc | 163 | CC_macosx=gcc |
| 146 | DEF_macosx= -DLUASOCKET_$(DEBUG) -DUNIX_HAS_SUN_LEN -DLUA_$(COMPAT)_MODULE \ | 164 | DEF_macosx= -DLUASOCKET_$(DEBUG) -DUNIX_HAS_SUN_LEN |
| 147 | -DLUASOCKET_API='__attribute__((visibility("default")))' \ | 165 | CFLAGS_macosx=$(LUAINC:%=-I%) $(DEF) -Wall -O2 -fno-common |
| 148 | -DUNIX_API='__attribute__((visibility("default")))' \ | 166 | LDFLAGS_macosx= -bundle -undefined dynamic_lookup -o |
| 149 | -DMIME_API='__attribute__((visibility("default")))' | 167 | LD_macosx=gcc |
| 150 | CFLAGS_macosx= -I$(LUAINC) $(DEF) -Wall -O2 -fno-common \ | ||
| 151 | -fvisibility=hidden | ||
| 152 | LDFLAGS_macosx= -bundle -undefined dynamic_lookup -o | ||
| 153 | LD_macosx= export MACOSX_DEPLOYMENT_TARGET="10.3"; gcc | ||
| 154 | SOCKET_macosx=usocket.o | 168 | SOCKET_macosx=usocket.o |
| 155 | 169 | ||
| 156 | #------ | 170 | #------ |
| @@ -159,13 +173,10 @@ SOCKET_macosx=usocket.o | |||
| 159 | SO_linux=so | 173 | SO_linux=so |
| 160 | O_linux=o | 174 | O_linux=o |
| 161 | CC_linux=gcc | 175 | CC_linux=gcc |
| 162 | DEF_linux=-DLUASOCKET_$(DEBUG) -DLUA_$(COMPAT)_MODULE \ | 176 | DEF_linux=-DLUASOCKET_$(DEBUG) |
| 163 | -DLUASOCKET_API='__attribute__((visibility("default")))' \ | 177 | CFLAGS_linux=$(LUAINC:%=-I%) $(DEF) -Wall -Wshadow -Wextra \ |
| 164 | -DUNIX_API='__attribute__((visibility("default")))' \ | 178 | -Wimplicit -O2 -ggdb3 -fpic |
| 165 | -DMIME_API='__attribute__((visibility("default")))' | 179 | LDFLAGS_linux=-O -shared -fpic -o |
| 166 | CFLAGS_linux= -I$(LUAINC) $(DEF) -Wall -Wshadow -Wextra \ | ||
| 167 | -Wimplicit -O2 -ggdb3 -fpic -fvisibility=hidden | ||
| 168 | LDFLAGS_linux=-O -shared -fpic -o | ||
| 169 | LD_linux=gcc | 180 | LD_linux=gcc |
| 170 | SOCKET_linux=usocket.o | 181 | SOCKET_linux=usocket.o |
| 171 | 182 | ||
| @@ -175,28 +186,36 @@ SOCKET_linux=usocket.o | |||
| 175 | SO_freebsd=so | 186 | SO_freebsd=so |
| 176 | O_freebsd=o | 187 | O_freebsd=o |
| 177 | CC_freebsd=gcc | 188 | CC_freebsd=gcc |
| 178 | DEF_freebsd=-DLUASOCKET_$(DEBUG) -DLUA_$(COMPAT)_MODULE \ | 189 | DEF_freebsd=-DLUASOCKET_$(DEBUG) -DUNIX_HAS_SUN_LEN |
| 179 | -DLUASOCKET_API='__attribute__((visibility("default")))' \ | 190 | CFLAGS_freebsd=$(LUAINC:%=-I%) $(DEF) -Wall -Wshadow -Wextra \ |
| 180 | -DUNIX_API='__attribute__((visibility("default")))' \ | 191 | -Wimplicit -O2 -ggdb3 -fpic |
| 181 | -DMIME_API='__attribute__((visibility("default")))' | 192 | LDFLAGS_freebsd=-O -shared -fpic -o |
| 182 | CFLAGS_freebsd= -I$(LUAINC) $(DEF) -Wall -Wshadow -Wextra \ | ||
| 183 | -Wimplicit -O2 -ggdb3 -fpic -fvisibility=hidden | ||
| 184 | LDFLAGS_freebsd=-O -shared -fpic -o | ||
| 185 | LD_freebsd=gcc | 193 | LD_freebsd=gcc |
| 186 | SOCKET_freebsd=usocket.o | 194 | SOCKET_freebsd=usocket.o |
| 187 | 195 | ||
| 188 | #------ | 196 | #------ |
| 189 | # Compiler and linker settings | 197 | # Compiler and linker settings |
| 198 | # for Solaris | ||
| 199 | SO_solaris=so | ||
| 200 | O_solaris=o | ||
| 201 | CC_solaris=gcc | ||
| 202 | DEF_solaris=-DLUASOCKET_$(DEBUG) | ||
| 203 | CFLAGS_solaris=$(LUAINC:%=-I%) $(DEF) -Wall -Wshadow -Wextra \ | ||
| 204 | -Wimplicit -O2 -ggdb3 -fpic | ||
| 205 | LDFLAGS_solaris=-lnsl -lsocket -lresolv -O -shared -fpic -o | ||
| 206 | LD_solaris=gcc | ||
| 207 | SOCKET_solaris=usocket.o | ||
| 208 | |||
| 209 | #------ | ||
| 210 | # Compiler and linker settings | ||
| 190 | # for MingW | 211 | # for MingW |
| 191 | SO_mingw=dll | 212 | SO_mingw=dll |
| 192 | O_mingw=o | 213 | O_mingw=o |
| 193 | CC_mingw=gcc | 214 | CC_mingw=gcc |
| 194 | DEF_mingw= -DLUASOCKET_INET_PTON -DLUASOCKET_$(DEBUG) -DLUA_$(COMPAT)_MODULE \ | 215 | DEF_mingw= -DLUASOCKET_$(DEBUG) \ |
| 195 | -DWINVER=0x0501 -DLUASOCKET_API='__declspec(dllexport)' \ | 216 | -DWINVER=0x0501 |
| 196 | -DMIME_API='__declspec(dllexport)' | 217 | CFLAGS_mingw=$(LUAINC:%=-I%) $(DEF) -Wall -O2 -fno-common |
| 197 | CFLAGS_mingw= -I$(LUAINC) $(DEF) -Wall -O2 -fno-common \ | 218 | LDFLAGS_mingw= $(LUALIB) -shared -Wl,-s -lws2_32 -o |
| 198 | -fvisibility=hidden | ||
| 199 | LDFLAGS_mingw= $(LUALIB) -shared -Wl,-s -lws2_32 -o | ||
| 200 | LD_mingw=gcc | 219 | LD_mingw=gcc |
| 201 | SOCKET_mingw=wsocket.o | 220 | SOCKET_mingw=wsocket.o |
| 202 | 221 | ||
| @@ -208,34 +227,55 @@ SO_win32=dll | |||
| 208 | O_win32=obj | 227 | O_win32=obj |
| 209 | CC_win32=cl | 228 | CC_win32=cl |
| 210 | DEF_win32= //D "WIN32" //D "NDEBUG" //D "_WINDOWS" //D "_USRDLL" \ | 229 | DEF_win32= //D "WIN32" //D "NDEBUG" //D "_WINDOWS" //D "_USRDLL" \ |
| 211 | //D "LUASOCKET_API=__declspec(dllexport)" //D "_CRT_SECURE_NO_WARNINGS" \ | 230 | //D "_CRT_SECURE_NO_WARNINGS" \ |
| 212 | //D "_WINDLL" //D "LUA_$(COMPAT)_MODULE" \ | 231 | //D "_WINDLL" \ |
| 213 | //D "MIME_API=__declspec(dllexport)" \ | 232 | //D "LUASOCKET_$(DEBUG)" |
| 214 | //D "LUASOCKET_$(DEBUG)" | 233 | CFLAGS_win32=$(LUAINC:%=//I "%") $(DEF) //O2 //Ot //MD //W3 //nologo |
| 215 | CFLAGS_win32=//I "$(LUAINC)" $(DEF) //O2 //Ot //MD //W3 //nologo | ||
| 216 | LDFLAGS_win32= //nologo //link //NOLOGO //DLL //INCREMENTAL:NO \ | 234 | LDFLAGS_win32= //nologo //link //NOLOGO //DLL //INCREMENTAL:NO \ |
| 217 | //MANIFEST //MANIFESTFILE:"intermediate.manifest" \ | 235 | //MANIFEST //MANIFESTFILE:"intermediate.manifest" \ |
| 218 | //MANIFESTUAC:"level='asInvoker' uiAccess='false'" \ | 236 | /MANIFESTUAC:"level='asInvoker' uiAccess='false'" \ |
| 219 | //SUBSYSTEM:WINDOWS //OPT:REF //OPT:ICF //DYNAMICBASE:NO \ | 237 | //SUBSYSTEM:WINDOWS //OPT:REF //OPT:ICF //DYNAMICBASE:NO \ |
| 220 | //MACHINE:X86 /LIBPATH:"$(shell cmd //c echo $(LUALIB))" \ | 238 | //MACHINE:X86 /LIBPATH:"$(LUALIB)" \ |
| 221 | lua$(subst .,,$(LUAV)).lib ws2_32.lib //OUT: | 239 | $(LUALIBNAME_win32) ws2_32.lib //OUT: |
| 240 | |||
| 222 | LD_win32=cl | 241 | LD_win32=cl |
| 223 | SOCKET_win32=wsocket.obj | 242 | SOCKET_win32=wsocket.obj |
| 224 | 243 | ||
| 244 | #------ | ||
| 245 | # Compiler and linker settings | ||
| 246 | # for Win64 | ||
| 247 | SO_win64=dll | ||
| 248 | O_win64=obj | ||
| 249 | CC_win64=cl | ||
| 250 | DEF_win64= //D "WIN32" //D "NDEBUG" //D "_WINDOWS" //D "_USRDLL" \ | ||
| 251 | //D "_CRT_SECURE_NO_WARNINGS" \ | ||
| 252 | //D "_WINDLL" \ | ||
| 253 | //D "LUASOCKET_$(DEBUG)" | ||
| 254 | CFLAGS_win64=$(LUAINC:%=//I "%") $(DEF) //O2 //Ot //MD //W3 //nologo | ||
| 255 | LDFLAGS_win64= //nologo //link //NOLOGO //DLL //INCREMENTAL:NO \ | ||
| 256 | //MANIFEST //MANIFESTFILE:"intermediate.manifest" \ | ||
| 257 | /MANIFESTUAC:"level='asInvoker' uiAccess='false'" \ | ||
| 258 | //SUBSYSTEM:WINDOWS //OPT:REF //OPT:ICF //DYNAMICBASE:NO \ | ||
| 259 | /LIBPATH:"$(LUALIB)" \ | ||
| 260 | $(LUALIBNAME_win64) ws2_32.lib //OUT: | ||
| 261 | |||
| 262 | LD_win64=cl | ||
| 263 | SOCKET_win64=wsocket.obj | ||
| 264 | |||
| 225 | .SUFFIXES: .obj | 265 | .SUFFIXES: .obj |
| 226 | 266 | ||
| 227 | .c.obj: | 267 | .c.obj: |
| 228 | $(CC) $(LUASOCKET_CFLAGS) //Fo"$@" //c $< | 268 | $(CC) $(CFLAGS) //Fo"$@" //c $< |
| 229 | 269 | ||
| 230 | #------ | 270 | #------ |
| 231 | # Output file names | 271 | # Output file names |
| 232 | # | 272 | # |
| 233 | SO=$(SO_$(PLAT)) | 273 | SO=$(SO_$(PLAT)) |
| 234 | O=$(O_$(PLAT)) | 274 | O=$(O_$(PLAT)) |
| 235 | SOCKET_V=3.0-rc1 | 275 | SOCKET_V=3.0.0 |
| 236 | MIME_V=1.0.3 | 276 | MIME_V=1.0.3 |
| 237 | SOCKET_SO=socket.$(SO).$(SOCKET_V) | 277 | SOCKET_SO=socket-$(SOCKET_V).$(SO) |
| 238 | MIME_SO=mime.$(SO).$(MIME_V) | 278 | MIME_SO=mime-$(MIME_V).$(SO) |
| 239 | UNIX_SO=unix.$(SO) | 279 | UNIX_SO=unix.$(SO) |
| 240 | SERIAL_SO=serial.$(SO) | 280 | SERIAL_SO=serial.$(SO) |
| 241 | SOCKET=$(SOCKET_$(PLAT)) | 281 | SOCKET=$(SOCKET_$(PLAT)) |
| @@ -286,6 +326,9 @@ UNIX_OBJS=\ | |||
| 286 | timeout.$(O) \ | 326 | timeout.$(O) \ |
| 287 | io.$(O) \ | 327 | io.$(O) \ |
| 288 | usocket.$(O) \ | 328 | usocket.$(O) \ |
| 329 | unixstream.$(O) \ | ||
| 330 | unixdgram.$(O) \ | ||
| 331 | compat.$(O) \ | ||
| 289 | unix.$(O) | 332 | unix.$(O) |
| 290 | 333 | ||
| 291 | #------ | 334 | #------ |
| @@ -293,6 +336,7 @@ UNIX_OBJS=\ | |||
| 293 | # | 336 | # |
| 294 | SERIAL_OBJS=\ | 337 | SERIAL_OBJS=\ |
| 295 | buffer.$(O) \ | 338 | buffer.$(O) \ |
| 339 | compat.$(O) \ | ||
| 296 | auxiliar.$(O) \ | 340 | auxiliar.$(O) \ |
| 297 | options.$(O) \ | 341 | options.$(O) \ |
| 298 | timeout.$(O) \ | 342 | timeout.$(O) \ |
| @@ -331,12 +375,18 @@ macosx: | |||
| 331 | win32: | 375 | win32: |
| 332 | $(MAKE) all PLAT=win32 | 376 | $(MAKE) all PLAT=win32 |
| 333 | 377 | ||
| 378 | win64: | ||
| 379 | $(MAKE) all PLAT=win64 | ||
| 380 | |||
| 334 | linux: | 381 | linux: |
| 335 | $(MAKE) all-unix PLAT=linux | 382 | $(MAKE) all-unix PLAT=linux |
| 336 | 383 | ||
| 337 | mingw: | 384 | mingw: |
| 338 | $(MAKE) all PLAT=mingw | 385 | $(MAKE) all PLAT=mingw |
| 339 | 386 | ||
| 387 | solaris: | ||
| 388 | $(MAKE) all-unix PLAT=solaris | ||
| 389 | |||
| 340 | none: | 390 | none: |
| 341 | @echo "Please run" | 391 | @echo "Please run" |
| 342 | @echo " make PLATFORM" | 392 | @echo " make PLATFORM" |
| @@ -359,7 +409,7 @@ $(UNIX_SO): $(UNIX_OBJS) | |||
| 359 | $(SERIAL_SO): $(SERIAL_OBJS) | 409 | $(SERIAL_SO): $(SERIAL_OBJS) |
| 360 | $(LD) $(SERIAL_OBJS) $(LDFLAGS)$@ | 410 | $(LD) $(SERIAL_OBJS) $(LDFLAGS)$@ |
| 361 | 411 | ||
| 362 | install: | 412 | install: |
| 363 | $(INSTALL_DIR) $(INSTALL_TOP_LDIR) | 413 | $(INSTALL_DIR) $(INSTALL_TOP_LDIR) |
| 364 | $(INSTALL_DATA) $(TO_TOP_LDIR) $(INSTALL_TOP_LDIR) | 414 | $(INSTALL_DATA) $(TO_TOP_LDIR) $(INSTALL_TOP_LDIR) |
| 365 | $(INSTALL_DIR) $(INSTALL_SOCKET_LDIR) | 415 | $(INSTALL_DIR) $(INSTALL_SOCKET_LDIR) |
diff --git a/src/mbox.lua b/src/mbox.lua index 7724ae2..12823b0 100644 --- a/src/mbox.lua +++ b/src/mbox.lua | |||
| @@ -1,8 +1,8 @@ | |||
| 1 | local _M = {} | 1 | local _M = {} |
| 2 | 2 | ||
| 3 | if module then | 3 | if module then |
| 4 | mbox = _M | 4 | mbox = _M -- luacheck: ignore |
| 5 | end | 5 | end |
| 6 | 6 | ||
| 7 | function _M.split_message(message_s) | 7 | function _M.split_message(message_s) |
| 8 | local message = {} | 8 | local message = {} |
| @@ -29,7 +29,7 @@ end | |||
| 29 | function _M.parse_header(header_s) | 29 | function _M.parse_header(header_s) |
| 30 | header_s = string.gsub(header_s, "\n[ ]+", " ") | 30 | header_s = string.gsub(header_s, "\n[ ]+", " ") |
| 31 | header_s = string.gsub(header_s, "\n+", "") | 31 | header_s = string.gsub(header_s, "\n+", "") |
| 32 | local _, __, name, value = string.find(header_s, "([^%s:]-):%s*(.*)") | 32 | local _, _, name, value = string.find(header_s, "([^%s:]-):%s*(.*)") |
| 33 | return name, value | 33 | return name, value |
| 34 | end | 34 | end |
| 35 | 35 | ||
| @@ -49,9 +49,9 @@ function _M.parse_headers(headers_s) | |||
| 49 | end | 49 | end |
| 50 | 50 | ||
| 51 | function _M.parse_from(from) | 51 | function _M.parse_from(from) |
| 52 | local _, __, name, address = string.find(from, "^%s*(.-)%s*%<(.-)%>") | 52 | local _, _, name, address = string.find(from, "^%s*(.-)%s*%<(.-)%>") |
| 53 | if not address then | 53 | if not address then |
| 54 | _, __, address = string.find(from, "%s*(.+)%s*") | 54 | _, _, address = string.find(from, "%s*(.+)%s*") |
| 55 | end | 55 | end |
| 56 | name = name or "" | 56 | name = name or "" |
| 57 | address = address or "" | 57 | address = address or "" |
| @@ -61,9 +61,10 @@ function _M.parse_from(from) | |||
| 61 | end | 61 | end |
| 62 | 62 | ||
| 63 | function _M.split_mbox(mbox_s) | 63 | function _M.split_mbox(mbox_s) |
| 64 | mbox = {} | 64 | local mbox = {} |
| 65 | mbox_s = string.gsub(mbox_s, "\r\n", "\n") .."\n\nFrom \n" | 65 | mbox_s = string.gsub(mbox_s, "\r\n", "\n") .."\n\nFrom \n" |
| 66 | local nj, i, j = 1, 1, 1 | 66 | local nj, i |
| 67 | local j = 1 | ||
| 67 | while 1 do | 68 | while 1 do |
| 68 | i, nj = string.find(mbox_s, "\n\nFrom .-\n", j) | 69 | i, nj = string.find(mbox_s, "\n\nFrom .-\n", j) |
| 69 | if not i then break end | 70 | if not i then break end |
diff --git a/src/mime.c b/src/mime.c index ed44104..05602f5 100644..100755 --- a/src/mime.c +++ b/src/mime.c | |||
| @@ -2,13 +2,10 @@ | |||
| 2 | * MIME support functions | 2 | * MIME support functions |
| 3 | * LuaSocket toolkit | 3 | * LuaSocket toolkit |
| 4 | \*=========================================================================*/ | 4 | \*=========================================================================*/ |
| 5 | #include <string.h> | 5 | #include "luasocket.h" |
| 6 | |||
| 7 | #include "lua.h" | ||
| 8 | #include "lauxlib.h" | ||
| 9 | #include "compat.h" | ||
| 10 | |||
| 11 | #include "mime.h" | 6 | #include "mime.h" |
| 7 | #include <string.h> | ||
| 8 | #include <ctype.h> | ||
| 12 | 9 | ||
| 13 | /*=========================================================================*\ | 10 | /*=========================================================================*\ |
| 14 | * Don't want to trust escape character constants | 11 | * Don't want to trust escape character constants |
| @@ -30,12 +27,12 @@ static int mime_global_eol(lua_State *L); | |||
| 30 | static int mime_global_dot(lua_State *L); | 27 | static int mime_global_dot(lua_State *L); |
| 31 | 28 | ||
| 32 | static size_t dot(int c, size_t state, luaL_Buffer *buffer); | 29 | static size_t dot(int c, size_t state, luaL_Buffer *buffer); |
| 33 | static void b64setup(UC *base); | 30 | /*static void b64setup(UC *base);*/ |
| 34 | static size_t b64encode(UC c, UC *input, size_t size, luaL_Buffer *buffer); | 31 | static size_t b64encode(UC c, UC *input, size_t size, luaL_Buffer *buffer); |
| 35 | static size_t b64pad(const UC *input, size_t size, luaL_Buffer *buffer); | 32 | static size_t b64pad(const UC *input, size_t size, luaL_Buffer *buffer); |
| 36 | static size_t b64decode(UC c, UC *input, size_t size, luaL_Buffer *buffer); | 33 | static size_t b64decode(UC c, UC *input, size_t size, luaL_Buffer *buffer); |
| 37 | 34 | ||
| 38 | static void qpsetup(UC *class, UC *unbase); | 35 | /*static void qpsetup(UC *class, UC *unbase);*/ |
| 39 | static void qpquote(UC c, luaL_Buffer *buffer); | 36 | static void qpquote(UC c, luaL_Buffer *buffer); |
| 40 | static size_t qpdecode(UC c, UC *input, size_t size, luaL_Buffer *buffer); | 37 | static size_t qpdecode(UC c, UC *input, size_t size, luaL_Buffer *buffer); |
| 41 | static size_t qpencode(UC c, UC *input, size_t size, | 38 | static size_t qpencode(UC c, UC *input, size_t size, |
| @@ -58,17 +55,111 @@ static luaL_Reg func[] = { | |||
| 58 | /*-------------------------------------------------------------------------*\ | 55 | /*-------------------------------------------------------------------------*\ |
| 59 | * Quoted-printable globals | 56 | * Quoted-printable globals |
| 60 | \*-------------------------------------------------------------------------*/ | 57 | \*-------------------------------------------------------------------------*/ |
| 61 | static UC qpclass[256]; | ||
| 62 | static UC qpbase[] = "0123456789ABCDEF"; | ||
| 63 | static UC qpunbase[256]; | ||
| 64 | enum {QP_PLAIN, QP_QUOTED, QP_CR, QP_IF_LAST}; | 58 | enum {QP_PLAIN, QP_QUOTED, QP_CR, QP_IF_LAST}; |
| 65 | 59 | ||
| 60 | static const UC qpclass[] = { | ||
| 61 | QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, | ||
| 62 | QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_IF_LAST, QP_QUOTED, QP_QUOTED, | ||
| 63 | QP_QUOTED, QP_CR, QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, | ||
| 64 | QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, | ||
| 65 | QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, | ||
| 66 | QP_QUOTED, QP_QUOTED, QP_IF_LAST, QP_PLAIN, QP_PLAIN, QP_PLAIN, | ||
| 67 | QP_PLAIN, QP_PLAIN, QP_PLAIN, QP_PLAIN, QP_PLAIN, QP_PLAIN, | ||
| 68 | QP_PLAIN, QP_PLAIN, QP_PLAIN, QP_PLAIN, QP_PLAIN, QP_PLAIN, | ||
| 69 | QP_PLAIN, QP_PLAIN, QP_PLAIN, QP_PLAIN, QP_PLAIN, QP_PLAIN, | ||
| 70 | QP_PLAIN, QP_PLAIN, QP_PLAIN, QP_PLAIN, QP_PLAIN, QP_PLAIN, | ||
| 71 | QP_PLAIN, QP_QUOTED, QP_PLAIN, QP_PLAIN, QP_PLAIN, QP_PLAIN, | ||
| 72 | QP_PLAIN, QP_PLAIN, QP_PLAIN, QP_PLAIN, QP_PLAIN, QP_PLAIN, | ||
| 73 | QP_PLAIN, QP_PLAIN, QP_PLAIN, QP_PLAIN, QP_PLAIN, QP_PLAIN, | ||
| 74 | QP_PLAIN, QP_PLAIN, QP_PLAIN, QP_PLAIN, QP_PLAIN, QP_PLAIN, | ||
| 75 | QP_PLAIN, QP_PLAIN, QP_PLAIN, QP_PLAIN, QP_PLAIN, QP_PLAIN, | ||
| 76 | QP_PLAIN, QP_PLAIN, QP_PLAIN, QP_PLAIN, QP_PLAIN, QP_PLAIN, | ||
| 77 | QP_PLAIN, QP_PLAIN, QP_PLAIN, QP_PLAIN, QP_PLAIN, QP_PLAIN, | ||
| 78 | QP_PLAIN, QP_PLAIN, QP_PLAIN, QP_PLAIN, QP_PLAIN, QP_PLAIN, | ||
| 79 | QP_PLAIN, QP_PLAIN, QP_PLAIN, QP_PLAIN, QP_PLAIN, QP_PLAIN, | ||
| 80 | QP_PLAIN, QP_PLAIN, QP_PLAIN, QP_PLAIN, QP_PLAIN, QP_PLAIN, | ||
| 81 | QP_PLAIN, QP_PLAIN, QP_PLAIN, QP_PLAIN, QP_PLAIN, QP_PLAIN, | ||
| 82 | QP_PLAIN, QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, | ||
| 83 | QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, | ||
| 84 | QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, | ||
| 85 | QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, | ||
| 86 | QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, | ||
| 87 | QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, | ||
| 88 | QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, | ||
| 89 | QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, | ||
| 90 | QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, | ||
| 91 | QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, | ||
| 92 | QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, | ||
| 93 | QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, | ||
| 94 | QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, | ||
| 95 | QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, | ||
| 96 | QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, | ||
| 97 | QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, | ||
| 98 | QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, | ||
| 99 | QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, | ||
| 100 | QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, | ||
| 101 | QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, | ||
| 102 | QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, | ||
| 103 | QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED | ||
| 104 | }; | ||
| 105 | |||
| 106 | static const UC qpbase[] = "0123456789ABCDEF"; | ||
| 107 | |||
| 108 | static const UC qpunbase[] = { | ||
| 109 | 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, | ||
| 110 | 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, | ||
| 111 | 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, | ||
| 112 | 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, | ||
| 113 | 255, 255, 255, 255, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 255, | ||
| 114 | 255, 255, 255, 255, 255, 255, 10, 11, 12, 13, 14, 15, | ||
| 115 | 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, | ||
| 116 | 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, | ||
| 117 | 255, 255, 255, 255, 10, 11, 12, 13, 14, 15, 255, 255, | ||
| 118 | 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, | ||
| 119 | 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, | ||
| 120 | 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, | ||
| 121 | 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, | ||
| 122 | 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, | ||
| 123 | 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, | ||
| 124 | 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, | ||
| 125 | 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, | ||
| 126 | 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, | ||
| 127 | 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, | ||
| 128 | 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, | ||
| 129 | 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, | ||
| 130 | 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, | ||
| 131 | 255, 255, 255, 255, 255, 255, 255, 255 | ||
| 132 | }; | ||
| 133 | |||
| 66 | /*-------------------------------------------------------------------------*\ | 134 | /*-------------------------------------------------------------------------*\ |
| 67 | * Base64 globals | 135 | * Base64 globals |
| 68 | \*-------------------------------------------------------------------------*/ | 136 | \*-------------------------------------------------------------------------*/ |
| 69 | static const UC b64base[] = | 137 | static const UC b64base[] = |
| 70 | "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; | 138 | "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; |
| 71 | static UC b64unbase[256]; | 139 | |
| 140 | static const UC b64unbase[] = { | ||
| 141 | 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, | ||
| 142 | 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, | ||
| 143 | 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, | ||
| 144 | 255, 255, 255, 255, 255, 255, 255, 62, 255, 255, 255, 63, | ||
| 145 | 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 255, 255, 255, 0, | ||
| 146 | 255, 255, 255, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, | ||
| 147 | 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 255, 255, | ||
| 148 | 255, 255, 255, 255, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, | ||
| 149 | 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, | ||
| 150 | 51, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, | ||
| 151 | 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, | ||
| 152 | 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, | ||
| 153 | 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, | ||
| 154 | 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, | ||
| 155 | 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, | ||
| 156 | 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, | ||
| 157 | 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, | ||
| 158 | 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, | ||
| 159 | 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, | ||
| 160 | 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, | ||
| 161 | 255, 255 | ||
| 162 | }; | ||
| 72 | 163 | ||
| 73 | /*=========================================================================*\ | 164 | /*=========================================================================*\ |
| 74 | * Exported functions | 165 | * Exported functions |
| @@ -76,7 +167,7 @@ static UC b64unbase[256]; | |||
| 76 | /*-------------------------------------------------------------------------*\ | 167 | /*-------------------------------------------------------------------------*\ |
| 77 | * Initializes module | 168 | * Initializes module |
| 78 | \*-------------------------------------------------------------------------*/ | 169 | \*-------------------------------------------------------------------------*/ |
| 79 | MIME_API int luaopen_mime_core(lua_State *L) | 170 | LUASOCKET_API int luaopen_mime_core(lua_State *L) |
| 80 | { | 171 | { |
| 81 | lua_newtable(L); | 172 | lua_newtable(L); |
| 82 | luaL_setfuncs(L, func, 0); | 173 | luaL_setfuncs(L, func, 0); |
| @@ -85,8 +176,8 @@ MIME_API int luaopen_mime_core(lua_State *L) | |||
| 85 | lua_pushstring(L, MIME_VERSION); | 176 | lua_pushstring(L, MIME_VERSION); |
| 86 | lua_rawset(L, -3); | 177 | lua_rawset(L, -3); |
| 87 | /* initialize lookup tables */ | 178 | /* initialize lookup tables */ |
| 88 | qpsetup(qpclass, qpunbase); | 179 | /*qpsetup(qpclass, qpunbase);*/ |
| 89 | b64setup(b64unbase); | 180 | /*b64setup(b64unbase);*/ |
| 90 | return 1; | 181 | return 1; |
| 91 | } | 182 | } |
| 92 | 183 | ||
| @@ -142,6 +233,7 @@ static int mime_global_wrp(lua_State *L) | |||
| 142 | return 2; | 233 | return 2; |
| 143 | } | 234 | } |
| 144 | 235 | ||
| 236 | #if 0 | ||
| 145 | /*-------------------------------------------------------------------------*\ | 237 | /*-------------------------------------------------------------------------*\ |
| 146 | * Fill base64 decode map. | 238 | * Fill base64 decode map. |
| 147 | \*-------------------------------------------------------------------------*/ | 239 | \*-------------------------------------------------------------------------*/ |
| @@ -151,7 +243,14 @@ static void b64setup(UC *unbase) | |||
| 151 | for (i = 0; i <= 255; i++) unbase[i] = (UC) 255; | 243 | for (i = 0; i <= 255; i++) unbase[i] = (UC) 255; |
| 152 | for (i = 0; i < 64; i++) unbase[b64base[i]] = (UC) i; | 244 | for (i = 0; i < 64; i++) unbase[b64base[i]] = (UC) i; |
| 153 | unbase['='] = 0; | 245 | unbase['='] = 0; |
| 246 | |||
| 247 | printf("static const UC b64unbase[] = {\n"); | ||
| 248 | for (int i = 0; i < 256; i++) { | ||
| 249 | printf("%d, ", unbase[i]); | ||
| 250 | } | ||
| 251 | printf("\n}\n;"); | ||
| 154 | } | 252 | } |
| 253 | #endif | ||
| 155 | 254 | ||
| 156 | /*-------------------------------------------------------------------------*\ | 255 | /*-------------------------------------------------------------------------*\ |
| 157 | * Acumulates bytes in input buffer until 3 bytes are available. | 256 | * Acumulates bytes in input buffer until 3 bytes are available. |
| @@ -345,12 +444,14 @@ static int mime_global_unb64(lua_State *L) | |||
| 345 | * To encode one byte, we need to see the next two. | 444 | * To encode one byte, we need to see the next two. |
| 346 | * Worst case is when we see a space, and wonder if a CRLF is comming | 445 | * Worst case is when we see a space, and wonder if a CRLF is comming |
| 347 | \*-------------------------------------------------------------------------*/ | 446 | \*-------------------------------------------------------------------------*/ |
| 447 | #if 0 | ||
| 348 | /*-------------------------------------------------------------------------*\ | 448 | /*-------------------------------------------------------------------------*\ |
| 349 | * Split quoted-printable characters into classes | 449 | * Split quoted-printable characters into classes |
| 350 | * Precompute reverse map for encoding | 450 | * Precompute reverse map for encoding |
| 351 | \*-------------------------------------------------------------------------*/ | 451 | \*-------------------------------------------------------------------------*/ |
| 352 | static void qpsetup(UC *cl, UC *unbase) | 452 | static void qpsetup(UC *cl, UC *unbase) |
| 353 | { | 453 | { |
| 454 | |||
| 354 | int i; | 455 | int i; |
| 355 | for (i = 0; i < 256; i++) cl[i] = QP_QUOTED; | 456 | for (i = 0; i < 256; i++) cl[i] = QP_QUOTED; |
| 356 | for (i = 33; i <= 60; i++) cl[i] = QP_PLAIN; | 457 | for (i = 33; i <= 60; i++) cl[i] = QP_PLAIN; |
| @@ -367,7 +468,37 @@ static void qpsetup(UC *cl, UC *unbase) | |||
| 367 | unbase['c'] = 12; unbase['D'] = 13; unbase['d'] = 13; | 468 | unbase['c'] = 12; unbase['D'] = 13; unbase['d'] = 13; |
| 368 | unbase['E'] = 14; unbase['e'] = 14; unbase['F'] = 15; | 469 | unbase['E'] = 14; unbase['e'] = 14; unbase['F'] = 15; |
| 369 | unbase['f'] = 15; | 470 | unbase['f'] = 15; |
| 471 | |||
| 472 | printf("static UC qpclass[] = {"); | ||
| 473 | for (int i = 0; i < 256; i++) { | ||
| 474 | if (i % 6 == 0) { | ||
| 475 | printf("\n "); | ||
| 476 | } | ||
| 477 | switch(cl[i]) { | ||
| 478 | case QP_QUOTED: | ||
| 479 | printf("QP_QUOTED, "); | ||
| 480 | break; | ||
| 481 | case QP_PLAIN: | ||
| 482 | printf("QP_PLAIN, "); | ||
| 483 | break; | ||
| 484 | case QP_CR: | ||
| 485 | printf("QP_CR, "); | ||
| 486 | break; | ||
| 487 | case QP_IF_LAST: | ||
| 488 | printf("QP_IF_LAST, "); | ||
| 489 | break; | ||
| 490 | } | ||
| 491 | } | ||
| 492 | printf("\n};\n"); | ||
| 493 | |||
| 494 | printf("static const UC qpunbase[] = {"); | ||
| 495 | for (int i = 0; i < 256; i++) { | ||
| 496 | int c = qpunbase[i]; | ||
| 497 | printf("%d, ", c); | ||
| 498 | } | ||
| 499 | printf("\";\n"); | ||
| 370 | } | 500 | } |
| 501 | #endif | ||
| 371 | 502 | ||
| 372 | /*-------------------------------------------------------------------------*\ | 503 | /*-------------------------------------------------------------------------*\ |
| 373 | * Output one character in form =XX | 504 | * Output one character in form =XX |
| @@ -447,7 +578,6 @@ static size_t qppad(UC *input, size_t size, luaL_Buffer *buffer) | |||
| 447 | \*-------------------------------------------------------------------------*/ | 578 | \*-------------------------------------------------------------------------*/ |
| 448 | static int mime_global_qp(lua_State *L) | 579 | static int mime_global_qp(lua_State *L) |
| 449 | { | 580 | { |
| 450 | |||
| 451 | size_t asize = 0, isize = 0; | 581 | size_t asize = 0, isize = 0; |
| 452 | UC atom[3]; | 582 | UC atom[3]; |
| 453 | const UC *input = (const UC *) luaL_optlstring(L, 1, NULL, &isize); | 583 | const UC *input = (const UC *) luaL_optlstring(L, 1, NULL, &isize); |
| @@ -654,7 +784,7 @@ static int eolprocess(int c, int last, const char *marker, | |||
| 654 | \*-------------------------------------------------------------------------*/ | 784 | \*-------------------------------------------------------------------------*/ |
| 655 | static int mime_global_eol(lua_State *L) | 785 | static int mime_global_eol(lua_State *L) |
| 656 | { | 786 | { |
| 657 | int ctx = luaL_checkinteger(L, 1); | 787 | int ctx = (int) luaL_checkinteger(L, 1); |
| 658 | size_t isize = 0; | 788 | size_t isize = 0; |
| 659 | const char *input = luaL_optlstring(L, 2, NULL, &isize); | 789 | const char *input = luaL_optlstring(L, 2, NULL, &isize); |
| 660 | const char *last = input + isize; | 790 | const char *last = input + isize; |
| @@ -689,6 +819,7 @@ static size_t dot(int c, size_t state, luaL_Buffer *buffer) | |||
| 689 | case '.': | 819 | case '.': |
| 690 | if (state == 2) | 820 | if (state == 2) |
| 691 | luaL_addchar(buffer, '.'); | 821 | luaL_addchar(buffer, '.'); |
| 822 | /* Falls through. */ | ||
| 692 | default: | 823 | default: |
| 693 | return 0; | 824 | return 0; |
| 694 | } | 825 | } |
| @@ -8,7 +8,7 @@ | |||
| 8 | * and formatting conforming to RFC 2045. It is used by mime.lua, which | 8 | * and formatting conforming to RFC 2045. It is used by mime.lua, which |
| 9 | * provide a higher level interface to this functionality. | 9 | * provide a higher level interface to this functionality. |
| 10 | \*=========================================================================*/ | 10 | \*=========================================================================*/ |
| 11 | #include "lua.h" | 11 | #include "luasocket.h" |
| 12 | 12 | ||
| 13 | /*-------------------------------------------------------------------------*\ | 13 | /*-------------------------------------------------------------------------*\ |
| 14 | * Current MIME library version | 14 | * Current MIME library version |
| @@ -17,13 +17,6 @@ | |||
| 17 | #define MIME_COPYRIGHT "Copyright (C) 2004-2013 Diego Nehab" | 17 | #define MIME_COPYRIGHT "Copyright (C) 2004-2013 Diego Nehab" |
| 18 | #define MIME_AUTHORS "Diego Nehab" | 18 | #define MIME_AUTHORS "Diego Nehab" |
| 19 | 19 | ||
| 20 | /*-------------------------------------------------------------------------*\ | 20 | LUASOCKET_API int luaopen_mime_core(lua_State *L); |
| 21 | * This macro prefixes all exported API functions | ||
| 22 | \*-------------------------------------------------------------------------*/ | ||
| 23 | #ifndef MIME_API | ||
| 24 | #define MIME_API extern | ||
| 25 | #endif | ||
| 26 | |||
| 27 | MIME_API int luaopen_mime_core(lua_State *L); | ||
| 28 | 21 | ||
| 29 | #endif /* MIME_H */ | 22 | #endif /* MIME_H */ |
diff --git a/src/mime.lua b/src/mime.lua index 642cd9c..93539de 100644 --- a/src/mime.lua +++ b/src/mime.lua | |||
| @@ -10,8 +10,6 @@ | |||
| 10 | local base = _G | 10 | local base = _G |
| 11 | local ltn12 = require("ltn12") | 11 | local ltn12 = require("ltn12") |
| 12 | local mime = require("mime.core") | 12 | local mime = require("mime.core") |
| 13 | local io = require("io") | ||
| 14 | local string = require("string") | ||
| 15 | local _M = mime | 13 | local _M = mime |
| 16 | 14 | ||
| 17 | -- encode, decode and wrap algorithm tables | 15 | -- encode, decode and wrap algorithm tables |
| @@ -19,7 +17,7 @@ local encodet, decodet, wrapt = {},{},{} | |||
| 19 | 17 | ||
| 20 | _M.encodet = encodet | 18 | _M.encodet = encodet |
| 21 | _M.decodet = decodet | 19 | _M.decodet = decodet |
| 22 | _M.wrapt = wrapt | 20 | _M.wrapt = wrapt |
| 23 | 21 | ||
| 24 | -- creates a function that chooses a filter by name from a given table | 22 | -- creates a function that chooses a filter by name from a given table |
| 25 | local function choose(table) | 23 | local function choose(table) |
| @@ -28,7 +26,7 @@ local function choose(table) | |||
| 28 | name, opt1, opt2 = "default", name, opt1 | 26 | name, opt1, opt2 = "default", name, opt1 |
| 29 | end | 27 | end |
| 30 | local f = table[name or "nil"] | 28 | local f = table[name or "nil"] |
| 31 | if not f then | 29 | if not f then |
| 32 | base.error("unknown key (" .. base.tostring(name) .. ")", 3) | 30 | base.error("unknown key (" .. base.tostring(name) .. ")", 3) |
| 33 | else return f(opt1, opt2) end | 31 | else return f(opt1, opt2) end |
| 34 | end | 32 | end |
| @@ -53,13 +51,6 @@ decodet['quoted-printable'] = function() | |||
| 53 | return ltn12.filter.cycle(_M.unqp, "") | 51 | return ltn12.filter.cycle(_M.unqp, "") |
| 54 | end | 52 | end |
| 55 | 53 | ||
| 56 | local function format(chunk) | ||
| 57 | if chunk then | ||
| 58 | if chunk == "" then return "''" | ||
| 59 | else return string.len(chunk) end | ||
| 60 | else return "nil" end | ||
| 61 | end | ||
| 62 | |||
| 63 | -- define the line-wrap filters | 54 | -- define the line-wrap filters |
| 64 | wrapt['text'] = function(length) | 55 | wrapt['text'] = function(length) |
| 65 | length = length or 76 | 56 | length = length or 76 |
| @@ -87,4 +78,4 @@ function _M.stuff() | |||
| 87 | return ltn12.filter.cycle(_M.dot, 2) | 78 | return ltn12.filter.cycle(_M.dot, 2) |
| 88 | end | 79 | end |
| 89 | 80 | ||
| 90 | return _M \ No newline at end of file | 81 | return _M |
diff --git a/src/options.c b/src/options.c index 20f4c28..9dea6bd 100644 --- a/src/options.c +++ b/src/options.c | |||
| @@ -2,14 +2,11 @@ | |||
| 2 | * Common option interface | 2 | * Common option interface |
| 3 | * LuaSocket toolkit | 3 | * LuaSocket toolkit |
| 4 | \*=========================================================================*/ | 4 | \*=========================================================================*/ |
| 5 | #include <string.h> | 5 | #include "luasocket.h" |
| 6 | |||
| 7 | #include "lauxlib.h" | ||
| 8 | |||
| 9 | #include "auxiliar.h" | 6 | #include "auxiliar.h" |
| 10 | #include "options.h" | 7 | #include "options.h" |
| 11 | #include "inet.h" | 8 | #include "inet.h" |
| 12 | 9 | #include <string.h> | |
| 13 | 10 | ||
| 14 | /*=========================================================================*\ | 11 | /*=========================================================================*\ |
| 15 | * Internal functions prototypes | 12 | * Internal functions prototypes |
| @@ -37,7 +34,7 @@ int opt_meth_setoption(lua_State *L, p_opt opt, p_socket ps) | |||
| 37 | while (opt->name && strcmp(name, opt->name)) | 34 | while (opt->name && strcmp(name, opt->name)) |
| 38 | opt++; | 35 | opt++; |
| 39 | if (!opt->func) { | 36 | if (!opt->func) { |
| 40 | char msg[45]; | 37 | char msg[57]; |
| 41 | sprintf(msg, "unsupported option `%.35s'", name); | 38 | sprintf(msg, "unsupported option `%.35s'", name); |
| 42 | luaL_argerror(L, 2, msg); | 39 | luaL_argerror(L, 2, msg); |
| 43 | } | 40 | } |
| @@ -50,13 +47,41 @@ int opt_meth_getoption(lua_State *L, p_opt opt, p_socket ps) | |||
| 50 | while (opt->name && strcmp(name, opt->name)) | 47 | while (opt->name && strcmp(name, opt->name)) |
| 51 | opt++; | 48 | opt++; |
| 52 | if (!opt->func) { | 49 | if (!opt->func) { |
| 53 | char msg[45]; | 50 | char msg[57]; |
| 54 | sprintf(msg, "unsupported option `%.35s'", name); | 51 | sprintf(msg, "unsupported option `%.35s'", name); |
| 55 | luaL_argerror(L, 2, msg); | 52 | luaL_argerror(L, 2, msg); |
| 56 | } | 53 | } |
| 57 | return opt->func(L, ps); | 54 | return opt->func(L, ps); |
| 58 | } | 55 | } |
| 59 | 56 | ||
| 57 | /*------------------------------------------------------*/ | ||
| 58 | /* binds socket to network interface */ | ||
| 59 | int opt_set_bindtodevice(lua_State *L, p_socket ps) | ||
| 60 | { | ||
| 61 | #ifndef SO_BINDTODEVICE | ||
| 62 | return luaL_error(L, "SO_BINDTODEVICE is not supported on this operating system"); | ||
| 63 | #else | ||
| 64 | const char *dev = luaL_checkstring(L, 3); | ||
| 65 | return opt_set(L, ps, SOL_SOCKET, SO_BINDTODEVICE, (char*)dev, strlen(dev)+1); | ||
| 66 | #endif | ||
| 67 | } | ||
| 68 | |||
| 69 | int opt_get_bindtodevice(lua_State *L, p_socket ps) | ||
| 70 | { | ||
| 71 | #ifndef SO_BINDTODEVICE | ||
| 72 | return luaL_error(L, "SO_BINDTODEVICE is not supported on this operating system"); | ||
| 73 | #else | ||
| 74 | char dev[IFNAMSIZ]; | ||
| 75 | int len = sizeof(dev); | ||
| 76 | int err = opt_get(L, ps, SOL_SOCKET, SO_BINDTODEVICE, &dev, &len); | ||
| 77 | if (err) | ||
| 78 | return err; | ||
| 79 | lua_pushstring(L, dev); | ||
| 80 | return 1; | ||
| 81 | #endif | ||
| 82 | } | ||
| 83 | |||
| 84 | /*------------------------------------------------------*/ | ||
| 60 | /* enables reuse of local address */ | 85 | /* enables reuse of local address */ |
| 61 | int opt_set_reuseaddr(lua_State *L, p_socket ps) | 86 | int opt_set_reuseaddr(lua_State *L, p_socket ps) |
| 62 | { | 87 | { |
| @@ -68,6 +93,7 @@ int opt_get_reuseaddr(lua_State *L, p_socket ps) | |||
| 68 | return opt_getboolean(L, ps, SOL_SOCKET, SO_REUSEADDR); | 93 | return opt_getboolean(L, ps, SOL_SOCKET, SO_REUSEADDR); |
| 69 | } | 94 | } |
| 70 | 95 | ||
| 96 | /*------------------------------------------------------*/ | ||
| 71 | /* enables reuse of local port */ | 97 | /* enables reuse of local port */ |
| 72 | int opt_set_reuseport(lua_State *L, p_socket ps) | 98 | int opt_set_reuseport(lua_State *L, p_socket ps) |
| 73 | { | 99 | { |
| @@ -79,7 +105,8 @@ int opt_get_reuseport(lua_State *L, p_socket ps) | |||
| 79 | return opt_getboolean(L, ps, SOL_SOCKET, SO_REUSEPORT); | 105 | return opt_getboolean(L, ps, SOL_SOCKET, SO_REUSEPORT); |
| 80 | } | 106 | } |
| 81 | 107 | ||
| 82 | /* disables the Naggle algorithm */ | 108 | /*------------------------------------------------------*/ |
| 109 | /* disables the Nagle algorithm */ | ||
| 83 | int opt_set_tcp_nodelay(lua_State *L, p_socket ps) | 110 | int opt_set_tcp_nodelay(lua_State *L, p_socket ps) |
| 84 | { | 111 | { |
| 85 | return opt_setboolean(L, ps, IPPROTO_TCP, TCP_NODELAY); | 112 | return opt_setboolean(L, ps, IPPROTO_TCP, TCP_NODELAY); |
| @@ -90,6 +117,52 @@ int opt_get_tcp_nodelay(lua_State *L, p_socket ps) | |||
| 90 | return opt_getboolean(L, ps, IPPROTO_TCP, TCP_NODELAY); | 117 | return opt_getboolean(L, ps, IPPROTO_TCP, TCP_NODELAY); |
| 91 | } | 118 | } |
| 92 | 119 | ||
| 120 | /*------------------------------------------------------*/ | ||
| 121 | #ifdef TCP_KEEPIDLE | ||
| 122 | |||
| 123 | int opt_get_tcp_keepidle(lua_State *L, p_socket ps) | ||
| 124 | { | ||
| 125 | return opt_getint(L, ps, IPPROTO_TCP, TCP_KEEPIDLE); | ||
| 126 | } | ||
| 127 | |||
| 128 | int opt_set_tcp_keepidle(lua_State *L, p_socket ps) | ||
| 129 | { | ||
| 130 | return opt_setint(L, ps, IPPROTO_TCP, TCP_KEEPIDLE); | ||
| 131 | } | ||
| 132 | |||
| 133 | #endif | ||
| 134 | |||
| 135 | /*------------------------------------------------------*/ | ||
| 136 | #ifdef TCP_KEEPCNT | ||
| 137 | |||
| 138 | int opt_get_tcp_keepcnt(lua_State *L, p_socket ps) | ||
| 139 | { | ||
| 140 | return opt_getint(L, ps, IPPROTO_TCP, TCP_KEEPCNT); | ||
| 141 | } | ||
| 142 | |||
| 143 | int opt_set_tcp_keepcnt(lua_State *L, p_socket ps) | ||
| 144 | { | ||
| 145 | return opt_setint(L, ps, IPPROTO_TCP, TCP_KEEPCNT); | ||
| 146 | } | ||
| 147 | |||
| 148 | #endif | ||
| 149 | |||
| 150 | /*------------------------------------------------------*/ | ||
| 151 | #ifdef TCP_KEEPINTVL | ||
| 152 | |||
| 153 | int opt_get_tcp_keepintvl(lua_State *L, p_socket ps) | ||
| 154 | { | ||
| 155 | return opt_getint(L, ps, IPPROTO_TCP, TCP_KEEPINTVL); | ||
| 156 | } | ||
| 157 | |||
| 158 | int opt_set_tcp_keepintvl(lua_State *L, p_socket ps) | ||
| 159 | { | ||
| 160 | return opt_setint(L, ps, IPPROTO_TCP, TCP_KEEPINTVL); | ||
| 161 | } | ||
| 162 | |||
| 163 | #endif | ||
| 164 | |||
| 165 | /*------------------------------------------------------*/ | ||
| 93 | int opt_set_keepalive(lua_State *L, p_socket ps) | 166 | int opt_set_keepalive(lua_State *L, p_socket ps) |
| 94 | { | 167 | { |
| 95 | return opt_setboolean(L, ps, SOL_SOCKET, SO_KEEPALIVE); | 168 | return opt_setboolean(L, ps, SOL_SOCKET, SO_KEEPALIVE); |
| @@ -100,6 +173,7 @@ int opt_get_keepalive(lua_State *L, p_socket ps) | |||
| 100 | return opt_getboolean(L, ps, SOL_SOCKET, SO_KEEPALIVE); | 173 | return opt_getboolean(L, ps, SOL_SOCKET, SO_KEEPALIVE); |
| 101 | } | 174 | } |
| 102 | 175 | ||
| 176 | /*------------------------------------------------------*/ | ||
| 103 | int opt_set_dontroute(lua_State *L, p_socket ps) | 177 | int opt_set_dontroute(lua_State *L, p_socket ps) |
| 104 | { | 178 | { |
| 105 | return opt_setboolean(L, ps, SOL_SOCKET, SO_DONTROUTE); | 179 | return opt_setboolean(L, ps, SOL_SOCKET, SO_DONTROUTE); |
| @@ -110,6 +184,7 @@ int opt_get_dontroute(lua_State *L, p_socket ps) | |||
| 110 | return opt_getboolean(L, ps, SOL_SOCKET, SO_DONTROUTE); | 184 | return opt_getboolean(L, ps, SOL_SOCKET, SO_DONTROUTE); |
| 111 | } | 185 | } |
| 112 | 186 | ||
| 187 | /*------------------------------------------------------*/ | ||
| 113 | int opt_set_broadcast(lua_State *L, p_socket ps) | 188 | int opt_set_broadcast(lua_State *L, p_socket ps) |
| 114 | { | 189 | { |
| 115 | return opt_setboolean(L, ps, SOL_SOCKET, SO_BROADCAST); | 190 | return opt_setboolean(L, ps, SOL_SOCKET, SO_BROADCAST); |
| @@ -120,6 +195,54 @@ int opt_get_broadcast(lua_State *L, p_socket ps) | |||
| 120 | return opt_getboolean(L, ps, SOL_SOCKET, SO_BROADCAST); | 195 | return opt_getboolean(L, ps, SOL_SOCKET, SO_BROADCAST); |
| 121 | } | 196 | } |
| 122 | 197 | ||
| 198 | /*------------------------------------------------------*/ | ||
| 199 | int opt_set_recv_buf_size(lua_State *L, p_socket ps) | ||
| 200 | { | ||
| 201 | return opt_setint(L, ps, SOL_SOCKET, SO_RCVBUF); | ||
| 202 | } | ||
| 203 | |||
| 204 | int opt_get_recv_buf_size(lua_State *L, p_socket ps) | ||
| 205 | { | ||
| 206 | return opt_getint(L, ps, SOL_SOCKET, SO_RCVBUF); | ||
| 207 | } | ||
| 208 | |||
| 209 | /*------------------------------------------------------*/ | ||
| 210 | int opt_get_send_buf_size(lua_State *L, p_socket ps) | ||
| 211 | { | ||
| 212 | return opt_getint(L, ps, SOL_SOCKET, SO_SNDBUF); | ||
| 213 | } | ||
| 214 | |||
| 215 | int opt_set_send_buf_size(lua_State *L, p_socket ps) | ||
| 216 | { | ||
| 217 | return opt_setint(L, ps, SOL_SOCKET, SO_SNDBUF); | ||
| 218 | } | ||
| 219 | |||
| 220 | /*------------------------------------------------------*/ | ||
| 221 | |||
| 222 | #ifdef TCP_FASTOPEN | ||
| 223 | int opt_set_tcp_fastopen(lua_State *L, p_socket ps) | ||
| 224 | { | ||
| 225 | return opt_setint(L, ps, IPPROTO_TCP, TCP_FASTOPEN); | ||
| 226 | } | ||
| 227 | #endif | ||
| 228 | |||
| 229 | #ifdef TCP_FASTOPEN_CONNECT | ||
| 230 | int opt_set_tcp_fastopen_connect(lua_State *L, p_socket ps) | ||
| 231 | { | ||
| 232 | return opt_setint(L, ps, IPPROTO_TCP, TCP_FASTOPEN_CONNECT); | ||
| 233 | } | ||
| 234 | #endif | ||
| 235 | |||
| 236 | /*------------------------------------------------------*/ | ||
| 237 | |||
| 238 | #ifdef TCP_DEFER_ACCEPT | ||
| 239 | int opt_set_tcp_defer_accept(lua_State *L, p_socket ps) | ||
| 240 | { | ||
| 241 | return opt_setint(L, ps, IPPROTO_TCP, TCP_DEFER_ACCEPT); | ||
| 242 | } | ||
| 243 | #endif | ||
| 244 | |||
| 245 | /*------------------------------------------------------*/ | ||
| 123 | int opt_set_ip6_unicast_hops(lua_State *L, p_socket ps) | 246 | int opt_set_ip6_unicast_hops(lua_State *L, p_socket ps) |
| 124 | { | 247 | { |
| 125 | return opt_setint(L, ps, IPPROTO_IPV6, IPV6_UNICAST_HOPS); | 248 | return opt_setint(L, ps, IPPROTO_IPV6, IPV6_UNICAST_HOPS); |
| @@ -130,6 +253,7 @@ int opt_get_ip6_unicast_hops(lua_State *L, p_socket ps) | |||
| 130 | return opt_getint(L, ps, IPPROTO_IPV6, IPV6_UNICAST_HOPS); | 253 | return opt_getint(L, ps, IPPROTO_IPV6, IPV6_UNICAST_HOPS); |
| 131 | } | 254 | } |
| 132 | 255 | ||
| 256 | /*------------------------------------------------------*/ | ||
| 133 | int opt_set_ip6_multicast_hops(lua_State *L, p_socket ps) | 257 | int opt_set_ip6_multicast_hops(lua_State *L, p_socket ps) |
| 134 | { | 258 | { |
| 135 | return opt_setint(L, ps, IPPROTO_IPV6, IPV6_MULTICAST_HOPS); | 259 | return opt_setint(L, ps, IPPROTO_IPV6, IPV6_MULTICAST_HOPS); |
| @@ -140,6 +264,7 @@ int opt_get_ip6_multicast_hops(lua_State *L, p_socket ps) | |||
| 140 | return opt_getint(L, ps, IPPROTO_IPV6, IPV6_MULTICAST_HOPS); | 264 | return opt_getint(L, ps, IPPROTO_IPV6, IPV6_MULTICAST_HOPS); |
| 141 | } | 265 | } |
| 142 | 266 | ||
| 267 | /*------------------------------------------------------*/ | ||
| 143 | int opt_set_ip_multicast_loop(lua_State *L, p_socket ps) | 268 | int opt_set_ip_multicast_loop(lua_State *L, p_socket ps) |
| 144 | { | 269 | { |
| 145 | return opt_setboolean(L, ps, IPPROTO_IP, IP_MULTICAST_LOOP); | 270 | return opt_setboolean(L, ps, IPPROTO_IP, IP_MULTICAST_LOOP); |
| @@ -150,6 +275,7 @@ int opt_get_ip_multicast_loop(lua_State *L, p_socket ps) | |||
| 150 | return opt_getboolean(L, ps, IPPROTO_IP, IP_MULTICAST_LOOP); | 275 | return opt_getboolean(L, ps, IPPROTO_IP, IP_MULTICAST_LOOP); |
| 151 | } | 276 | } |
| 152 | 277 | ||
| 278 | /*------------------------------------------------------*/ | ||
| 153 | int opt_set_ip6_multicast_loop(lua_State *L, p_socket ps) | 279 | int opt_set_ip6_multicast_loop(lua_State *L, p_socket ps) |
| 154 | { | 280 | { |
| 155 | return opt_setboolean(L, ps, IPPROTO_IPV6, IPV6_MULTICAST_LOOP); | 281 | return opt_setboolean(L, ps, IPPROTO_IPV6, IPV6_MULTICAST_LOOP); |
| @@ -160,6 +286,7 @@ int opt_get_ip6_multicast_loop(lua_State *L, p_socket ps) | |||
| 160 | return opt_getboolean(L, ps, IPPROTO_IPV6, IPV6_MULTICAST_LOOP); | 286 | return opt_getboolean(L, ps, IPPROTO_IPV6, IPV6_MULTICAST_LOOP); |
| 161 | } | 287 | } |
| 162 | 288 | ||
| 289 | /*------------------------------------------------------*/ | ||
| 163 | int opt_set_linger(lua_State *L, p_socket ps) | 290 | int opt_set_linger(lua_State *L, p_socket ps) |
| 164 | { | 291 | { |
| 165 | struct linger li; /* obj, name, table */ | 292 | struct linger li; /* obj, name, table */ |
| @@ -192,11 +319,13 @@ int opt_get_linger(lua_State *L, p_socket ps) | |||
| 192 | return 1; | 319 | return 1; |
| 193 | } | 320 | } |
| 194 | 321 | ||
| 322 | /*------------------------------------------------------*/ | ||
| 195 | int opt_set_ip_multicast_ttl(lua_State *L, p_socket ps) | 323 | int opt_set_ip_multicast_ttl(lua_State *L, p_socket ps) |
| 196 | { | 324 | { |
| 197 | return opt_setint(L, ps, IPPROTO_IP, IP_MULTICAST_TTL); | 325 | return opt_setint(L, ps, IPPROTO_IP, IP_MULTICAST_TTL); |
| 198 | } | 326 | } |
| 199 | 327 | ||
| 328 | /*------------------------------------------------------*/ | ||
| 200 | int opt_set_ip_multicast_if(lua_State *L, p_socket ps) | 329 | int opt_set_ip_multicast_if(lua_State *L, p_socket ps) |
| 201 | { | 330 | { |
| 202 | const char *address = luaL_checkstring(L, 3); /* obj, name, ip */ | 331 | const char *address = luaL_checkstring(L, 3); /* obj, name, ip */ |
| @@ -221,6 +350,7 @@ int opt_get_ip_multicast_if(lua_State *L, p_socket ps) | |||
| 221 | return 1; | 350 | return 1; |
| 222 | } | 351 | } |
| 223 | 352 | ||
| 353 | /*------------------------------------------------------*/ | ||
| 224 | int opt_set_ip_add_membership(lua_State *L, p_socket ps) | 354 | int opt_set_ip_add_membership(lua_State *L, p_socket ps) |
| 225 | { | 355 | { |
| 226 | return opt_setmembership(L, ps, IPPROTO_IP, IP_ADD_MEMBERSHIP); | 356 | return opt_setmembership(L, ps, IPPROTO_IP, IP_ADD_MEMBERSHIP); |
| @@ -231,6 +361,7 @@ int opt_set_ip_drop_membersip(lua_State *L, p_socket ps) | |||
| 231 | return opt_setmembership(L, ps, IPPROTO_IP, IP_DROP_MEMBERSHIP); | 361 | return opt_setmembership(L, ps, IPPROTO_IP, IP_DROP_MEMBERSHIP); |
| 232 | } | 362 | } |
| 233 | 363 | ||
| 364 | /*------------------------------------------------------*/ | ||
| 234 | int opt_set_ip6_add_membership(lua_State *L, p_socket ps) | 365 | int opt_set_ip6_add_membership(lua_State *L, p_socket ps) |
| 235 | { | 366 | { |
| 236 | return opt_ip6_setmembership(L, ps, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP); | 367 | return opt_ip6_setmembership(L, ps, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP); |
| @@ -241,6 +372,7 @@ int opt_set_ip6_drop_membersip(lua_State *L, p_socket ps) | |||
| 241 | return opt_ip6_setmembership(L, ps, IPPROTO_IPV6, IPV6_DROP_MEMBERSHIP); | 372 | return opt_ip6_setmembership(L, ps, IPPROTO_IPV6, IPV6_DROP_MEMBERSHIP); |
| 242 | } | 373 | } |
| 243 | 374 | ||
| 375 | /*------------------------------------------------------*/ | ||
| 244 | int opt_get_ip6_v6only(lua_State *L, p_socket ps) | 376 | int opt_get_ip6_v6only(lua_State *L, p_socket ps) |
| 245 | { | 377 | { |
| 246 | return opt_getboolean(L, ps, IPPROTO_IPV6, IPV6_V6ONLY); | 378 | return opt_getboolean(L, ps, IPPROTO_IPV6, IPV6_V6ONLY); |
| @@ -251,6 +383,20 @@ int opt_set_ip6_v6only(lua_State *L, p_socket ps) | |||
| 251 | return opt_setboolean(L, ps, IPPROTO_IPV6, IPV6_V6ONLY); | 383 | return opt_setboolean(L, ps, IPPROTO_IPV6, IPV6_V6ONLY); |
| 252 | } | 384 | } |
| 253 | 385 | ||
| 386 | /*------------------------------------------------------*/ | ||
| 387 | int opt_get_error(lua_State *L, p_socket ps) | ||
| 388 | { | ||
| 389 | int val = 0; | ||
| 390 | socklen_t len = sizeof(val); | ||
| 391 | if (getsockopt(*ps, SOL_SOCKET, SO_ERROR, (char *) &val, &len) < 0) { | ||
| 392 | lua_pushnil(L); | ||
| 393 | lua_pushstring(L, "getsockopt failed"); | ||
| 394 | return 2; | ||
| 395 | } | ||
| 396 | lua_pushstring(L, socket_strerror(val)); | ||
| 397 | return 1; | ||
| 398 | } | ||
| 399 | |||
| 254 | /*=========================================================================*\ | 400 | /*=========================================================================*\ |
| 255 | * Auxiliar functions | 401 | * Auxiliar functions |
| 256 | \*=========================================================================*/ | 402 | \*=========================================================================*/ |
| @@ -337,19 +483,6 @@ static int opt_getboolean(lua_State *L, p_socket ps, int level, int name) | |||
| 337 | return 1; | 483 | return 1; |
| 338 | } | 484 | } |
| 339 | 485 | ||
| 340 | int opt_get_error(lua_State *L, p_socket ps) | ||
| 341 | { | ||
| 342 | int val = 0; | ||
| 343 | socklen_t len = sizeof(val); | ||
| 344 | if (getsockopt(*ps, SOL_SOCKET, SO_ERROR, (char *) &val, &len) < 0) { | ||
| 345 | lua_pushnil(L); | ||
| 346 | lua_pushstring(L, "getsockopt failed"); | ||
| 347 | return 2; | ||
| 348 | } | ||
| 349 | lua_pushstring(L, socket_strerror(val)); | ||
| 350 | return 1; | ||
| 351 | } | ||
| 352 | |||
| 353 | static int opt_setboolean(lua_State *L, p_socket ps, int level, int name) | 486 | static int opt_setboolean(lua_State *L, p_socket ps, int level, int name) |
| 354 | { | 487 | { |
| 355 | int val = auxiliar_checkboolean(L, 3); /* obj, name, bool */ | 488 | int val = auxiliar_checkboolean(L, 3); /* obj, name, bool */ |
diff --git a/src/options.h b/src/options.h index ad1b00d..26d6f02 100644 --- a/src/options.h +++ b/src/options.h | |||
| @@ -8,7 +8,7 @@ | |||
| 8 | * modules UDP and TCP. | 8 | * modules UDP and TCP. |
| 9 | \*=========================================================================*/ | 9 | \*=========================================================================*/ |
| 10 | 10 | ||
| 11 | #include "lua.h" | 11 | #include "luasocket.h" |
| 12 | #include "socket.h" | 12 | #include "socket.h" |
| 13 | 13 | ||
| 14 | /* option registry */ | 14 | /* option registry */ |
| @@ -18,45 +18,99 @@ typedef struct t_opt { | |||
| 18 | } t_opt; | 18 | } t_opt; |
| 19 | typedef t_opt *p_opt; | 19 | typedef t_opt *p_opt; |
| 20 | 20 | ||
| 21 | /* supported options for setoption */ | 21 | #ifndef _WIN32 |
| 22 | int opt_set_dontroute(lua_State *L, p_socket ps); | 22 | #pragma GCC visibility push(hidden) |
| 23 | int opt_set_broadcast(lua_State *L, p_socket ps); | 23 | #endif |
| 24 | |||
| 25 | int opt_meth_setoption(lua_State *L, p_opt opt, p_socket ps); | ||
| 26 | int opt_meth_getoption(lua_State *L, p_opt opt, p_socket ps); | ||
| 27 | |||
| 24 | int opt_set_reuseaddr(lua_State *L, p_socket ps); | 28 | int opt_set_reuseaddr(lua_State *L, p_socket ps); |
| 29 | int opt_get_reuseaddr(lua_State *L, p_socket ps); | ||
| 30 | |||
| 31 | int opt_set_reuseport(lua_State *L, p_socket ps); | ||
| 32 | int opt_get_reuseport(lua_State *L, p_socket ps); | ||
| 33 | |||
| 25 | int opt_set_tcp_nodelay(lua_State *L, p_socket ps); | 34 | int opt_set_tcp_nodelay(lua_State *L, p_socket ps); |
| 35 | int opt_get_tcp_nodelay(lua_State *L, p_socket ps); | ||
| 36 | |||
| 37 | #ifdef TCP_KEEPIDLE | ||
| 38 | int opt_set_tcp_keepidle(lua_State *L, p_socket ps); | ||
| 39 | int opt_get_tcp_keepidle(lua_State *L, p_socket ps); | ||
| 40 | #endif | ||
| 41 | |||
| 42 | #ifdef TCP_KEEPCNT | ||
| 43 | int opt_set_tcp_keepcnt(lua_State *L, p_socket ps); | ||
| 44 | int opt_get_tcp_keepcnt(lua_State *L, p_socket ps); | ||
| 45 | #endif | ||
| 46 | |||
| 47 | #ifdef TCP_KEEPINTVL | ||
| 48 | int opt_set_tcp_keepintvl(lua_State *L, p_socket ps); | ||
| 49 | int opt_get_tcp_keepintvl(lua_State *L, p_socket ps); | ||
| 50 | #endif | ||
| 51 | |||
| 52 | #ifdef TCP_DEFER_ACCEPT | ||
| 53 | int opt_set_tcp_defer_accept(lua_State *L, p_socket ps); | ||
| 54 | #endif | ||
| 55 | |||
| 56 | int opt_set_bindtodevice(lua_State *L, p_socket ps); | ||
| 57 | int opt_get_bindtodevice(lua_State *L, p_socket ps); | ||
| 58 | |||
| 26 | int opt_set_keepalive(lua_State *L, p_socket ps); | 59 | int opt_set_keepalive(lua_State *L, p_socket ps); |
| 60 | int opt_get_keepalive(lua_State *L, p_socket ps); | ||
| 61 | |||
| 62 | int opt_set_dontroute(lua_State *L, p_socket ps); | ||
| 63 | int opt_get_dontroute(lua_State *L, p_socket ps); | ||
| 64 | |||
| 65 | int opt_set_broadcast(lua_State *L, p_socket ps); | ||
| 66 | int opt_get_broadcast(lua_State *L, p_socket ps); | ||
| 67 | |||
| 68 | int opt_set_recv_buf_size(lua_State *L, p_socket ps); | ||
| 69 | int opt_get_recv_buf_size(lua_State *L, p_socket ps); | ||
| 70 | |||
| 71 | int opt_set_send_buf_size(lua_State *L, p_socket ps); | ||
| 72 | int opt_get_send_buf_size(lua_State *L, p_socket ps); | ||
| 73 | |||
| 74 | #ifdef TCP_FASTOPEN | ||
| 75 | int opt_set_tcp_fastopen(lua_State *L, p_socket ps); | ||
| 76 | #endif | ||
| 77 | #ifdef TCP_FASTOPEN_CONNECT | ||
| 78 | int opt_set_tcp_fastopen_connect(lua_State *L, p_socket ps); | ||
| 79 | #endif | ||
| 80 | |||
| 81 | int opt_set_ip6_unicast_hops(lua_State *L, p_socket ps); | ||
| 82 | int opt_get_ip6_unicast_hops(lua_State *L, p_socket ps); | ||
| 83 | |||
| 84 | int opt_set_ip6_multicast_hops(lua_State *L, p_socket ps); | ||
| 85 | int opt_get_ip6_multicast_hops(lua_State *L, p_socket ps); | ||
| 86 | |||
| 87 | int opt_set_ip_multicast_loop(lua_State *L, p_socket ps); | ||
| 88 | int opt_get_ip_multicast_loop(lua_State *L, p_socket ps); | ||
| 89 | |||
| 90 | int opt_set_ip6_multicast_loop(lua_State *L, p_socket ps); | ||
| 91 | int opt_get_ip6_multicast_loop(lua_State *L, p_socket ps); | ||
| 92 | |||
| 27 | int opt_set_linger(lua_State *L, p_socket ps); | 93 | int opt_set_linger(lua_State *L, p_socket ps); |
| 28 | int opt_set_reuseaddr(lua_State *L, p_socket ps); | 94 | int opt_get_linger(lua_State *L, p_socket ps); |
| 29 | int opt_set_reuseport(lua_State *L, p_socket ps); | 95 | |
| 30 | int opt_set_ip_multicast_if(lua_State *L, p_socket ps); | ||
| 31 | int opt_set_ip_multicast_ttl(lua_State *L, p_socket ps); | 96 | int opt_set_ip_multicast_ttl(lua_State *L, p_socket ps); |
| 32 | int opt_set_ip_multicast_loop(lua_State *L, p_socket ps); | 97 | |
| 98 | int opt_set_ip_multicast_if(lua_State *L, p_socket ps); | ||
| 99 | int opt_get_ip_multicast_if(lua_State *L, p_socket ps); | ||
| 100 | |||
| 33 | int opt_set_ip_add_membership(lua_State *L, p_socket ps); | 101 | int opt_set_ip_add_membership(lua_State *L, p_socket ps); |
| 34 | int opt_set_ip_drop_membersip(lua_State *L, p_socket ps); | 102 | int opt_set_ip_drop_membersip(lua_State *L, p_socket ps); |
| 35 | int opt_set_ip6_unicast_hops(lua_State *L, p_socket ps); | 103 | |
| 36 | int opt_set_ip6_multicast_hops(lua_State *L, p_socket ps); | ||
| 37 | int opt_set_ip6_multicast_loop(lua_State *L, p_socket ps); | ||
| 38 | int opt_set_ip6_add_membership(lua_State *L, p_socket ps); | 104 | int opt_set_ip6_add_membership(lua_State *L, p_socket ps); |
| 39 | int opt_set_ip6_drop_membersip(lua_State *L, p_socket ps); | 105 | int opt_set_ip6_drop_membersip(lua_State *L, p_socket ps); |
| 106 | |||
| 40 | int opt_set_ip6_v6only(lua_State *L, p_socket ps); | 107 | int opt_set_ip6_v6only(lua_State *L, p_socket ps); |
| 108 | int opt_get_ip6_v6only(lua_State *L, p_socket ps); | ||
| 41 | 109 | ||
| 42 | /* supported options for getoption */ | ||
| 43 | int opt_get_dontroute(lua_State *L, p_socket ps); | ||
| 44 | int opt_get_broadcast(lua_State *L, p_socket ps); | ||
| 45 | int opt_get_reuseaddr(lua_State *L, p_socket ps); | ||
| 46 | int opt_get_tcp_nodelay(lua_State *L, p_socket ps); | ||
| 47 | int opt_get_keepalive(lua_State *L, p_socket ps); | ||
| 48 | int opt_get_linger(lua_State *L, p_socket ps); | ||
| 49 | int opt_get_ip_multicast_loop(lua_State *L, p_socket ps); | ||
| 50 | int opt_get_ip_multicast_if(lua_State *L, p_socket ps); | ||
| 51 | int opt_get_error(lua_State *L, p_socket ps); | 110 | int opt_get_error(lua_State *L, p_socket ps); |
| 52 | int opt_get_ip6_multicast_loop(lua_State *L, p_socket ps); | ||
| 53 | int opt_get_ip6_multicast_hops(lua_State *L, p_socket ps); | ||
| 54 | int opt_get_ip6_unicast_hops(lua_State *L, p_socket ps); | ||
| 55 | int opt_get_ip6_v6only(lua_State *L, p_socket ps); | ||
| 56 | int opt_get_reuseport(lua_State *L, p_socket ps); | ||
| 57 | 111 | ||
| 58 | /* invokes the appropriate option handler */ | 112 | #ifndef _WIN32 |
| 59 | int opt_meth_setoption(lua_State *L, p_opt opt, p_socket ps); | 113 | #pragma GCC visibility pop |
| 60 | int opt_meth_getoption(lua_State *L, p_opt opt, p_socket ps); | 114 | #endif |
| 61 | 115 | ||
| 62 | #endif | 116 | #endif |
diff --git a/src/select.c b/src/select.c index d14c40a..bb47c45 100644 --- a/src/select.c +++ b/src/select.c | |||
| @@ -2,16 +2,14 @@ | |||
| 2 | * Select implementation | 2 | * Select implementation |
| 3 | * LuaSocket toolkit | 3 | * LuaSocket toolkit |
| 4 | \*=========================================================================*/ | 4 | \*=========================================================================*/ |
| 5 | #include <string.h> | 5 | #include "luasocket.h" |
| 6 | |||
| 7 | #include "lua.h" | ||
| 8 | #include "lauxlib.h" | ||
| 9 | #include "compat.h" | ||
| 10 | 6 | ||
| 11 | #include "socket.h" | 7 | #include "socket.h" |
| 12 | #include "timeout.h" | 8 | #include "timeout.h" |
| 13 | #include "select.h" | 9 | #include "select.h" |
| 14 | 10 | ||
| 11 | #include <string.h> | ||
| 12 | |||
| 15 | /*=========================================================================*\ | 13 | /*=========================================================================*\ |
| 16 | * Internal function prototypes. | 14 | * Internal function prototypes. |
| 17 | \*=========================================================================*/ | 15 | \*=========================================================================*/ |
| @@ -31,15 +29,15 @@ static luaL_Reg func[] = { | |||
| 31 | {NULL, NULL} | 29 | {NULL, NULL} |
| 32 | }; | 30 | }; |
| 33 | 31 | ||
| 34 | /*=========================================================================*\ | ||
| 35 | * Exported functions | ||
| 36 | \*=========================================================================*/ | ||
| 37 | /*-------------------------------------------------------------------------*\ | 32 | /*-------------------------------------------------------------------------*\ |
| 38 | * Initializes module | 33 | * Initializes module |
| 39 | \*-------------------------------------------------------------------------*/ | 34 | \*-------------------------------------------------------------------------*/ |
| 40 | int select_open(lua_State *L) { | 35 | int select_open(lua_State *L) { |
| 41 | lua_pushstring(L, "_SETSIZE"); | 36 | lua_pushstring(L, "_SETSIZE"); |
| 42 | lua_pushnumber(L, FD_SETSIZE); | 37 | lua_pushinteger(L, FD_SETSIZE); |
| 38 | lua_rawset(L, -3); | ||
| 39 | lua_pushstring(L, "_SOCKETINVALID"); | ||
| 40 | lua_pushinteger(L, SOCKET_INVALID); | ||
| 43 | lua_rawset(L, -3); | 41 | lua_rawset(L, -3); |
| 44 | luaL_setfuncs(L, func, 0); | 42 | luaL_setfuncs(L, func, 0); |
| 45 | return 0; | 43 | return 0; |
| @@ -214,4 +212,3 @@ static void make_assoc(lua_State *L, int tab) { | |||
| 214 | i = i+1; | 212 | i = i+1; |
| 215 | } | 213 | } |
| 216 | } | 214 | } |
| 217 | |||
diff --git a/src/select.h b/src/select.h index 8750200..5d45fe7 100644 --- a/src/select.h +++ b/src/select.h | |||
| @@ -10,6 +10,14 @@ | |||
| 10 | * true if there is data ready for reading (required for buffered input). | 10 | * true if there is data ready for reading (required for buffered input). |
| 11 | \*=========================================================================*/ | 11 | \*=========================================================================*/ |
| 12 | 12 | ||
| 13 | #ifndef _WIN32 | ||
| 14 | #pragma GCC visibility push(hidden) | ||
| 15 | #endif | ||
| 16 | |||
| 13 | int select_open(lua_State *L); | 17 | int select_open(lua_State *L); |
| 14 | 18 | ||
| 19 | #ifndef _WIN32 | ||
| 20 | #pragma GCC visibility pop | ||
| 21 | #endif | ||
| 22 | |||
| 15 | #endif /* SELECT_H */ | 23 | #endif /* SELECT_H */ |
diff --git a/src/serial.c b/src/serial.c index 7bdb21c..21485d3 100644 --- a/src/serial.c +++ b/src/serial.c | |||
| @@ -2,15 +2,14 @@ | |||
| 2 | * Serial stream | 2 | * Serial stream |
| 3 | * LuaSocket toolkit | 3 | * LuaSocket toolkit |
| 4 | \*=========================================================================*/ | 4 | \*=========================================================================*/ |
| 5 | #include <string.h> | 5 | #include "luasocket.h" |
| 6 | |||
| 7 | #include "lua.h" | ||
| 8 | #include "lauxlib.h" | ||
| 9 | 6 | ||
| 10 | #include "auxiliar.h" | 7 | #include "auxiliar.h" |
| 11 | #include "socket.h" | 8 | #include "socket.h" |
| 12 | #include "options.h" | 9 | #include "options.h" |
| 13 | #include "unix.h" | 10 | #include "unix.h" |
| 11 | |||
| 12 | #include <string.h> | ||
| 14 | #include <sys/un.h> | 13 | #include <sys/un.h> |
| 15 | 14 | ||
| 16 | /* | 15 | /* |
diff --git a/src/socket.h b/src/socket.h index 63573de..2555bab 100644..100755 --- a/src/socket.h +++ b/src/socket.h | |||
| @@ -16,8 +16,10 @@ | |||
| 16 | \*=========================================================================*/ | 16 | \*=========================================================================*/ |
| 17 | #ifdef _WIN32 | 17 | #ifdef _WIN32 |
| 18 | #include "wsocket.h" | 18 | #include "wsocket.h" |
| 19 | #define LUA_GAI_STRERROR gai_strerrorA | ||
| 19 | #else | 20 | #else |
| 20 | #include "usocket.h" | 21 | #include "usocket.h" |
| 22 | #define LUA_GAI_STRERROR gai_strerror | ||
| 21 | #endif | 23 | #endif |
| 22 | 24 | ||
| 23 | /*=========================================================================*\ | 25 | /*=========================================================================*\ |
| @@ -28,51 +30,46 @@ | |||
| 28 | \*=========================================================================*/ | 30 | \*=========================================================================*/ |
| 29 | #include "timeout.h" | 31 | #include "timeout.h" |
| 30 | 32 | ||
| 31 | /* we are lazy... */ | 33 | /* convenient shorthand */ |
| 32 | typedef struct sockaddr SA; | 34 | typedef struct sockaddr SA; |
| 33 | 35 | ||
| 34 | /*=========================================================================*\ | 36 | /*=========================================================================*\ |
| 35 | * Functions bellow implement a comfortable platform independent | 37 | * Functions bellow implement a comfortable platform independent |
| 36 | * interface to sockets | 38 | * interface to sockets |
| 37 | \*=========================================================================*/ | 39 | \*=========================================================================*/ |
| 38 | int socket_open(void); | ||
| 39 | int socket_close(void); | ||
| 40 | void socket_destroy(p_socket ps); | ||
| 41 | void socket_shutdown(p_socket ps, int how); | ||
| 42 | int socket_sendto(p_socket ps, const char *data, size_t count, | ||
| 43 | size_t *sent, SA *addr, socklen_t addr_len, p_timeout tm); | ||
| 44 | int socket_recvfrom(p_socket ps, char *data, size_t count, | ||
| 45 | size_t *got, SA *addr, socklen_t *addr_len, p_timeout tm); | ||
| 46 | 40 | ||
| 47 | void socket_setnonblocking(p_socket ps); | 41 | #ifndef _WIN32 |
| 48 | void socket_setblocking(p_socket ps); | 42 | #pragma GCC visibility push(hidden) |
| 43 | #endif | ||
| 49 | 44 | ||
| 50 | int socket_waitfd(p_socket ps, int sw, p_timeout tm); | 45 | int socket_waitfd(p_socket ps, int sw, p_timeout tm); |
| 51 | int socket_select(t_socket n, fd_set *rfds, fd_set *wfds, fd_set *efds, | 46 | int socket_open(void); |
| 52 | p_timeout tm); | 47 | int socket_close(void); |
| 53 | 48 | void socket_destroy(p_socket ps); | |
| 54 | int socket_connect(p_socket ps, SA *addr, socklen_t addr_len, p_timeout tm); | 49 | int socket_select(t_socket n, fd_set *rfds, fd_set *wfds, fd_set *efds, p_timeout tm); |
| 55 | int socket_create(p_socket ps, int domain, int type, int protocol); | 50 | int socket_create(p_socket ps, int domain, int type, int protocol); |
| 56 | int socket_bind(p_socket ps, SA *addr, socklen_t addr_len); | 51 | int socket_bind(p_socket ps, SA *addr, socklen_t addr_len); |
| 57 | int socket_listen(p_socket ps, int backlog); | 52 | int socket_listen(p_socket ps, int backlog); |
| 58 | int socket_accept(p_socket ps, p_socket pa, SA *addr, | 53 | void socket_shutdown(p_socket ps, int how); |
| 59 | socklen_t *addr_len, p_timeout tm); | 54 | int socket_connect(p_socket ps, SA *addr, socklen_t addr_len, p_timeout tm); |
| 60 | 55 | int socket_accept(p_socket ps, p_socket pa, SA *addr, socklen_t *addr_len, p_timeout tm); | |
| 61 | const char *socket_hoststrerror(int err); | 56 | int socket_send(p_socket ps, const char *data, size_t count, size_t *sent, p_timeout tm); |
| 62 | const char *socket_gaistrerror(int err); | 57 | int socket_sendto(p_socket ps, const char *data, size_t count, size_t *sent, SA *addr, socklen_t addr_len, p_timeout tm); |
| 63 | const char *socket_strerror(int err); | ||
| 64 | |||
| 65 | /* these are perfect to use with the io abstraction module | ||
| 66 | and the buffered input module */ | ||
| 67 | int socket_send(p_socket ps, const char *data, size_t count, | ||
| 68 | size_t *sent, p_timeout tm); | ||
| 69 | int socket_recv(p_socket ps, char *data, size_t count, size_t *got, p_timeout tm); | 58 | int socket_recv(p_socket ps, char *data, size_t count, size_t *got, p_timeout tm); |
| 70 | int socket_write(p_socket ps, const char *data, size_t count, | 59 | int socket_recvfrom(p_socket ps, char *data, size_t count, size_t *got, SA *addr, socklen_t *addr_len, p_timeout tm); |
| 71 | size_t *sent, p_timeout tm); | 60 | int socket_write(p_socket ps, const char *data, size_t count, size_t *sent, p_timeout tm); |
| 72 | int socket_read(p_socket ps, char *data, size_t count, size_t *got, p_timeout tm); | 61 | int socket_read(p_socket ps, char *data, size_t count, size_t *got, p_timeout tm); |
| 73 | const char *socket_ioerror(p_socket ps, int err); | 62 | void socket_setblocking(p_socket ps); |
| 74 | 63 | void socket_setnonblocking(p_socket ps); | |
| 75 | int socket_gethostbyaddr(const char *addr, socklen_t len, struct hostent **hp); | 64 | int socket_gethostbyaddr(const char *addr, socklen_t len, struct hostent **hp); |
| 76 | int socket_gethostbyname(const char *addr, struct hostent **hp); | 65 | int socket_gethostbyname(const char *addr, struct hostent **hp); |
| 66 | const char *socket_hoststrerror(int err); | ||
| 67 | const char *socket_strerror(int err); | ||
| 68 | const char *socket_ioerror(p_socket ps, int err); | ||
| 69 | const char *socket_gaistrerror(int err); | ||
| 70 | |||
| 71 | #ifndef _WIN32 | ||
| 72 | #pragma GCC visibility pop | ||
| 73 | #endif | ||
| 77 | 74 | ||
| 78 | #endif /* SOCKET_H */ | 75 | #endif /* SOCKET_H */ |
| @@ -2,11 +2,7 @@ | |||
| 2 | * TCP object | 2 | * TCP object |
| 3 | * LuaSocket toolkit | 3 | * LuaSocket toolkit |
| 4 | \*=========================================================================*/ | 4 | \*=========================================================================*/ |
| 5 | #include <string.h> | 5 | #include "luasocket.h" |
| 6 | |||
| 7 | #include "lua.h" | ||
| 8 | #include "lauxlib.h" | ||
| 9 | #include "compat.h" | ||
| 10 | 6 | ||
| 11 | #include "auxiliar.h" | 7 | #include "auxiliar.h" |
| 12 | #include "socket.h" | 8 | #include "socket.h" |
| @@ -14,6 +10,8 @@ | |||
| 14 | #include "options.h" | 10 | #include "options.h" |
| 15 | #include "tcp.h" | 11 | #include "tcp.h" |
| 16 | 12 | ||
| 13 | #include <string.h> | ||
| 14 | |||
| 17 | /*=========================================================================*\ | 15 | /*=========================================================================*\ |
| 18 | * Internal function prototypes | 16 | * Internal function prototypes |
| 19 | \*=========================================================================*/ | 17 | \*=========================================================================*/ |
| @@ -36,6 +34,7 @@ static int meth_accept(lua_State *L); | |||
| 36 | static int meth_close(lua_State *L); | 34 | static int meth_close(lua_State *L); |
| 37 | static int meth_getoption(lua_State *L); | 35 | static int meth_getoption(lua_State *L); |
| 38 | static int meth_setoption(lua_State *L); | 36 | static int meth_setoption(lua_State *L); |
| 37 | static int meth_gettimeout(lua_State *L); | ||
| 39 | static int meth_settimeout(lua_State *L); | 38 | static int meth_settimeout(lua_State *L); |
| 40 | static int meth_getfd(lua_State *L); | 39 | static int meth_getfd(lua_State *L); |
| 41 | static int meth_setfd(lua_State *L); | 40 | static int meth_setfd(lua_State *L); |
| @@ -65,26 +64,62 @@ static luaL_Reg tcp_methods[] = { | |||
| 65 | {"setpeername", meth_connect}, | 64 | {"setpeername", meth_connect}, |
| 66 | {"setsockname", meth_bind}, | 65 | {"setsockname", meth_bind}, |
| 67 | {"settimeout", meth_settimeout}, | 66 | {"settimeout", meth_settimeout}, |
| 67 | {"gettimeout", meth_gettimeout}, | ||
| 68 | {"shutdown", meth_shutdown}, | 68 | {"shutdown", meth_shutdown}, |
| 69 | {NULL, NULL} | 69 | {NULL, NULL} |
| 70 | }; | 70 | }; |
| 71 | 71 | ||
| 72 | /* socket option handlers */ | 72 | /* socket option handlers */ |
| 73 | static t_opt optget[] = { | 73 | static t_opt optget[] = { |
| 74 | {"bindtodevice", opt_get_bindtodevice}, | ||
| 74 | {"keepalive", opt_get_keepalive}, | 75 | {"keepalive", opt_get_keepalive}, |
| 75 | {"reuseaddr", opt_get_reuseaddr}, | 76 | {"reuseaddr", opt_get_reuseaddr}, |
| 77 | {"reuseport", opt_get_reuseport}, | ||
| 76 | {"tcp-nodelay", opt_get_tcp_nodelay}, | 78 | {"tcp-nodelay", opt_get_tcp_nodelay}, |
| 79 | #ifdef TCP_KEEPIDLE | ||
| 80 | {"tcp-keepidle", opt_get_tcp_keepidle}, | ||
| 81 | #endif | ||
| 82 | #ifdef TCP_KEEPCNT | ||
| 83 | {"tcp-keepcnt", opt_get_tcp_keepcnt}, | ||
| 84 | #endif | ||
| 85 | #ifdef TCP_KEEPINTVL | ||
| 86 | {"tcp-keepintvl", opt_get_tcp_keepintvl}, | ||
| 87 | #endif | ||
| 77 | {"linger", opt_get_linger}, | 88 | {"linger", opt_get_linger}, |
| 78 | {"error", opt_get_error}, | 89 | {"error", opt_get_error}, |
| 90 | {"recv-buffer-size", opt_get_recv_buf_size}, | ||
| 91 | {"send-buffer-size", opt_get_send_buf_size}, | ||
| 79 | {NULL, NULL} | 92 | {NULL, NULL} |
| 80 | }; | 93 | }; |
| 81 | 94 | ||
| 82 | static t_opt optset[] = { | 95 | static t_opt optset[] = { |
| 96 | {"bindtodevice", opt_set_bindtodevice}, | ||
| 83 | {"keepalive", opt_set_keepalive}, | 97 | {"keepalive", opt_set_keepalive}, |
| 84 | {"reuseaddr", opt_set_reuseaddr}, | 98 | {"reuseaddr", opt_set_reuseaddr}, |
| 99 | {"reuseport", opt_set_reuseport}, | ||
| 85 | {"tcp-nodelay", opt_set_tcp_nodelay}, | 100 | {"tcp-nodelay", opt_set_tcp_nodelay}, |
| 101 | #ifdef TCP_KEEPIDLE | ||
| 102 | {"tcp-keepidle", opt_set_tcp_keepidle}, | ||
| 103 | #endif | ||
| 104 | #ifdef TCP_KEEPCNT | ||
| 105 | {"tcp-keepcnt", opt_set_tcp_keepcnt}, | ||
| 106 | #endif | ||
| 107 | #ifdef TCP_KEEPINTVL | ||
| 108 | {"tcp-keepintvl", opt_set_tcp_keepintvl}, | ||
| 109 | #endif | ||
| 86 | {"ipv6-v6only", opt_set_ip6_v6only}, | 110 | {"ipv6-v6only", opt_set_ip6_v6only}, |
| 87 | {"linger", opt_set_linger}, | 111 | {"linger", opt_set_linger}, |
| 112 | {"recv-buffer-size", opt_set_recv_buf_size}, | ||
| 113 | {"send-buffer-size", opt_set_send_buf_size}, | ||
| 114 | #ifdef TCP_DEFER_ACCEPT | ||
| 115 | {"tcp-defer-accept", opt_set_tcp_defer_accept}, | ||
| 116 | #endif | ||
| 117 | #ifdef TCP_FASTOPEN | ||
| 118 | {"tcp-fastopen", opt_set_tcp_fastopen}, | ||
| 119 | #endif | ||
| 120 | #ifdef TCP_FASTOPEN_CONNECT | ||
| 121 | {"tcp-fastopen-connect", opt_set_tcp_fastopen_connect}, | ||
| 122 | #endif | ||
| 88 | {NULL, NULL} | 123 | {NULL, NULL} |
| 89 | }; | 124 | }; |
| 90 | 125 | ||
| @@ -348,6 +383,12 @@ static int meth_settimeout(lua_State *L) | |||
| 348 | return timeout_meth_settimeout(L, &tcp->tm); | 383 | return timeout_meth_settimeout(L, &tcp->tm); |
| 349 | } | 384 | } |
| 350 | 385 | ||
| 386 | static int meth_gettimeout(lua_State *L) | ||
| 387 | { | ||
| 388 | p_tcp tcp = (p_tcp) auxiliar_checkgroup(L, "tcp{any}", 1); | ||
| 389 | return timeout_meth_gettimeout(L, &tcp->tm); | ||
| 390 | } | ||
| 391 | |||
| 351 | /*=========================================================================*\ | 392 | /*=========================================================================*\ |
| 352 | * Library functions | 393 | * Library functions |
| 353 | \*=========================================================================*/ | 394 | \*=========================================================================*/ |
| @@ -415,7 +456,7 @@ static int global_connect(lua_State *L) { | |||
| 415 | bindhints.ai_family = family; | 456 | bindhints.ai_family = family; |
| 416 | bindhints.ai_flags = AI_PASSIVE; | 457 | bindhints.ai_flags = AI_PASSIVE; |
| 417 | if (localaddr) { | 458 | if (localaddr) { |
| 418 | err = inet_trybind(&tcp->sock, &tcp->family, localaddr, | 459 | err = inet_trybind(&tcp->sock, &tcp->family, localaddr, |
| 419 | localserv, &bindhints); | 460 | localserv, &bindhints); |
| 420 | if (err) { | 461 | if (err) { |
| 421 | lua_pushnil(L); | 462 | lua_pushnil(L); |
| @@ -427,7 +468,7 @@ static int global_connect(lua_State *L) { | |||
| 427 | memset(&connecthints, 0, sizeof(connecthints)); | 468 | memset(&connecthints, 0, sizeof(connecthints)); |
| 428 | connecthints.ai_socktype = SOCK_STREAM; | 469 | connecthints.ai_socktype = SOCK_STREAM; |
| 429 | /* make sure we try to connect only to the same family */ | 470 | /* make sure we try to connect only to the same family */ |
| 430 | connecthints.ai_family = tcp->family; | 471 | connecthints.ai_family = tcp->family; |
| 431 | err = inet_tryconnect(&tcp->sock, &tcp->family, remoteaddr, remoteserv, | 472 | err = inet_tryconnect(&tcp->sock, &tcp->family, remoteaddr, remoteserv, |
| 432 | &tcp->tm, &connecthints); | 473 | &tcp->tm, &connecthints); |
| 433 | if (err) { | 474 | if (err) { |
| @@ -14,7 +14,7 @@ | |||
| 14 | * tcp objects either connected to some address or returned by the accept | 14 | * tcp objects either connected to some address or returned by the accept |
| 15 | * method of a server object. | 15 | * method of a server object. |
| 16 | \*=========================================================================*/ | 16 | \*=========================================================================*/ |
| 17 | #include "lua.h" | 17 | #include "luasocket.h" |
| 18 | 18 | ||
| 19 | #include "buffer.h" | 19 | #include "buffer.h" |
| 20 | #include "timeout.h" | 20 | #include "timeout.h" |
| @@ -30,6 +30,14 @@ typedef struct t_tcp_ { | |||
| 30 | 30 | ||
| 31 | typedef t_tcp *p_tcp; | 31 | typedef t_tcp *p_tcp; |
| 32 | 32 | ||
| 33 | #ifndef _WIN32 | ||
| 34 | #pragma GCC visibility push(hidden) | ||
| 35 | #endif | ||
| 36 | |||
| 33 | int tcp_open(lua_State *L); | 37 | int tcp_open(lua_State *L); |
| 34 | 38 | ||
| 39 | #ifndef _WIN32 | ||
| 40 | #pragma GCC visibility pop | ||
| 41 | #endif | ||
| 42 | |||
| 35 | #endif /* TCP_H */ | 43 | #endif /* TCP_H */ |
diff --git a/src/timeout.c b/src/timeout.c index 087d033..2bdc069 100644 --- a/src/timeout.c +++ b/src/timeout.c | |||
| @@ -2,17 +2,15 @@ | |||
| 2 | * Timeout management functions | 2 | * Timeout management functions |
| 3 | * LuaSocket toolkit | 3 | * LuaSocket toolkit |
| 4 | \*=========================================================================*/ | 4 | \*=========================================================================*/ |
| 5 | #include <stdio.h> | 5 | #include "luasocket.h" |
| 6 | #include <limits.h> | ||
| 7 | #include <float.h> | ||
| 8 | |||
| 9 | #include "lua.h" | ||
| 10 | #include "lauxlib.h" | ||
| 11 | #include "compat.h" | ||
| 12 | 6 | ||
| 13 | #include "auxiliar.h" | 7 | #include "auxiliar.h" |
| 14 | #include "timeout.h" | 8 | #include "timeout.h" |
| 15 | 9 | ||
| 10 | #include <stdio.h> | ||
| 11 | #include <limits.h> | ||
| 12 | #include <float.h> | ||
| 13 | |||
| 16 | #ifdef _WIN32 | 14 | #ifdef _WIN32 |
| 17 | #include <windows.h> | 15 | #include <windows.h> |
| 18 | #else | 16 | #else |
| @@ -173,6 +171,16 @@ int timeout_meth_settimeout(lua_State *L, p_timeout tm) { | |||
| 173 | return 1; | 171 | return 1; |
| 174 | } | 172 | } |
| 175 | 173 | ||
| 174 | /*-------------------------------------------------------------------------*\ | ||
| 175 | * Gets timeout values for IO operations | ||
| 176 | * Lua Output: block, total | ||
| 177 | \*-------------------------------------------------------------------------*/ | ||
| 178 | int timeout_meth_gettimeout(lua_State *L, p_timeout tm) { | ||
| 179 | lua_pushnumber(L, tm->block); | ||
| 180 | lua_pushnumber(L, tm->total); | ||
| 181 | return 2; | ||
| 182 | } | ||
| 183 | |||
| 176 | /*=========================================================================*\ | 184 | /*=========================================================================*\ |
| 177 | * Test support functions | 185 | * Test support functions |
| 178 | \*=========================================================================*/ | 186 | \*=========================================================================*/ |
diff --git a/src/timeout.h b/src/timeout.h index 6715ca7..9e5250d 100644 --- a/src/timeout.h +++ b/src/timeout.h | |||
| @@ -4,7 +4,7 @@ | |||
| 4 | * Timeout management functions | 4 | * Timeout management functions |
| 5 | * LuaSocket toolkit | 5 | * LuaSocket toolkit |
| 6 | \*=========================================================================*/ | 6 | \*=========================================================================*/ |
| 7 | #include "lua.h" | 7 | #include "luasocket.h" |
| 8 | 8 | ||
| 9 | /* timeout control structure */ | 9 | /* timeout control structure */ |
| 10 | typedef struct t_timeout_ { | 10 | typedef struct t_timeout_ { |
| @@ -14,14 +14,26 @@ typedef struct t_timeout_ { | |||
| 14 | } t_timeout; | 14 | } t_timeout; |
| 15 | typedef t_timeout *p_timeout; | 15 | typedef t_timeout *p_timeout; |
| 16 | 16 | ||
| 17 | int timeout_open(lua_State *L); | 17 | #ifndef _WIN32 |
| 18 | #pragma GCC visibility push(hidden) | ||
| 19 | #endif | ||
| 20 | |||
| 18 | void timeout_init(p_timeout tm, double block, double total); | 21 | void timeout_init(p_timeout tm, double block, double total); |
| 19 | double timeout_get(p_timeout tm); | 22 | double timeout_get(p_timeout tm); |
| 23 | double timeout_getstart(p_timeout tm); | ||
| 20 | double timeout_getretry(p_timeout tm); | 24 | double timeout_getretry(p_timeout tm); |
| 21 | p_timeout timeout_markstart(p_timeout tm); | 25 | p_timeout timeout_markstart(p_timeout tm); |
| 22 | double timeout_getstart(p_timeout tm); | 26 | |
| 23 | double timeout_gettime(void); | 27 | double timeout_gettime(void); |
| 28 | |||
| 29 | int timeout_open(lua_State *L); | ||
| 30 | |||
| 24 | int timeout_meth_settimeout(lua_State *L, p_timeout tm); | 31 | int timeout_meth_settimeout(lua_State *L, p_timeout tm); |
| 32 | int timeout_meth_gettimeout(lua_State *L, p_timeout tm); | ||
| 33 | |||
| 34 | #ifndef _WIN32 | ||
| 35 | #pragma GCC visibility pop | ||
| 36 | #endif | ||
| 25 | 37 | ||
| 26 | #define timeout_iszero(tm) ((tm)->block == 0.0) | 38 | #define timeout_iszero(tm) ((tm)->block == 0.0) |
| 27 | 39 | ||
| @@ -46,6 +46,14 @@ end | |||
| 46 | -- metatable for sock object | 46 | -- metatable for sock object |
| 47 | local metat = { __index = {} } | 47 | local metat = { __index = {} } |
| 48 | 48 | ||
| 49 | function metat.__index:getpeername() | ||
| 50 | return self.c:getpeername() | ||
| 51 | end | ||
| 52 | |||
| 53 | function metat.__index:getsockname() | ||
| 54 | return self.c:getpeername() | ||
| 55 | end | ||
| 56 | |||
| 49 | function metat.__index:check(ok) | 57 | function metat.__index:check(ok) |
| 50 | local code, reply = get_reply(self.c) | 58 | local code, reply = get_reply(self.c) |
| 51 | if not code then return nil, reply end | 59 | if not code then return nil, reply end |
| @@ -74,7 +82,7 @@ function metat.__index:command(cmd, arg) | |||
| 74 | end | 82 | end |
| 75 | 83 | ||
| 76 | function metat.__index:sink(snk, pat) | 84 | function metat.__index:sink(snk, pat) |
| 77 | local chunk, err = c:receive(pat) | 85 | local chunk, err = self.c:receive(pat) |
| 78 | return snk(chunk, err) | 86 | return snk(chunk, err) |
| 79 | end | 87 | end |
| 80 | 88 | ||
| @@ -123,4 +131,4 @@ function _M.connect(host, port, timeout, create) | |||
| 123 | return base.setmetatable({c = c}, metat) | 131 | return base.setmetatable({c = c}, metat) |
| 124 | end | 132 | end |
| 125 | 133 | ||
| 126 | return _M \ No newline at end of file | 134 | return _M |
| @@ -2,12 +2,7 @@ | |||
| 2 | * UDP object | 2 | * UDP object |
| 3 | * LuaSocket toolkit | 3 | * LuaSocket toolkit |
| 4 | \*=========================================================================*/ | 4 | \*=========================================================================*/ |
| 5 | #include <string.h> | 5 | #include "luasocket.h" |
| 6 | #include <stdlib.h> | ||
| 7 | |||
| 8 | #include "lua.h" | ||
| 9 | #include "lauxlib.h" | ||
| 10 | #include "compat.h" | ||
| 11 | 6 | ||
| 12 | #include "auxiliar.h" | 7 | #include "auxiliar.h" |
| 13 | #include "socket.h" | 8 | #include "socket.h" |
| @@ -15,6 +10,9 @@ | |||
| 15 | #include "options.h" | 10 | #include "options.h" |
| 16 | #include "udp.h" | 11 | #include "udp.h" |
| 17 | 12 | ||
| 13 | #include <string.h> | ||
| 14 | #include <stdlib.h> | ||
| 15 | |||
| 18 | /* min and max macros */ | 16 | /* min and max macros */ |
| 19 | #ifndef MIN | 17 | #ifndef MIN |
| 20 | #define MIN(x, y) ((x) < (y) ? x : y) | 18 | #define MIN(x, y) ((x) < (y) ? x : y) |
| @@ -36,6 +34,7 @@ static int meth_receivefrom(lua_State *L); | |||
| 36 | static int meth_getfamily(lua_State *L); | 34 | static int meth_getfamily(lua_State *L); |
| 37 | static int meth_getsockname(lua_State *L); | 35 | static int meth_getsockname(lua_State *L); |
| 38 | static int meth_getpeername(lua_State *L); | 36 | static int meth_getpeername(lua_State *L); |
| 37 | static int meth_gettimeout(lua_State *L); | ||
| 39 | static int meth_setsockname(lua_State *L); | 38 | static int meth_setsockname(lua_State *L); |
| 40 | static int meth_setpeername(lua_State *L); | 39 | static int meth_setpeername(lua_State *L); |
| 41 | static int meth_close(lua_State *L); | 40 | static int meth_close(lua_State *L); |
| @@ -66,6 +65,7 @@ static luaL_Reg udp_methods[] = { | |||
| 66 | {"setpeername", meth_setpeername}, | 65 | {"setpeername", meth_setpeername}, |
| 67 | {"setsockname", meth_setsockname}, | 66 | {"setsockname", meth_setsockname}, |
| 68 | {"settimeout", meth_settimeout}, | 67 | {"settimeout", meth_settimeout}, |
| 68 | {"gettimeout", meth_gettimeout}, | ||
| 69 | {NULL, NULL} | 69 | {NULL, NULL} |
| 70 | }; | 70 | }; |
| 71 | 71 | ||
| @@ -86,6 +86,8 @@ static t_opt optset[] = { | |||
| 86 | {"ipv6-add-membership", opt_set_ip6_add_membership}, | 86 | {"ipv6-add-membership", opt_set_ip6_add_membership}, |
| 87 | {"ipv6-drop-membership", opt_set_ip6_drop_membersip}, | 87 | {"ipv6-drop-membership", opt_set_ip6_drop_membersip}, |
| 88 | {"ipv6-v6only", opt_set_ip6_v6only}, | 88 | {"ipv6-v6only", opt_set_ip6_v6only}, |
| 89 | {"recv-buffer-size", opt_set_recv_buf_size}, | ||
| 90 | {"send-buffer-size", opt_set_send_buf_size}, | ||
| 89 | {NULL, NULL} | 91 | {NULL, NULL} |
| 90 | }; | 92 | }; |
| 91 | 93 | ||
| @@ -102,6 +104,8 @@ static t_opt optget[] = { | |||
| 102 | {"ipv6-multicast-hops", opt_get_ip6_unicast_hops}, | 104 | {"ipv6-multicast-hops", opt_get_ip6_unicast_hops}, |
| 103 | {"ipv6-multicast-loop", opt_get_ip6_multicast_loop}, | 105 | {"ipv6-multicast-loop", opt_get_ip6_multicast_loop}, |
| 104 | {"ipv6-v6only", opt_get_ip6_v6only}, | 106 | {"ipv6-v6only", opt_get_ip6_v6only}, |
| 107 | {"recv-buffer-size", opt_get_recv_buf_size}, | ||
| 108 | {"send-buffer-size", opt_get_send_buf_size}, | ||
| 105 | {NULL, NULL} | 109 | {NULL, NULL} |
| 106 | }; | 110 | }; |
| 107 | 111 | ||
| @@ -116,8 +120,7 @@ static luaL_Reg func[] = { | |||
| 116 | /*-------------------------------------------------------------------------*\ | 120 | /*-------------------------------------------------------------------------*\ |
| 117 | * Initializes module | 121 | * Initializes module |
| 118 | \*-------------------------------------------------------------------------*/ | 122 | \*-------------------------------------------------------------------------*/ |
| 119 | int udp_open(lua_State *L) | 123 | int udp_open(lua_State *L) { |
| 120 | { | ||
| 121 | /* create classes */ | 124 | /* create classes */ |
| 122 | auxiliar_newclass(L, "udp{connected}", udp_methods); | 125 | auxiliar_newclass(L, "udp{connected}", udp_methods); |
| 123 | auxiliar_newclass(L, "udp{unconnected}", udp_methods); | 126 | auxiliar_newclass(L, "udp{unconnected}", udp_methods); |
| @@ -128,6 +131,10 @@ int udp_open(lua_State *L) | |||
| 128 | auxiliar_add2group(L, "udp{unconnected}", "select{able}"); | 131 | auxiliar_add2group(L, "udp{unconnected}", "select{able}"); |
| 129 | /* define library functions */ | 132 | /* define library functions */ |
| 130 | luaL_setfuncs(L, func, 0); | 133 | luaL_setfuncs(L, func, 0); |
| 134 | /* export default UDP size */ | ||
| 135 | lua_pushliteral(L, "_DATAGRAMSIZE"); | ||
| 136 | lua_pushinteger(L, UDP_DATAGRAMSIZE); | ||
| 137 | lua_rawset(L, -3); | ||
| 131 | return 0; | 138 | return 0; |
| 132 | } | 139 | } |
| 133 | 140 | ||
| @@ -177,13 +184,37 @@ static int meth_sendto(lua_State *L) { | |||
| 177 | memset(&aihint, 0, sizeof(aihint)); | 184 | memset(&aihint, 0, sizeof(aihint)); |
| 178 | aihint.ai_family = udp->family; | 185 | aihint.ai_family = udp->family; |
| 179 | aihint.ai_socktype = SOCK_DGRAM; | 186 | aihint.ai_socktype = SOCK_DGRAM; |
| 180 | aihint.ai_flags = AI_NUMERICHOST | AI_NUMERICSERV; | 187 | aihint.ai_flags = AI_NUMERICHOST; |
| 188 | #ifdef AI_NUMERICSERV | ||
| 189 | aihint.ai_flags |= AI_NUMERICSERV; | ||
| 190 | #endif | ||
| 181 | err = getaddrinfo(ip, port, &aihint, &ai); | 191 | err = getaddrinfo(ip, port, &aihint, &ai); |
| 182 | if (err) { | 192 | if (err) { |
| 183 | lua_pushnil(L); | 193 | lua_pushnil(L); |
| 184 | lua_pushstring(L, gai_strerror(err)); | 194 | lua_pushstring(L, LUA_GAI_STRERROR(err)); |
| 185 | return 2; | 195 | return 2; |
| 186 | } | 196 | } |
| 197 | |||
| 198 | /* create socket if on first sendto if AF_UNSPEC was set */ | ||
| 199 | if (udp->family == AF_UNSPEC && udp->sock == SOCKET_INVALID) { | ||
| 200 | struct addrinfo *ap; | ||
| 201 | const char *errstr = NULL; | ||
| 202 | for (ap = ai; ap != NULL; ap = ap->ai_next) { | ||
| 203 | errstr = inet_trycreate(&udp->sock, ap->ai_family, SOCK_DGRAM, 0); | ||
| 204 | if (errstr == NULL) { | ||
| 205 | socket_setnonblocking(&udp->sock); | ||
| 206 | udp->family = ap->ai_family; | ||
| 207 | break; | ||
| 208 | } | ||
| 209 | } | ||
| 210 | if (errstr != NULL) { | ||
| 211 | lua_pushnil(L); | ||
| 212 | lua_pushstring(L, errstr); | ||
| 213 | freeaddrinfo(ai); | ||
| 214 | return 2; | ||
| 215 | } | ||
| 216 | } | ||
| 217 | |||
| 187 | timeout_markstart(tm); | 218 | timeout_markstart(tm); |
| 188 | err = socket_sendto(&udp->sock, data, count, &sent, ai->ai_addr, | 219 | err = socket_sendto(&udp->sock, data, count, &sent, ai->ai_addr, |
| 189 | (socklen_t) ai->ai_addrlen, tm); | 220 | (socklen_t) ai->ai_addrlen, tm); |
| @@ -202,69 +233,78 @@ static int meth_sendto(lua_State *L) { | |||
| 202 | \*-------------------------------------------------------------------------*/ | 233 | \*-------------------------------------------------------------------------*/ |
| 203 | static int meth_receive(lua_State *L) { | 234 | static int meth_receive(lua_State *L) { |
| 204 | p_udp udp = (p_udp) auxiliar_checkgroup(L, "udp{any}", 1); | 235 | p_udp udp = (p_udp) auxiliar_checkgroup(L, "udp{any}", 1); |
| 205 | char buffer[UDP_DATAGRAMSIZE]; | 236 | char buf[UDP_DATAGRAMSIZE]; |
| 206 | size_t got, count = (size_t) luaL_optnumber(L, 2, sizeof(buffer)); | 237 | size_t got, wanted = (size_t) luaL_optnumber(L, 2, sizeof(buf)); |
| 238 | char *dgram = wanted > sizeof(buf)? (char *) malloc(wanted): buf; | ||
| 207 | int err; | 239 | int err; |
| 208 | p_timeout tm = &udp->tm; | 240 | p_timeout tm = &udp->tm; |
| 209 | count = MIN(count, sizeof(buffer)); | ||
| 210 | timeout_markstart(tm); | 241 | timeout_markstart(tm); |
| 211 | err = socket_recv(&udp->sock, buffer, count, &got, tm); | 242 | if (!dgram) { |
| 243 | lua_pushnil(L); | ||
| 244 | lua_pushliteral(L, "out of memory"); | ||
| 245 | return 2; | ||
| 246 | } | ||
| 247 | err = socket_recv(&udp->sock, dgram, wanted, &got, tm); | ||
| 212 | /* Unlike TCP, recv() of zero is not closed, but a zero-length packet. */ | 248 | /* Unlike TCP, recv() of zero is not closed, but a zero-length packet. */ |
| 213 | if (err == IO_CLOSED) | 249 | if (err != IO_DONE && err != IO_CLOSED) { |
| 214 | err = IO_DONE; | ||
| 215 | if (err != IO_DONE) { | ||
| 216 | lua_pushnil(L); | 250 | lua_pushnil(L); |
| 217 | lua_pushstring(L, udp_strerror(err)); | 251 | lua_pushstring(L, udp_strerror(err)); |
| 252 | if (wanted > sizeof(buf)) free(dgram); | ||
| 218 | return 2; | 253 | return 2; |
| 219 | } | 254 | } |
| 220 | lua_pushlstring(L, buffer, got); | 255 | lua_pushlstring(L, dgram, got); |
| 256 | if (wanted > sizeof(buf)) free(dgram); | ||
| 221 | return 1; | 257 | return 1; |
| 222 | } | 258 | } |
| 223 | 259 | ||
| 224 | /*-------------------------------------------------------------------------*\ | 260 | /*-------------------------------------------------------------------------*\ |
| 225 | * Receives data and sender from a UDP socket | 261 | * Receives data and sender from a UDP socket |
| 226 | \*-------------------------------------------------------------------------*/ | 262 | \*-------------------------------------------------------------------------*/ |
| 227 | static int meth_receivefrom(lua_State *L) | 263 | static int meth_receivefrom(lua_State *L) { |
| 228 | { | ||
| 229 | p_udp udp = (p_udp) auxiliar_checkclass(L, "udp{unconnected}", 1); | 264 | p_udp udp = (p_udp) auxiliar_checkclass(L, "udp{unconnected}", 1); |
| 230 | char buffer[UDP_DATAGRAMSIZE]; | 265 | char buf[UDP_DATAGRAMSIZE]; |
| 231 | size_t got, count = (size_t) luaL_optnumber(L, 2, sizeof(buffer)); | 266 | size_t got, wanted = (size_t) luaL_optnumber(L, 2, sizeof(buf)); |
| 232 | int err; | 267 | char *dgram = wanted > sizeof(buf)? (char *) malloc(wanted): buf; |
| 233 | p_timeout tm = &udp->tm; | ||
| 234 | struct sockaddr_storage addr; | 268 | struct sockaddr_storage addr; |
| 235 | socklen_t addr_len = sizeof(addr); | 269 | socklen_t addr_len = sizeof(addr); |
| 236 | char addrstr[INET6_ADDRSTRLEN]; | 270 | char addrstr[INET6_ADDRSTRLEN]; |
| 237 | char portstr[6]; | 271 | char portstr[6]; |
| 272 | int err; | ||
| 273 | p_timeout tm = &udp->tm; | ||
| 238 | timeout_markstart(tm); | 274 | timeout_markstart(tm); |
| 239 | count = MIN(count, sizeof(buffer)); | 275 | if (!dgram) { |
| 240 | err = socket_recvfrom(&udp->sock, buffer, count, &got, (SA *) &addr, | 276 | lua_pushnil(L); |
| 277 | lua_pushliteral(L, "out of memory"); | ||
| 278 | return 2; | ||
| 279 | } | ||
| 280 | err = socket_recvfrom(&udp->sock, dgram, wanted, &got, (SA *) &addr, | ||
| 241 | &addr_len, tm); | 281 | &addr_len, tm); |
| 242 | /* Unlike TCP, recv() of zero is not closed, but a zero-length packet. */ | 282 | /* Unlike TCP, recv() of zero is not closed, but a zero-length packet. */ |
| 243 | if (err == IO_CLOSED) | 283 | if (err != IO_DONE && err != IO_CLOSED) { |
| 244 | err = IO_DONE; | ||
| 245 | if (err != IO_DONE) { | ||
| 246 | lua_pushnil(L); | 284 | lua_pushnil(L); |
| 247 | lua_pushstring(L, udp_strerror(err)); | 285 | lua_pushstring(L, udp_strerror(err)); |
| 286 | if (wanted > sizeof(buf)) free(dgram); | ||
| 248 | return 2; | 287 | return 2; |
| 249 | } | 288 | } |
| 250 | err = getnameinfo((struct sockaddr *)&addr, addr_len, addrstr, | 289 | err = getnameinfo((struct sockaddr *)&addr, addr_len, addrstr, |
| 251 | INET6_ADDRSTRLEN, portstr, 6, NI_NUMERICHOST | NI_NUMERICSERV); | 290 | INET6_ADDRSTRLEN, portstr, 6, NI_NUMERICHOST | NI_NUMERICSERV); |
| 252 | if (err) { | 291 | if (err) { |
| 253 | lua_pushnil(L); | 292 | lua_pushnil(L); |
| 254 | lua_pushstring(L, gai_strerror(err)); | 293 | lua_pushstring(L, LUA_GAI_STRERROR(err)); |
| 294 | if (wanted > sizeof(buf)) free(dgram); | ||
| 255 | return 2; | 295 | return 2; |
| 256 | } | 296 | } |
| 257 | lua_pushlstring(L, buffer, got); | 297 | lua_pushlstring(L, dgram, got); |
| 258 | lua_pushstring(L, addrstr); | 298 | lua_pushstring(L, addrstr); |
| 259 | lua_pushinteger(L, (int) strtol(portstr, (char **) NULL, 10)); | 299 | lua_pushinteger(L, (int) strtol(portstr, (char **) NULL, 10)); |
| 300 | if (wanted > sizeof(buf)) free(dgram); | ||
| 260 | return 3; | 301 | return 3; |
| 261 | } | 302 | } |
| 262 | 303 | ||
| 263 | /*-------------------------------------------------------------------------*\ | 304 | /*-------------------------------------------------------------------------*\ |
| 264 | * Returns family as string | 305 | * Returns family as string |
| 265 | \*-------------------------------------------------------------------------*/ | 306 | \*-------------------------------------------------------------------------*/ |
| 266 | static int meth_getfamily(lua_State *L) | 307 | static int meth_getfamily(lua_State *L) { |
| 267 | { | ||
| 268 | p_udp udp = (p_udp) auxiliar_checkgroup(L, "udp{any}", 1); | 308 | p_udp udp = (p_udp) auxiliar_checkgroup(L, "udp{any}", 1); |
| 269 | if (udp->family == AF_INET6) { | 309 | if (udp->family == AF_INET6) { |
| 270 | lua_pushliteral(L, "inet6"); | 310 | lua_pushliteral(L, "inet6"); |
| @@ -335,6 +375,11 @@ static int meth_settimeout(lua_State *L) { | |||
| 335 | return timeout_meth_settimeout(L, &udp->tm); | 375 | return timeout_meth_settimeout(L, &udp->tm); |
| 336 | } | 376 | } |
| 337 | 377 | ||
| 378 | static int meth_gettimeout(lua_State *L) { | ||
| 379 | p_udp udp = (p_udp) auxiliar_checkgroup(L, "udp{any}", 1); | ||
| 380 | return timeout_meth_gettimeout(L, &udp->tm); | ||
| 381 | } | ||
| 382 | |||
| 338 | /*-------------------------------------------------------------------------*\ | 383 | /*-------------------------------------------------------------------------*\ |
| 339 | * Turns a master udp object into a client object. | 384 | * Turns a master udp object into a client object. |
| 340 | \*-------------------------------------------------------------------------*/ | 385 | \*-------------------------------------------------------------------------*/ |
| @@ -8,16 +8,15 @@ | |||
| 8 | * (AF_INET, SOCK_DGRAM). | 8 | * (AF_INET, SOCK_DGRAM). |
| 9 | * | 9 | * |
| 10 | * Two classes are defined: connected and unconnected. UDP objects are | 10 | * Two classes are defined: connected and unconnected. UDP objects are |
| 11 | * originally unconnected. They can be "connected" to a given address | 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 | 12 | * with a call to the setpeername function. The same function can be used to |
| 13 | * break the connection. | 13 | * break the connection. |
| 14 | \*=========================================================================*/ | 14 | \*=========================================================================*/ |
| 15 | #include "lua.h" | 15 | #include "luasocket.h" |
| 16 | 16 | ||
| 17 | #include "timeout.h" | 17 | #include "timeout.h" |
| 18 | #include "socket.h" | 18 | #include "socket.h" |
| 19 | 19 | ||
| 20 | /* can't be larger than wsocket.c MAXCHUNK!!! */ | ||
| 21 | #define UDP_DATAGRAMSIZE 8192 | 20 | #define UDP_DATAGRAMSIZE 8192 |
| 22 | 21 | ||
| 23 | typedef struct t_udp_ { | 22 | typedef struct t_udp_ { |
| @@ -27,6 +26,14 @@ typedef struct t_udp_ { | |||
| 27 | } t_udp; | 26 | } t_udp; |
| 28 | typedef t_udp *p_udp; | 27 | typedef t_udp *p_udp; |
| 29 | 28 | ||
| 29 | #ifndef _WIN32 | ||
| 30 | #pragma GCC visibility push(hidden) | ||
| 31 | #endif | ||
| 32 | |||
| 30 | int udp_open(lua_State *L); | 33 | int udp_open(lua_State *L); |
| 31 | 34 | ||
| 35 | #ifndef _WIN32 | ||
| 36 | #pragma GCC visibility pop | ||
| 37 | #endif | ||
| 38 | |||
| 32 | #endif /* UDP_H */ | 39 | #endif /* UDP_H */ |
| @@ -2,329 +2,68 @@ | |||
| 2 | * Unix domain socket | 2 | * Unix domain socket |
| 3 | * LuaSocket toolkit | 3 | * LuaSocket toolkit |
| 4 | \*=========================================================================*/ | 4 | \*=========================================================================*/ |
| 5 | #include <string.h> | 5 | #include "luasocket.h" |
| 6 | 6 | ||
| 7 | #include "lua.h" | 7 | #include "unixstream.h" |
| 8 | #include "lauxlib.h" | 8 | #include "unixdgram.h" |
| 9 | |||
| 10 | #include "auxiliar.h" | ||
| 11 | #include "socket.h" | ||
| 12 | #include "options.h" | ||
| 13 | #include "unix.h" | ||
| 14 | #include <sys/un.h> | ||
| 15 | |||
| 16 | /*=========================================================================*\ | ||
| 17 | * Internal function prototypes | ||
| 18 | \*=========================================================================*/ | ||
| 19 | static int global_create(lua_State *L); | ||
| 20 | static int meth_connect(lua_State *L); | ||
| 21 | static int meth_listen(lua_State *L); | ||
| 22 | static int meth_bind(lua_State *L); | ||
| 23 | static int meth_send(lua_State *L); | ||
| 24 | static int meth_shutdown(lua_State *L); | ||
| 25 | static int meth_receive(lua_State *L); | ||
| 26 | static int meth_accept(lua_State *L); | ||
| 27 | static int meth_close(lua_State *L); | ||
| 28 | static int meth_setoption(lua_State *L); | ||
| 29 | static int meth_settimeout(lua_State *L); | ||
| 30 | static int meth_getfd(lua_State *L); | ||
| 31 | static int meth_setfd(lua_State *L); | ||
| 32 | static int meth_dirty(lua_State *L); | ||
| 33 | static int meth_getstats(lua_State *L); | ||
| 34 | static int meth_setstats(lua_State *L); | ||
| 35 | |||
| 36 | static const char *unix_tryconnect(p_unix un, const char *path); | ||
| 37 | static const char *unix_trybind(p_unix un, const char *path); | ||
| 38 | |||
| 39 | /* unix object methods */ | ||
| 40 | static luaL_Reg unix_methods[] = { | ||
| 41 | {"__gc", meth_close}, | ||
| 42 | {"__tostring", auxiliar_tostring}, | ||
| 43 | {"accept", meth_accept}, | ||
| 44 | {"bind", meth_bind}, | ||
| 45 | {"close", meth_close}, | ||
| 46 | {"connect", meth_connect}, | ||
| 47 | {"dirty", meth_dirty}, | ||
| 48 | {"getfd", meth_getfd}, | ||
| 49 | {"getstats", meth_getstats}, | ||
| 50 | {"setstats", meth_setstats}, | ||
| 51 | {"listen", meth_listen}, | ||
| 52 | {"receive", meth_receive}, | ||
| 53 | {"send", meth_send}, | ||
| 54 | {"setfd", meth_setfd}, | ||
| 55 | {"setoption", meth_setoption}, | ||
| 56 | {"setpeername", meth_connect}, | ||
| 57 | {"setsockname", meth_bind}, | ||
| 58 | {"settimeout", meth_settimeout}, | ||
| 59 | {"shutdown", meth_shutdown}, | ||
| 60 | {NULL, NULL} | ||
| 61 | }; | ||
| 62 | |||
| 63 | /* socket option handlers */ | ||
| 64 | static t_opt optset[] = { | ||
| 65 | {"keepalive", opt_set_keepalive}, | ||
| 66 | {"reuseaddr", opt_set_reuseaddr}, | ||
| 67 | {"linger", opt_set_linger}, | ||
| 68 | {NULL, NULL} | ||
| 69 | }; | ||
| 70 | 9 | ||
| 71 | /*-------------------------------------------------------------------------*\ | 10 | /*-------------------------------------------------------------------------*\ |
| 72 | * Initializes module | 11 | * Modules and functions |
| 73 | \*-------------------------------------------------------------------------*/ | 12 | \*-------------------------------------------------------------------------*/ |
| 74 | int luaopen_socket_unix(lua_State *L) { | 13 | static const luaL_Reg mod[] = { |
| 75 | /* create classes */ | 14 | {"stream", unixstream_open}, |
| 76 | auxiliar_newclass(L, "unix{master}", unix_methods); | 15 | {"dgram", unixdgram_open}, |
| 77 | auxiliar_newclass(L, "unix{client}", unix_methods); | 16 | {NULL, NULL} |
| 78 | auxiliar_newclass(L, "unix{server}", unix_methods); | 17 | }; |
| 79 | /* create class groups */ | ||
| 80 | auxiliar_add2group(L, "unix{master}", "unix{any}"); | ||
| 81 | auxiliar_add2group(L, "unix{client}", "unix{any}"); | ||
| 82 | auxiliar_add2group(L, "unix{server}", "unix{any}"); | ||
| 83 | /* return the function instead of the 'socket' table */ | ||
| 84 | lua_pushcfunction(L, global_create); | ||
| 85 | return 1; | ||
| 86 | } | ||
| 87 | |||
| 88 | /*=========================================================================*\ | ||
| 89 | * Lua methods | ||
| 90 | \*=========================================================================*/ | ||
| 91 | /*-------------------------------------------------------------------------*\ | ||
| 92 | * Just call buffered IO methods | ||
| 93 | \*-------------------------------------------------------------------------*/ | ||
| 94 | static int meth_send(lua_State *L) { | ||
| 95 | p_unix un = (p_unix) auxiliar_checkclass(L, "unix{client}", 1); | ||
| 96 | return buffer_meth_send(L, &un->buf); | ||
| 97 | } | ||
| 98 | |||
| 99 | static int meth_receive(lua_State *L) { | ||
| 100 | p_unix un = (p_unix) auxiliar_checkclass(L, "unix{client}", 1); | ||
| 101 | return buffer_meth_receive(L, &un->buf); | ||
| 102 | } | ||
| 103 | |||
| 104 | static int meth_getstats(lua_State *L) { | ||
| 105 | p_unix un = (p_unix) auxiliar_checkclass(L, "unix{client}", 1); | ||
| 106 | return buffer_meth_getstats(L, &un->buf); | ||
| 107 | } | ||
| 108 | |||
| 109 | static int meth_setstats(lua_State *L) { | ||
| 110 | p_unix un = (p_unix) auxiliar_checkclass(L, "unix{client}", 1); | ||
| 111 | return buffer_meth_setstats(L, &un->buf); | ||
| 112 | } | ||
| 113 | |||
| 114 | /*-------------------------------------------------------------------------*\ | ||
| 115 | * Just call option handler | ||
| 116 | \*-------------------------------------------------------------------------*/ | ||
| 117 | static int meth_setoption(lua_State *L) { | ||
| 118 | p_unix un = (p_unix) auxiliar_checkgroup(L, "unix{any}", 1); | ||
| 119 | return opt_meth_setoption(L, optset, &un->sock); | ||
| 120 | } | ||
| 121 | |||
| 122 | /*-------------------------------------------------------------------------*\ | ||
| 123 | * Select support methods | ||
| 124 | \*-------------------------------------------------------------------------*/ | ||
| 125 | static int meth_getfd(lua_State *L) { | ||
| 126 | p_unix un = (p_unix) auxiliar_checkgroup(L, "unix{any}", 1); | ||
| 127 | lua_pushnumber(L, (int) un->sock); | ||
| 128 | return 1; | ||
| 129 | } | ||
| 130 | |||
| 131 | /* this is very dangerous, but can be handy for those that are brave enough */ | ||
| 132 | static int meth_setfd(lua_State *L) { | ||
| 133 | p_unix un = (p_unix) auxiliar_checkgroup(L, "unix{any}", 1); | ||
| 134 | un->sock = (t_socket) luaL_checknumber(L, 2); | ||
| 135 | return 0; | ||
| 136 | } | ||
| 137 | 18 | ||
| 138 | static int meth_dirty(lua_State *L) { | 19 | static void add_alias(lua_State *L, int index, const char *name, const char *target) |
| 139 | p_unix un = (p_unix) auxiliar_checkgroup(L, "unix{any}", 1); | 20 | { |
| 140 | lua_pushboolean(L, !buffer_isempty(&un->buf)); | 21 | lua_getfield(L, index, target); |
| 141 | return 1; | 22 | lua_setfield(L, index, name); |
| 142 | } | 23 | } |
| 143 | 24 | ||
| 144 | /*-------------------------------------------------------------------------*\ | 25 | static int compat_socket_unix_call(lua_State *L) |
| 145 | * Waits for and returns a client object attempting connection to the | 26 | { |
| 146 | * server object | 27 | /* Look up socket.unix.stream in the socket.unix table (which is the first |
| 147 | \*-------------------------------------------------------------------------*/ | 28 | * argument). */ |
| 148 | static int meth_accept(lua_State *L) { | 29 | lua_getfield(L, 1, "stream"); |
| 149 | p_unix server = (p_unix) auxiliar_checkclass(L, "unix{server}", 1); | ||
| 150 | p_timeout tm = timeout_markstart(&server->tm); | ||
| 151 | t_socket sock; | ||
| 152 | int err = socket_accept(&server->sock, &sock, NULL, NULL, tm); | ||
| 153 | /* if successful, push client socket */ | ||
| 154 | if (err == IO_DONE) { | ||
| 155 | p_unix clnt = (p_unix) lua_newuserdata(L, sizeof(t_unix)); | ||
| 156 | auxiliar_setclass(L, "unix{client}", -1); | ||
| 157 | /* initialize structure fields */ | ||
| 158 | socket_setnonblocking(&sock); | ||
| 159 | clnt->sock = sock; | ||
| 160 | io_init(&clnt->io, (p_send)socket_send, (p_recv)socket_recv, | ||
| 161 | (p_error) socket_ioerror, &clnt->sock); | ||
| 162 | timeout_init(&clnt->tm, -1, -1); | ||
| 163 | buffer_init(&clnt->buf, &clnt->io, &clnt->tm); | ||
| 164 | return 1; | ||
| 165 | } else { | ||
| 166 | lua_pushnil(L); | ||
| 167 | lua_pushstring(L, socket_strerror(err)); | ||
| 168 | return 2; | ||
| 169 | } | ||
| 170 | } | ||
| 171 | 30 | ||
| 172 | /*-------------------------------------------------------------------------*\ | 31 | /* Replace the stack entry for the socket.unix table with the |
| 173 | * Binds an object to an address | 32 | * socket.unix.stream function. */ |
| 174 | \*-------------------------------------------------------------------------*/ | 33 | lua_replace(L, 1); |
| 175 | static const char *unix_trybind(p_unix un, const char *path) { | ||
| 176 | struct sockaddr_un local; | ||
| 177 | size_t len = strlen(path); | ||
| 178 | int err; | ||
| 179 | if (len >= sizeof(local.sun_path)) return "path too long"; | ||
| 180 | memset(&local, 0, sizeof(local)); | ||
| 181 | strcpy(local.sun_path, path); | ||
| 182 | local.sun_family = AF_UNIX; | ||
| 183 | #ifdef UNIX_HAS_SUN_LEN | ||
| 184 | local.sun_len = sizeof(local.sun_family) + sizeof(local.sun_len) | ||
| 185 | + len + 1; | ||
| 186 | err = socket_bind(&un->sock, (SA *) &local, local.sun_len); | ||
| 187 | 34 | ||
| 188 | #else | 35 | /* Call socket.unix.stream, passing along any arguments. */ |
| 189 | err = socket_bind(&un->sock, (SA *) &local, | 36 | int n = lua_gettop(L); |
| 190 | sizeof(local.sun_family) + len); | 37 | lua_call(L, n-1, LUA_MULTRET); |
| 191 | #endif | ||
| 192 | if (err != IO_DONE) socket_destroy(&un->sock); | ||
| 193 | return socket_strerror(err); | ||
| 194 | } | ||
| 195 | 38 | ||
| 196 | static int meth_bind(lua_State *L) { | 39 | /* Pass along the return values from socket.unix.stream. */ |
| 197 | p_unix un = (p_unix) auxiliar_checkclass(L, "unix{master}", 1); | 40 | n = lua_gettop(L); |
| 198 | const char *path = luaL_checkstring(L, 2); | 41 | return n; |
| 199 | const char *err = unix_trybind(un, path); | ||
| 200 | if (err) { | ||
| 201 | lua_pushnil(L); | ||
| 202 | lua_pushstring(L, err); | ||
| 203 | return 2; | ||
| 204 | } | ||
| 205 | lua_pushnumber(L, 1); | ||
| 206 | return 1; | ||
| 207 | } | 42 | } |
| 208 | 43 | ||
| 209 | /*-------------------------------------------------------------------------*\ | 44 | /*-------------------------------------------------------------------------*\ |
| 210 | * Turns a master unix object into a client object. | 45 | * Initializes module |
| 211 | \*-------------------------------------------------------------------------*/ | 46 | \*-------------------------------------------------------------------------*/ |
| 212 | static const char *unix_tryconnect(p_unix un, const char *path) | 47 | LUASOCKET_API int luaopen_socket_unix(lua_State *L) |
| 213 | { | 48 | { |
| 214 | struct sockaddr_un remote; | 49 | int i; |
| 215 | int err; | 50 | lua_newtable(L); |
| 216 | size_t len = strlen(path); | 51 | int socket_unix_table = lua_gettop(L); |
| 217 | if (len >= sizeof(remote.sun_path)) return "path too long"; | ||
| 218 | memset(&remote, 0, sizeof(remote)); | ||
| 219 | strcpy(remote.sun_path, path); | ||
| 220 | remote.sun_family = AF_UNIX; | ||
| 221 | timeout_markstart(&un->tm); | ||
| 222 | #ifdef UNIX_HAS_SUN_LEN | ||
| 223 | remote.sun_len = sizeof(remote.sun_family) + sizeof(remote.sun_len) | ||
| 224 | + len + 1; | ||
| 225 | err = socket_connect(&un->sock, (SA *) &remote, remote.sun_len, &un->tm); | ||
| 226 | #else | ||
| 227 | err = socket_connect(&un->sock, (SA *) &remote, | ||
| 228 | sizeof(remote.sun_family) + len, &un->tm); | ||
| 229 | #endif | ||
| 230 | if (err != IO_DONE) socket_destroy(&un->sock); | ||
| 231 | return socket_strerror(err); | ||
| 232 | } | ||
| 233 | 52 | ||
| 234 | static int meth_connect(lua_State *L) | 53 | for (i = 0; mod[i].name; i++) |
| 235 | { | 54 | mod[i].func(L); |
| 236 | p_unix un = (p_unix) auxiliar_checkclass(L, "unix{master}", 1); | ||
| 237 | const char *path = luaL_checkstring(L, 2); | ||
| 238 | const char *err = unix_tryconnect(un, path); | ||
| 239 | if (err) { | ||
| 240 | lua_pushnil(L); | ||
| 241 | lua_pushstring(L, err); | ||
| 242 | return 2; | ||
| 243 | } | ||
| 244 | /* turn master object into a client object */ | ||
| 245 | auxiliar_setclass(L, "unix{client}", 1); | ||
| 246 | lua_pushnumber(L, 1); | ||
| 247 | return 1; | ||
| 248 | } | ||
| 249 | 55 | ||
| 250 | /*-------------------------------------------------------------------------*\ | 56 | /* Add backwards compatibility aliases "tcp" and "udp" for the "stream" and |
| 251 | * Closes socket used by object | 57 | * "dgram" functions. */ |
| 252 | \*-------------------------------------------------------------------------*/ | 58 | add_alias(L, socket_unix_table, "tcp", "stream"); |
| 253 | static int meth_close(lua_State *L) | 59 | add_alias(L, socket_unix_table, "udp", "dgram"); |
| 254 | { | ||
| 255 | p_unix un = (p_unix) auxiliar_checkgroup(L, "unix{any}", 1); | ||
| 256 | socket_destroy(&un->sock); | ||
| 257 | lua_pushnumber(L, 1); | ||
| 258 | return 1; | ||
| 259 | } | ||
| 260 | 60 | ||
| 261 | /*-------------------------------------------------------------------------*\ | 61 | /* Add a backwards compatibility function and a metatable setup to call it |
| 262 | * Puts the sockt in listen mode | 62 | * for the old socket.unix() interface. */ |
| 263 | \*-------------------------------------------------------------------------*/ | 63 | lua_pushcfunction(L, compat_socket_unix_call); |
| 264 | static int meth_listen(lua_State *L) | 64 | lua_setfield(L, socket_unix_table, "__call"); |
| 265 | { | 65 | lua_pushvalue(L, socket_unix_table); |
| 266 | p_unix un = (p_unix) auxiliar_checkclass(L, "unix{master}", 1); | 66 | lua_setmetatable(L, socket_unix_table); |
| 267 | int backlog = (int) luaL_optnumber(L, 2, 32); | ||
| 268 | int err = socket_listen(&un->sock, backlog); | ||
| 269 | if (err != IO_DONE) { | ||
| 270 | lua_pushnil(L); | ||
| 271 | lua_pushstring(L, socket_strerror(err)); | ||
| 272 | return 2; | ||
| 273 | } | ||
| 274 | /* turn master object into a server object */ | ||
| 275 | auxiliar_setclass(L, "unix{server}", 1); | ||
| 276 | lua_pushnumber(L, 1); | ||
| 277 | return 1; | ||
| 278 | } | ||
| 279 | 67 | ||
| 280 | /*-------------------------------------------------------------------------*\ | ||
| 281 | * Shuts the connection down partially | ||
| 282 | \*-------------------------------------------------------------------------*/ | ||
| 283 | static int meth_shutdown(lua_State *L) | ||
| 284 | { | ||
| 285 | /* SHUT_RD, SHUT_WR, SHUT_RDWR have the value 0, 1, 2, so we can use method index directly */ | ||
| 286 | static const char* methods[] = { "receive", "send", "both", NULL }; | ||
| 287 | p_unix tcp = (p_unix) auxiliar_checkclass(L, "unix{client}", 1); | ||
| 288 | int how = luaL_checkoption(L, 2, "both", methods); | ||
| 289 | socket_shutdown(&tcp->sock, how); | ||
| 290 | lua_pushnumber(L, 1); | ||
| 291 | return 1; | 68 | return 1; |
| 292 | } | 69 | } |
| 293 | |||
| 294 | /*-------------------------------------------------------------------------*\ | ||
| 295 | * Just call tm methods | ||
| 296 | \*-------------------------------------------------------------------------*/ | ||
| 297 | static int meth_settimeout(lua_State *L) { | ||
| 298 | p_unix un = (p_unix) auxiliar_checkgroup(L, "unix{any}", 1); | ||
| 299 | return timeout_meth_settimeout(L, &un->tm); | ||
| 300 | } | ||
| 301 | |||
| 302 | /*=========================================================================*\ | ||
| 303 | * Library functions | ||
| 304 | \*=========================================================================*/ | ||
| 305 | /*-------------------------------------------------------------------------*\ | ||
| 306 | * Creates a master unix object | ||
| 307 | \*-------------------------------------------------------------------------*/ | ||
| 308 | static int global_create(lua_State *L) { | ||
| 309 | t_socket sock; | ||
| 310 | int err = socket_create(&sock, AF_UNIX, SOCK_STREAM, 0); | ||
| 311 | /* try to allocate a system socket */ | ||
| 312 | if (err == IO_DONE) { | ||
| 313 | /* allocate unix object */ | ||
| 314 | p_unix un = (p_unix) lua_newuserdata(L, sizeof(t_unix)); | ||
| 315 | /* set its type as master object */ | ||
| 316 | auxiliar_setclass(L, "unix{master}", -1); | ||
| 317 | /* initialize remaining structure fields */ | ||
| 318 | socket_setnonblocking(&sock); | ||
| 319 | un->sock = sock; | ||
| 320 | io_init(&un->io, (p_send) socket_send, (p_recv) socket_recv, | ||
| 321 | (p_error) socket_ioerror, &un->sock); | ||
| 322 | timeout_init(&un->tm, -1, -1); | ||
| 323 | buffer_init(&un->buf, &un->io, &un->tm); | ||
| 324 | return 1; | ||
| 325 | } else { | ||
| 326 | lua_pushnil(L); | ||
| 327 | lua_pushstring(L, socket_strerror(err)); | ||
| 328 | return 2; | ||
| 329 | } | ||
| 330 | } | ||
| @@ -7,16 +7,12 @@ | |||
| 7 | * This module is just an example of how to extend LuaSocket with a new | 7 | * This module is just an example of how to extend LuaSocket with a new |
| 8 | * domain. | 8 | * domain. |
| 9 | \*=========================================================================*/ | 9 | \*=========================================================================*/ |
| 10 | #include "lua.h" | 10 | #include "luasocket.h" |
| 11 | 11 | ||
| 12 | #include "buffer.h" | 12 | #include "buffer.h" |
| 13 | #include "timeout.h" | 13 | #include "timeout.h" |
| 14 | #include "socket.h" | 14 | #include "socket.h" |
| 15 | 15 | ||
| 16 | #ifndef UNIX_API | ||
| 17 | #define UNIX_API extern | ||
| 18 | #endif | ||
| 19 | |||
| 20 | typedef struct t_unix_ { | 16 | typedef struct t_unix_ { |
| 21 | t_socket sock; | 17 | t_socket sock; |
| 22 | t_io io; | 18 | t_io io; |
| @@ -25,6 +21,6 @@ typedef struct t_unix_ { | |||
| 25 | } t_unix; | 21 | } t_unix; |
| 26 | typedef t_unix *p_unix; | 22 | typedef t_unix *p_unix; |
| 27 | 23 | ||
| 28 | UNIX_API int luaopen_socket_unix(lua_State *L); | 24 | LUASOCKET_API int luaopen_socket_unix(lua_State *L); |
| 29 | 25 | ||
| 30 | #endif /* UNIX_H */ | 26 | #endif /* UNIX_H */ |
diff --git a/src/unixdgram.c b/src/unixdgram.c new file mode 100644 index 0000000..69093d7 --- /dev/null +++ b/src/unixdgram.c | |||
| @@ -0,0 +1,405 @@ | |||
| 1 | /*=========================================================================*\ | ||
| 2 | * Unix domain socket dgram submodule | ||
| 3 | * LuaSocket toolkit | ||
| 4 | \*=========================================================================*/ | ||
| 5 | #include "luasocket.h" | ||
| 6 | |||
| 7 | #include "auxiliar.h" | ||
| 8 | #include "socket.h" | ||
| 9 | #include "options.h" | ||
| 10 | #include "unix.h" | ||
| 11 | |||
| 12 | #include <string.h> | ||
| 13 | #include <stdlib.h> | ||
| 14 | |||
| 15 | #include <sys/un.h> | ||
| 16 | |||
| 17 | #define UNIXDGRAM_DATAGRAMSIZE 8192 | ||
| 18 | |||
| 19 | /* provide a SUN_LEN macro if sys/un.h doesn't (e.g. Android) */ | ||
| 20 | #ifndef SUN_LEN | ||
| 21 | #define SUN_LEN(ptr) \ | ||
| 22 | ((size_t) (((struct sockaddr_un *) 0)->sun_path) \ | ||
| 23 | + strlen ((ptr)->sun_path)) | ||
| 24 | #endif | ||
| 25 | |||
| 26 | /*=========================================================================*\ | ||
| 27 | * Internal function prototypes | ||
| 28 | \*=========================================================================*/ | ||
| 29 | static int global_create(lua_State *L); | ||
| 30 | static int meth_connect(lua_State *L); | ||
| 31 | static int meth_bind(lua_State *L); | ||
| 32 | static int meth_send(lua_State *L); | ||
| 33 | static int meth_receive(lua_State *L); | ||
| 34 | static int meth_close(lua_State *L); | ||
| 35 | static int meth_setoption(lua_State *L); | ||
| 36 | static int meth_settimeout(lua_State *L); | ||
| 37 | static int meth_gettimeout(lua_State *L); | ||
| 38 | static int meth_getfd(lua_State *L); | ||
| 39 | static int meth_setfd(lua_State *L); | ||
| 40 | static int meth_dirty(lua_State *L); | ||
| 41 | static int meth_receivefrom(lua_State *L); | ||
| 42 | static int meth_sendto(lua_State *L); | ||
| 43 | static int meth_getsockname(lua_State *L); | ||
| 44 | |||
| 45 | static const char *unixdgram_tryconnect(p_unix un, const char *path); | ||
| 46 | static const char *unixdgram_trybind(p_unix un, const char *path); | ||
| 47 | |||
| 48 | /* unixdgram object methods */ | ||
| 49 | static luaL_Reg unixdgram_methods[] = { | ||
| 50 | {"__gc", meth_close}, | ||
| 51 | {"__tostring", auxiliar_tostring}, | ||
| 52 | {"bind", meth_bind}, | ||
| 53 | {"close", meth_close}, | ||
| 54 | {"connect", meth_connect}, | ||
| 55 | {"dirty", meth_dirty}, | ||
| 56 | {"getfd", meth_getfd}, | ||
| 57 | {"send", meth_send}, | ||
| 58 | {"sendto", meth_sendto}, | ||
| 59 | {"receive", meth_receive}, | ||
| 60 | {"receivefrom", meth_receivefrom}, | ||
| 61 | {"setfd", meth_setfd}, | ||
| 62 | {"setoption", meth_setoption}, | ||
| 63 | {"setpeername", meth_connect}, | ||
| 64 | {"setsockname", meth_bind}, | ||
| 65 | {"getsockname", meth_getsockname}, | ||
| 66 | {"settimeout", meth_settimeout}, | ||
| 67 | {"gettimeout", meth_gettimeout}, | ||
| 68 | {NULL, NULL} | ||
| 69 | }; | ||
| 70 | |||
| 71 | /* socket option handlers */ | ||
| 72 | static t_opt optset[] = { | ||
| 73 | {"reuseaddr", opt_set_reuseaddr}, | ||
| 74 | {NULL, NULL} | ||
| 75 | }; | ||
| 76 | |||
| 77 | /* functions in library namespace */ | ||
| 78 | static luaL_Reg func[] = { | ||
| 79 | {"dgram", global_create}, | ||
| 80 | {NULL, NULL} | ||
| 81 | }; | ||
| 82 | |||
| 83 | /*-------------------------------------------------------------------------*\ | ||
| 84 | * Initializes module | ||
| 85 | \*-------------------------------------------------------------------------*/ | ||
| 86 | int unixdgram_open(lua_State *L) | ||
| 87 | { | ||
| 88 | /* create classes */ | ||
| 89 | auxiliar_newclass(L, "unixdgram{connected}", unixdgram_methods); | ||
| 90 | auxiliar_newclass(L, "unixdgram{unconnected}", unixdgram_methods); | ||
| 91 | /* create class groups */ | ||
| 92 | auxiliar_add2group(L, "unixdgram{connected}", "unixdgram{any}"); | ||
| 93 | auxiliar_add2group(L, "unixdgram{unconnected}", "unixdgram{any}"); | ||
| 94 | auxiliar_add2group(L, "unixdgram{connected}", "select{able}"); | ||
| 95 | auxiliar_add2group(L, "unixdgram{unconnected}", "select{able}"); | ||
| 96 | |||
| 97 | luaL_setfuncs(L, func, 0); | ||
| 98 | return 0; | ||
| 99 | } | ||
| 100 | |||
| 101 | /*=========================================================================*\ | ||
| 102 | * Lua methods | ||
| 103 | \*=========================================================================*/ | ||
| 104 | static const char *unixdgram_strerror(int err) | ||
| 105 | { | ||
| 106 | /* a 'closed' error on an unconnected means the target address was not | ||
| 107 | * accepted by the transport layer */ | ||
| 108 | if (err == IO_CLOSED) return "refused"; | ||
| 109 | else return socket_strerror(err); | ||
| 110 | } | ||
| 111 | |||
| 112 | static int meth_send(lua_State *L) | ||
| 113 | { | ||
| 114 | p_unix un = (p_unix) auxiliar_checkclass(L, "unixdgram{connected}", 1); | ||
| 115 | p_timeout tm = &un->tm; | ||
| 116 | size_t count, sent = 0; | ||
| 117 | int err; | ||
| 118 | const char *data = luaL_checklstring(L, 2, &count); | ||
| 119 | timeout_markstart(tm); | ||
| 120 | err = socket_send(&un->sock, data, count, &sent, tm); | ||
| 121 | if (err != IO_DONE) { | ||
| 122 | lua_pushnil(L); | ||
| 123 | lua_pushstring(L, unixdgram_strerror(err)); | ||
| 124 | return 2; | ||
| 125 | } | ||
| 126 | lua_pushnumber(L, (lua_Number) sent); | ||
| 127 | return 1; | ||
| 128 | } | ||
| 129 | |||
| 130 | /*-------------------------------------------------------------------------*\ | ||
| 131 | * Send data through unconnected unixdgram socket | ||
| 132 | \*-------------------------------------------------------------------------*/ | ||
| 133 | static int meth_sendto(lua_State *L) | ||
| 134 | { | ||
| 135 | p_unix un = (p_unix) auxiliar_checkclass(L, "unixdgram{unconnected}", 1); | ||
| 136 | size_t count, sent = 0; | ||
| 137 | const char *data = luaL_checklstring(L, 2, &count); | ||
| 138 | const char *path = luaL_checkstring(L, 3); | ||
| 139 | p_timeout tm = &un->tm; | ||
| 140 | int err; | ||
| 141 | struct sockaddr_un remote; | ||
| 142 | size_t len = strlen(path); | ||
| 143 | |||
| 144 | if (len >= sizeof(remote.sun_path)) { | ||
| 145 | lua_pushnil(L); | ||
| 146 | lua_pushstring(L, "path too long"); | ||
| 147 | return 2; | ||
| 148 | } | ||
| 149 | |||
| 150 | memset(&remote, 0, sizeof(remote)); | ||
| 151 | strcpy(remote.sun_path, path); | ||
| 152 | remote.sun_family = AF_UNIX; | ||
| 153 | timeout_markstart(tm); | ||
| 154 | #ifdef UNIX_HAS_SUN_LEN | ||
| 155 | remote.sun_len = sizeof(remote.sun_family) + sizeof(remote.sun_len) | ||
| 156 | + len + 1; | ||
| 157 | err = socket_sendto(&un->sock, data, count, &sent, (SA *) &remote, remote.sun_len, tm); | ||
| 158 | #else | ||
| 159 | err = socket_sendto(&un->sock, data, count, &sent, (SA *) &remote, | ||
| 160 | sizeof(remote.sun_family) + len, tm); | ||
| 161 | #endif | ||
| 162 | if (err != IO_DONE) { | ||
| 163 | lua_pushnil(L); | ||
| 164 | lua_pushstring(L, unixdgram_strerror(err)); | ||
| 165 | return 2; | ||
| 166 | } | ||
| 167 | lua_pushnumber(L, (lua_Number) sent); | ||
| 168 | return 1; | ||
| 169 | } | ||
| 170 | |||
| 171 | static int meth_receive(lua_State *L) { | ||
| 172 | p_unix un = (p_unix) auxiliar_checkgroup(L, "unixdgram{any}", 1); | ||
| 173 | char buf[UNIXDGRAM_DATAGRAMSIZE]; | ||
| 174 | size_t got, wanted = (size_t) luaL_optnumber(L, 2, sizeof(buf)); | ||
| 175 | char *dgram = wanted > sizeof(buf)? (char *) malloc(wanted): buf; | ||
| 176 | int err; | ||
| 177 | p_timeout tm = &un->tm; | ||
| 178 | timeout_markstart(tm); | ||
| 179 | if (!dgram) { | ||
| 180 | lua_pushnil(L); | ||
| 181 | lua_pushliteral(L, "out of memory"); | ||
| 182 | return 2; | ||
| 183 | } | ||
| 184 | err = socket_recv(&un->sock, dgram, wanted, &got, tm); | ||
| 185 | /* Unlike STREAM, recv() of zero is not closed, but a zero-length packet. */ | ||
| 186 | if (err != IO_DONE && err != IO_CLOSED) { | ||
| 187 | lua_pushnil(L); | ||
| 188 | lua_pushstring(L, unixdgram_strerror(err)); | ||
| 189 | if (wanted > sizeof(buf)) free(dgram); | ||
| 190 | return 2; | ||
| 191 | } | ||
| 192 | lua_pushlstring(L, dgram, got); | ||
| 193 | if (wanted > sizeof(buf)) free(dgram); | ||
| 194 | return 1; | ||
| 195 | } | ||
| 196 | |||
| 197 | /*-------------------------------------------------------------------------*\ | ||
| 198 | * Receives data and sender from a DGRAM socket | ||
| 199 | \*-------------------------------------------------------------------------*/ | ||
| 200 | static int meth_receivefrom(lua_State *L) { | ||
| 201 | p_unix un = (p_unix) auxiliar_checkclass(L, "unixdgram{unconnected}", 1); | ||
| 202 | char buf[UNIXDGRAM_DATAGRAMSIZE]; | ||
| 203 | size_t got, wanted = (size_t) luaL_optnumber(L, 2, sizeof(buf)); | ||
| 204 | char *dgram = wanted > sizeof(buf)? (char *) malloc(wanted): buf; | ||
| 205 | struct sockaddr_un addr; | ||
| 206 | socklen_t addr_len = sizeof(addr); | ||
| 207 | int err; | ||
| 208 | p_timeout tm = &un->tm; | ||
| 209 | timeout_markstart(tm); | ||
| 210 | if (!dgram) { | ||
| 211 | lua_pushnil(L); | ||
| 212 | lua_pushliteral(L, "out of memory"); | ||
| 213 | return 2; | ||
| 214 | } | ||
| 215 | addr.sun_path[0] = '\0'; | ||
| 216 | err = socket_recvfrom(&un->sock, dgram, wanted, &got, (SA *) &addr, | ||
| 217 | &addr_len, tm); | ||
| 218 | /* Unlike STREAM, recv() of zero is not closed, but a zero-length packet. */ | ||
| 219 | if (err != IO_DONE && err != IO_CLOSED) { | ||
| 220 | lua_pushnil(L); | ||
| 221 | lua_pushstring(L, unixdgram_strerror(err)); | ||
| 222 | if (wanted > sizeof(buf)) free(dgram); | ||
| 223 | return 2; | ||
| 224 | } | ||
| 225 | |||
| 226 | lua_pushlstring(L, dgram, got); | ||
| 227 | /* the path may be empty, when client send without bind */ | ||
| 228 | lua_pushstring(L, addr.sun_path); | ||
| 229 | if (wanted > sizeof(buf)) free(dgram); | ||
| 230 | return 2; | ||
| 231 | } | ||
| 232 | |||
| 233 | /*-------------------------------------------------------------------------*\ | ||
| 234 | * Just call option handler | ||
| 235 | \*-------------------------------------------------------------------------*/ | ||
| 236 | static int meth_setoption(lua_State *L) { | ||
| 237 | p_unix un = (p_unix) auxiliar_checkgroup(L, "unixdgram{any}", 1); | ||
| 238 | return opt_meth_setoption(L, optset, &un->sock); | ||
| 239 | } | ||
| 240 | |||
| 241 | /*-------------------------------------------------------------------------*\ | ||
| 242 | * Select support methods | ||
| 243 | \*-------------------------------------------------------------------------*/ | ||
| 244 | static int meth_getfd(lua_State *L) { | ||
| 245 | p_unix un = (p_unix) auxiliar_checkgroup(L, "unixdgram{any}", 1); | ||
| 246 | lua_pushnumber(L, (int) un->sock); | ||
| 247 | return 1; | ||
| 248 | } | ||
| 249 | |||
| 250 | /* this is very dangerous, but can be handy for those that are brave enough */ | ||
| 251 | static int meth_setfd(lua_State *L) { | ||
| 252 | p_unix un = (p_unix) auxiliar_checkgroup(L, "unixdgram{any}", 1); | ||
| 253 | un->sock = (t_socket) luaL_checknumber(L, 2); | ||
| 254 | return 0; | ||
| 255 | } | ||
| 256 | |||
| 257 | static int meth_dirty(lua_State *L) { | ||
| 258 | p_unix un = (p_unix) auxiliar_checkgroup(L, "unixdgram{any}", 1); | ||
| 259 | (void) un; | ||
| 260 | lua_pushboolean(L, 0); | ||
| 261 | return 1; | ||
| 262 | } | ||
| 263 | |||
| 264 | /*-------------------------------------------------------------------------*\ | ||
| 265 | * Binds an object to an address | ||
| 266 | \*-------------------------------------------------------------------------*/ | ||
| 267 | static const char *unixdgram_trybind(p_unix un, const char *path) { | ||
| 268 | struct sockaddr_un local; | ||
| 269 | size_t len = strlen(path); | ||
| 270 | if (len >= sizeof(local.sun_path)) return "path too long"; | ||
| 271 | memset(&local, 0, sizeof(local)); | ||
| 272 | strcpy(local.sun_path, path); | ||
| 273 | local.sun_family = AF_UNIX; | ||
| 274 | size_t addrlen = SUN_LEN(&local); | ||
| 275 | #ifdef UNIX_HAS_SUN_LEN | ||
| 276 | local.sun_len = addrlen + 1; | ||
| 277 | #endif | ||
| 278 | int err = socket_bind(&un->sock, (SA *) &local, addrlen); | ||
| 279 | if (err != IO_DONE) socket_destroy(&un->sock); | ||
| 280 | return socket_strerror(err); | ||
| 281 | } | ||
| 282 | |||
| 283 | static int meth_bind(lua_State *L) | ||
| 284 | { | ||
| 285 | p_unix un = (p_unix) auxiliar_checkclass(L, "unixdgram{unconnected}", 1); | ||
| 286 | const char *path = luaL_checkstring(L, 2); | ||
| 287 | const char *err = unixdgram_trybind(un, path); | ||
| 288 | if (err) { | ||
| 289 | lua_pushnil(L); | ||
| 290 | lua_pushstring(L, err); | ||
| 291 | return 2; | ||
| 292 | } | ||
| 293 | lua_pushnumber(L, 1); | ||
| 294 | return 1; | ||
| 295 | } | ||
| 296 | |||
| 297 | static int meth_getsockname(lua_State *L) | ||
| 298 | { | ||
| 299 | p_unix un = (p_unix) auxiliar_checkgroup(L, "unixdgram{any}", 1); | ||
| 300 | struct sockaddr_un peer = {0}; | ||
| 301 | socklen_t peer_len = sizeof(peer); | ||
| 302 | |||
| 303 | if (getsockname(un->sock, (SA *) &peer, &peer_len) < 0) { | ||
| 304 | lua_pushnil(L); | ||
| 305 | lua_pushstring(L, socket_strerror(errno)); | ||
| 306 | return 2; | ||
| 307 | } | ||
| 308 | |||
| 309 | lua_pushstring(L, peer.sun_path); | ||
| 310 | return 1; | ||
| 311 | } | ||
| 312 | |||
| 313 | /*-------------------------------------------------------------------------*\ | ||
| 314 | * Turns a master unixdgram object into a client object. | ||
| 315 | \*-------------------------------------------------------------------------*/ | ||
| 316 | static const char *unixdgram_tryconnect(p_unix un, const char *path) | ||
| 317 | { | ||
| 318 | struct sockaddr_un remote; | ||
| 319 | size_t len = strlen(path); | ||
| 320 | if (len >= sizeof(remote.sun_path)) return "path too long"; | ||
| 321 | memset(&remote, 0, sizeof(remote)); | ||
| 322 | strcpy(remote.sun_path, path); | ||
| 323 | remote.sun_family = AF_UNIX; | ||
| 324 | timeout_markstart(&un->tm); | ||
| 325 | size_t addrlen = SUN_LEN(&remote); | ||
| 326 | #ifdef UNIX_HAS_SUN_LEN | ||
| 327 | remote.sun_len = addrlen + 1; | ||
| 328 | #endif | ||
| 329 | int err = socket_connect(&un->sock, (SA *) &remote, addrlen, &un->tm); | ||
| 330 | if (err != IO_DONE) socket_destroy(&un->sock); | ||
| 331 | return socket_strerror(err); | ||
| 332 | } | ||
| 333 | |||
| 334 | static int meth_connect(lua_State *L) | ||
| 335 | { | ||
| 336 | p_unix un = (p_unix) auxiliar_checkgroup(L, "unixdgram{any}", 1); | ||
| 337 | const char *path = luaL_checkstring(L, 2); | ||
| 338 | const char *err = unixdgram_tryconnect(un, path); | ||
| 339 | if (err) { | ||
| 340 | lua_pushnil(L); | ||
| 341 | lua_pushstring(L, err); | ||
| 342 | return 2; | ||
| 343 | } | ||
| 344 | /* turn unconnected object into a connected object */ | ||
| 345 | auxiliar_setclass(L, "unixdgram{connected}", 1); | ||
| 346 | lua_pushnumber(L, 1); | ||
| 347 | return 1; | ||
| 348 | } | ||
| 349 | |||
| 350 | /*-------------------------------------------------------------------------*\ | ||
| 351 | * Closes socket used by object | ||
| 352 | \*-------------------------------------------------------------------------*/ | ||
| 353 | static int meth_close(lua_State *L) | ||
| 354 | { | ||
| 355 | p_unix un = (p_unix) auxiliar_checkgroup(L, "unixdgram{any}", 1); | ||
| 356 | socket_destroy(&un->sock); | ||
| 357 | lua_pushnumber(L, 1); | ||
| 358 | return 1; | ||
| 359 | } | ||
| 360 | |||
| 361 | /*-------------------------------------------------------------------------*\ | ||
| 362 | * Just call tm methods | ||
| 363 | \*-------------------------------------------------------------------------*/ | ||
| 364 | static int meth_settimeout(lua_State *L) | ||
| 365 | { | ||
| 366 | p_unix un = (p_unix) auxiliar_checkgroup(L, "unixdgram{any}", 1); | ||
| 367 | return timeout_meth_settimeout(L, &un->tm); | ||
| 368 | } | ||
| 369 | |||
| 370 | static int meth_gettimeout(lua_State *L) | ||
| 371 | { | ||
| 372 | p_unix un = (p_unix) auxiliar_checkgroup(L, "unixdgram{any}", 1); | ||
| 373 | return timeout_meth_gettimeout(L, &un->tm); | ||
| 374 | } | ||
| 375 | |||
| 376 | /*=========================================================================*\ | ||
| 377 | * Library functions | ||
| 378 | \*=========================================================================*/ | ||
| 379 | /*-------------------------------------------------------------------------*\ | ||
| 380 | * Creates a master unixdgram object | ||
| 381 | \*-------------------------------------------------------------------------*/ | ||
| 382 | static int global_create(lua_State *L) | ||
| 383 | { | ||
| 384 | t_socket sock; | ||
| 385 | int err = socket_create(&sock, AF_UNIX, SOCK_DGRAM, 0); | ||
| 386 | /* try to allocate a system socket */ | ||
| 387 | if (err == IO_DONE) { | ||
| 388 | /* allocate unixdgram object */ | ||
| 389 | p_unix un = (p_unix) lua_newuserdata(L, sizeof(t_unix)); | ||
| 390 | /* set its type as master object */ | ||
| 391 | auxiliar_setclass(L, "unixdgram{unconnected}", -1); | ||
| 392 | /* initialize remaining structure fields */ | ||
| 393 | socket_setnonblocking(&sock); | ||
| 394 | un->sock = sock; | ||
| 395 | io_init(&un->io, (p_send) socket_send, (p_recv) socket_recv, | ||
| 396 | (p_error) socket_ioerror, &un->sock); | ||
| 397 | timeout_init(&un->tm, -1, -1); | ||
| 398 | buffer_init(&un->buf, &un->io, &un->tm); | ||
| 399 | return 1; | ||
| 400 | } else { | ||
| 401 | lua_pushnil(L); | ||
| 402 | lua_pushstring(L, socket_strerror(err)); | ||
| 403 | return 2; | ||
| 404 | } | ||
| 405 | } | ||
diff --git a/src/unixdgram.h b/src/unixdgram.h new file mode 100644 index 0000000..a1a0166 --- /dev/null +++ b/src/unixdgram.h | |||
| @@ -0,0 +1,28 @@ | |||
| 1 | #ifndef UNIXDGRAM_H | ||
| 2 | #define UNIXDGRAM_H | ||
| 3 | /*=========================================================================*\ | ||
| 4 | * DGRAM object | ||
| 5 | * LuaSocket toolkit | ||
| 6 | * | ||
| 7 | * The dgram.h module provides LuaSocket with support for DGRAM protocol | ||
| 8 | * (AF_INET, SOCK_DGRAM). | ||
| 9 | * | ||
| 10 | * Two classes are defined: connected and unconnected. DGRAM 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 | |||
| 16 | #include "unix.h" | ||
| 17 | |||
| 18 | #ifndef _WIN32 | ||
| 19 | #pragma GCC visibility push(hidden) | ||
| 20 | #endif | ||
| 21 | |||
| 22 | int unixdgram_open(lua_State *L); | ||
| 23 | |||
| 24 | #ifndef _WIN32 | ||
| 25 | #pragma GCC visibility pop | ||
| 26 | #endif | ||
| 27 | |||
| 28 | #endif /* UNIXDGRAM_H */ | ||
diff --git a/src/unixstream.c b/src/unixstream.c new file mode 100644 index 0000000..02aced9 --- /dev/null +++ b/src/unixstream.c | |||
| @@ -0,0 +1,355 @@ | |||
| 1 | /*=========================================================================*\ | ||
| 2 | * Unix domain socket stream sub module | ||
| 3 | * LuaSocket toolkit | ||
| 4 | \*=========================================================================*/ | ||
| 5 | #include "luasocket.h" | ||
| 6 | |||
| 7 | #include "auxiliar.h" | ||
| 8 | #include "socket.h" | ||
| 9 | #include "options.h" | ||
| 10 | #include "unixstream.h" | ||
| 11 | |||
| 12 | #include <string.h> | ||
| 13 | #include <sys/un.h> | ||
| 14 | |||
| 15 | /*=========================================================================*\ | ||
| 16 | * Internal function prototypes | ||
| 17 | \*=========================================================================*/ | ||
| 18 | static int global_create(lua_State *L); | ||
| 19 | static int meth_connect(lua_State *L); | ||
| 20 | static int meth_listen(lua_State *L); | ||
| 21 | static int meth_bind(lua_State *L); | ||
| 22 | static int meth_send(lua_State *L); | ||
| 23 | static int meth_shutdown(lua_State *L); | ||
| 24 | static int meth_receive(lua_State *L); | ||
| 25 | static int meth_accept(lua_State *L); | ||
| 26 | static int meth_close(lua_State *L); | ||
| 27 | static int meth_setoption(lua_State *L); | ||
| 28 | static int meth_settimeout(lua_State *L); | ||
| 29 | static int meth_getfd(lua_State *L); | ||
| 30 | static int meth_setfd(lua_State *L); | ||
| 31 | static int meth_dirty(lua_State *L); | ||
| 32 | static int meth_getstats(lua_State *L); | ||
| 33 | static int meth_setstats(lua_State *L); | ||
| 34 | static int meth_getsockname(lua_State *L); | ||
| 35 | |||
| 36 | static const char *unixstream_tryconnect(p_unix un, const char *path); | ||
| 37 | static const char *unixstream_trybind(p_unix un, const char *path); | ||
| 38 | |||
| 39 | /* unixstream object methods */ | ||
| 40 | static luaL_Reg unixstream_methods[] = { | ||
| 41 | {"__gc", meth_close}, | ||
| 42 | {"__tostring", auxiliar_tostring}, | ||
| 43 | {"accept", meth_accept}, | ||
| 44 | {"bind", meth_bind}, | ||
| 45 | {"close", meth_close}, | ||
| 46 | {"connect", meth_connect}, | ||
| 47 | {"dirty", meth_dirty}, | ||
| 48 | {"getfd", meth_getfd}, | ||
| 49 | {"getstats", meth_getstats}, | ||
| 50 | {"setstats", meth_setstats}, | ||
| 51 | {"listen", meth_listen}, | ||
| 52 | {"receive", meth_receive}, | ||
| 53 | {"send", meth_send}, | ||
| 54 | {"setfd", meth_setfd}, | ||
| 55 | {"setoption", meth_setoption}, | ||
| 56 | {"setpeername", meth_connect}, | ||
| 57 | {"setsockname", meth_bind}, | ||
| 58 | {"getsockname", meth_getsockname}, | ||
| 59 | {"settimeout", meth_settimeout}, | ||
| 60 | {"shutdown", meth_shutdown}, | ||
| 61 | {NULL, NULL} | ||
| 62 | }; | ||
| 63 | |||
| 64 | /* socket option handlers */ | ||
| 65 | static t_opt optset[] = { | ||
| 66 | {"keepalive", opt_set_keepalive}, | ||
| 67 | {"reuseaddr", opt_set_reuseaddr}, | ||
| 68 | {"linger", opt_set_linger}, | ||
| 69 | {NULL, NULL} | ||
| 70 | }; | ||
| 71 | |||
| 72 | /* functions in library namespace */ | ||
| 73 | static luaL_Reg func[] = { | ||
| 74 | {"stream", global_create}, | ||
| 75 | {NULL, NULL} | ||
| 76 | }; | ||
| 77 | |||
| 78 | /*-------------------------------------------------------------------------*\ | ||
| 79 | * Initializes module | ||
| 80 | \*-------------------------------------------------------------------------*/ | ||
| 81 | int unixstream_open(lua_State *L) | ||
| 82 | { | ||
| 83 | /* create classes */ | ||
| 84 | auxiliar_newclass(L, "unixstream{master}", unixstream_methods); | ||
| 85 | auxiliar_newclass(L, "unixstream{client}", unixstream_methods); | ||
| 86 | auxiliar_newclass(L, "unixstream{server}", unixstream_methods); | ||
| 87 | |||
| 88 | /* create class groups */ | ||
| 89 | auxiliar_add2group(L, "unixstream{master}", "unixstream{any}"); | ||
| 90 | auxiliar_add2group(L, "unixstream{client}", "unixstream{any}"); | ||
| 91 | auxiliar_add2group(L, "unixstream{server}", "unixstream{any}"); | ||
| 92 | |||
| 93 | luaL_setfuncs(L, func, 0); | ||
| 94 | return 0; | ||
| 95 | } | ||
| 96 | |||
| 97 | /*=========================================================================*\ | ||
| 98 | * Lua methods | ||
| 99 | \*=========================================================================*/ | ||
| 100 | /*-------------------------------------------------------------------------*\ | ||
| 101 | * Just call buffered IO methods | ||
| 102 | \*-------------------------------------------------------------------------*/ | ||
| 103 | static int meth_send(lua_State *L) { | ||
| 104 | p_unix un = (p_unix) auxiliar_checkclass(L, "unixstream{client}", 1); | ||
| 105 | return buffer_meth_send(L, &un->buf); | ||
| 106 | } | ||
| 107 | |||
| 108 | static int meth_receive(lua_State *L) { | ||
| 109 | p_unix un = (p_unix) auxiliar_checkclass(L, "unixstream{client}", 1); | ||
| 110 | return buffer_meth_receive(L, &un->buf); | ||
| 111 | } | ||
| 112 | |||
| 113 | static int meth_getstats(lua_State *L) { | ||
| 114 | p_unix un = (p_unix) auxiliar_checkclass(L, "unixstream{client}", 1); | ||
| 115 | return buffer_meth_getstats(L, &un->buf); | ||
| 116 | } | ||
| 117 | |||
| 118 | static int meth_setstats(lua_State *L) { | ||
| 119 | p_unix un = (p_unix) auxiliar_checkclass(L, "unixstream{client}", 1); | ||
| 120 | return buffer_meth_setstats(L, &un->buf); | ||
| 121 | } | ||
| 122 | |||
| 123 | /*-------------------------------------------------------------------------*\ | ||
| 124 | * Just call option handler | ||
| 125 | \*-------------------------------------------------------------------------*/ | ||
| 126 | static int meth_setoption(lua_State *L) { | ||
| 127 | p_unix un = (p_unix) auxiliar_checkgroup(L, "unixstream{any}", 1); | ||
| 128 | return opt_meth_setoption(L, optset, &un->sock); | ||
| 129 | } | ||
| 130 | |||
| 131 | /*-------------------------------------------------------------------------*\ | ||
| 132 | * Select support methods | ||
| 133 | \*-------------------------------------------------------------------------*/ | ||
| 134 | static int meth_getfd(lua_State *L) { | ||
| 135 | p_unix un = (p_unix) auxiliar_checkgroup(L, "unixstream{any}", 1); | ||
| 136 | lua_pushnumber(L, (int) un->sock); | ||
| 137 | return 1; | ||
| 138 | } | ||
| 139 | |||
| 140 | /* this is very dangerous, but can be handy for those that are brave enough */ | ||
| 141 | static int meth_setfd(lua_State *L) { | ||
| 142 | p_unix un = (p_unix) auxiliar_checkgroup(L, "unixstream{any}", 1); | ||
| 143 | un->sock = (t_socket) luaL_checknumber(L, 2); | ||
| 144 | return 0; | ||
| 145 | } | ||
| 146 | |||
| 147 | static int meth_dirty(lua_State *L) { | ||
| 148 | p_unix un = (p_unix) auxiliar_checkgroup(L, "unixstream{any}", 1); | ||
| 149 | lua_pushboolean(L, !buffer_isempty(&un->buf)); | ||
| 150 | return 1; | ||
| 151 | } | ||
| 152 | |||
| 153 | /*-------------------------------------------------------------------------*\ | ||
| 154 | * Waits for and returns a client object attempting connection to the | ||
| 155 | * server object | ||
| 156 | \*-------------------------------------------------------------------------*/ | ||
| 157 | static int meth_accept(lua_State *L) { | ||
| 158 | p_unix server = (p_unix) auxiliar_checkclass(L, "unixstream{server}", 1); | ||
| 159 | p_timeout tm = timeout_markstart(&server->tm); | ||
| 160 | t_socket sock; | ||
| 161 | int err = socket_accept(&server->sock, &sock, NULL, NULL, tm); | ||
| 162 | /* if successful, push client socket */ | ||
| 163 | if (err == IO_DONE) { | ||
| 164 | p_unix clnt = (p_unix) lua_newuserdata(L, sizeof(t_unix)); | ||
| 165 | auxiliar_setclass(L, "unixstream{client}", -1); | ||
| 166 | /* initialize structure fields */ | ||
| 167 | socket_setnonblocking(&sock); | ||
| 168 | clnt->sock = sock; | ||
| 169 | io_init(&clnt->io, (p_send)socket_send, (p_recv)socket_recv, | ||
| 170 | (p_error) socket_ioerror, &clnt->sock); | ||
| 171 | timeout_init(&clnt->tm, -1, -1); | ||
| 172 | buffer_init(&clnt->buf, &clnt->io, &clnt->tm); | ||
| 173 | return 1; | ||
| 174 | } else { | ||
| 175 | lua_pushnil(L); | ||
| 176 | lua_pushstring(L, socket_strerror(err)); | ||
| 177 | return 2; | ||
| 178 | } | ||
| 179 | } | ||
| 180 | |||
| 181 | /*-------------------------------------------------------------------------*\ | ||
| 182 | * Binds an object to an address | ||
| 183 | \*-------------------------------------------------------------------------*/ | ||
| 184 | static const char *unixstream_trybind(p_unix un, const char *path) { | ||
| 185 | struct sockaddr_un local; | ||
| 186 | size_t len = strlen(path); | ||
| 187 | int err; | ||
| 188 | if (len >= sizeof(local.sun_path)) return "path too long"; | ||
| 189 | memset(&local, 0, sizeof(local)); | ||
| 190 | strcpy(local.sun_path, path); | ||
| 191 | local.sun_family = AF_UNIX; | ||
| 192 | #ifdef UNIX_HAS_SUN_LEN | ||
| 193 | local.sun_len = sizeof(local.sun_family) + sizeof(local.sun_len) | ||
| 194 | + len + 1; | ||
| 195 | err = socket_bind(&un->sock, (SA *) &local, local.sun_len); | ||
| 196 | |||
| 197 | #else | ||
| 198 | err = socket_bind(&un->sock, (SA *) &local, | ||
| 199 | sizeof(local.sun_family) + len); | ||
| 200 | #endif | ||
| 201 | if (err != IO_DONE) socket_destroy(&un->sock); | ||
| 202 | return socket_strerror(err); | ||
| 203 | } | ||
| 204 | |||
| 205 | static int meth_bind(lua_State *L) { | ||
| 206 | p_unix un = (p_unix) auxiliar_checkclass(L, "unixstream{master}", 1); | ||
| 207 | const char *path = luaL_checkstring(L, 2); | ||
| 208 | const char *err = unixstream_trybind(un, path); | ||
| 209 | if (err) { | ||
| 210 | lua_pushnil(L); | ||
| 211 | lua_pushstring(L, err); | ||
| 212 | return 2; | ||
| 213 | } | ||
| 214 | lua_pushnumber(L, 1); | ||
| 215 | return 1; | ||
| 216 | } | ||
| 217 | |||
| 218 | static int meth_getsockname(lua_State *L) | ||
| 219 | { | ||
| 220 | p_unix un = (p_unix) auxiliar_checkgroup(L, "unixstream{any}", 1); | ||
| 221 | struct sockaddr_un peer = {0}; | ||
| 222 | socklen_t peer_len = sizeof(peer); | ||
| 223 | |||
| 224 | if (getsockname(un->sock, (SA *) &peer, &peer_len) < 0) { | ||
| 225 | lua_pushnil(L); | ||
| 226 | lua_pushstring(L, socket_strerror(errno)); | ||
| 227 | return 2; | ||
| 228 | } | ||
| 229 | |||
| 230 | lua_pushstring(L, peer.sun_path); | ||
| 231 | return 1; | ||
| 232 | } | ||
| 233 | |||
| 234 | /*-------------------------------------------------------------------------*\ | ||
| 235 | * Turns a master unixstream object into a client object. | ||
| 236 | \*-------------------------------------------------------------------------*/ | ||
| 237 | static const char *unixstream_tryconnect(p_unix un, const char *path) | ||
| 238 | { | ||
| 239 | struct sockaddr_un remote; | ||
| 240 | int err; | ||
| 241 | size_t len = strlen(path); | ||
| 242 | if (len >= sizeof(remote.sun_path)) return "path too long"; | ||
| 243 | memset(&remote, 0, sizeof(remote)); | ||
| 244 | strcpy(remote.sun_path, path); | ||
| 245 | remote.sun_family = AF_UNIX; | ||
| 246 | timeout_markstart(&un->tm); | ||
| 247 | #ifdef UNIX_HAS_SUN_LEN | ||
| 248 | remote.sun_len = sizeof(remote.sun_family) + sizeof(remote.sun_len) | ||
| 249 | + len + 1; | ||
| 250 | err = socket_connect(&un->sock, (SA *) &remote, remote.sun_len, &un->tm); | ||
| 251 | #else | ||
| 252 | err = socket_connect(&un->sock, (SA *) &remote, | ||
| 253 | sizeof(remote.sun_family) + len, &un->tm); | ||
| 254 | #endif | ||
| 255 | if (err != IO_DONE) socket_destroy(&un->sock); | ||
| 256 | return socket_strerror(err); | ||
| 257 | } | ||
| 258 | |||
| 259 | static int meth_connect(lua_State *L) | ||
| 260 | { | ||
| 261 | p_unix un = (p_unix) auxiliar_checkclass(L, "unixstream{master}", 1); | ||
| 262 | const char *path = luaL_checkstring(L, 2); | ||
| 263 | const char *err = unixstream_tryconnect(un, path); | ||
| 264 | if (err) { | ||
| 265 | lua_pushnil(L); | ||
| 266 | lua_pushstring(L, err); | ||
| 267 | return 2; | ||
| 268 | } | ||
| 269 | /* turn master object into a client object */ | ||
| 270 | auxiliar_setclass(L, "unixstream{client}", 1); | ||
| 271 | lua_pushnumber(L, 1); | ||
| 272 | return 1; | ||
| 273 | } | ||
| 274 | |||
| 275 | /*-------------------------------------------------------------------------*\ | ||
| 276 | * Closes socket used by object | ||
| 277 | \*-------------------------------------------------------------------------*/ | ||
| 278 | static int meth_close(lua_State *L) | ||
| 279 | { | ||
| 280 | p_unix un = (p_unix) auxiliar_checkgroup(L, "unixstream{any}", 1); | ||
| 281 | socket_destroy(&un->sock); | ||
| 282 | lua_pushnumber(L, 1); | ||
| 283 | return 1; | ||
| 284 | } | ||
| 285 | |||
| 286 | /*-------------------------------------------------------------------------*\ | ||
| 287 | * Puts the sockt in listen mode | ||
| 288 | \*-------------------------------------------------------------------------*/ | ||
| 289 | static int meth_listen(lua_State *L) | ||
| 290 | { | ||
| 291 | p_unix un = (p_unix) auxiliar_checkclass(L, "unixstream{master}", 1); | ||
| 292 | int backlog = (int) luaL_optnumber(L, 2, 32); | ||
| 293 | int err = socket_listen(&un->sock, backlog); | ||
| 294 | if (err != IO_DONE) { | ||
| 295 | lua_pushnil(L); | ||
| 296 | lua_pushstring(L, socket_strerror(err)); | ||
| 297 | return 2; | ||
| 298 | } | ||
| 299 | /* turn master object into a server object */ | ||
| 300 | auxiliar_setclass(L, "unixstream{server}", 1); | ||
| 301 | lua_pushnumber(L, 1); | ||
| 302 | return 1; | ||
| 303 | } | ||
| 304 | |||
| 305 | /*-------------------------------------------------------------------------*\ | ||
| 306 | * Shuts the connection down partially | ||
| 307 | \*-------------------------------------------------------------------------*/ | ||
| 308 | static int meth_shutdown(lua_State *L) | ||
| 309 | { | ||
| 310 | /* SHUT_RD, SHUT_WR, SHUT_RDWR have the value 0, 1, 2, so we can use method index directly */ | ||
| 311 | static const char* methods[] = { "receive", "send", "both", NULL }; | ||
| 312 | p_unix stream = (p_unix) auxiliar_checkclass(L, "unixstream{client}", 1); | ||
| 313 | int how = luaL_checkoption(L, 2, "both", methods); | ||
| 314 | socket_shutdown(&stream->sock, how); | ||
| 315 | lua_pushnumber(L, 1); | ||
| 316 | return 1; | ||
| 317 | } | ||
| 318 | |||
| 319 | /*-------------------------------------------------------------------------*\ | ||
| 320 | * Just call tm methods | ||
| 321 | \*-------------------------------------------------------------------------*/ | ||
| 322 | static int meth_settimeout(lua_State *L) { | ||
| 323 | p_unix un = (p_unix) auxiliar_checkgroup(L, "unixstream{any}", 1); | ||
| 324 | return timeout_meth_settimeout(L, &un->tm); | ||
| 325 | } | ||
| 326 | |||
| 327 | /*=========================================================================*\ | ||
| 328 | * Library functions | ||
| 329 | \*=========================================================================*/ | ||
| 330 | /*-------------------------------------------------------------------------*\ | ||
| 331 | * Creates a master unixstream object | ||
| 332 | \*-------------------------------------------------------------------------*/ | ||
| 333 | static int global_create(lua_State *L) { | ||
| 334 | t_socket sock; | ||
| 335 | int err = socket_create(&sock, AF_UNIX, SOCK_STREAM, 0); | ||
| 336 | /* try to allocate a system socket */ | ||
| 337 | if (err == IO_DONE) { | ||
| 338 | /* allocate unixstream object */ | ||
| 339 | p_unix un = (p_unix) lua_newuserdata(L, sizeof(t_unix)); | ||
| 340 | /* set its type as master object */ | ||
| 341 | auxiliar_setclass(L, "unixstream{master}", -1); | ||
| 342 | /* initialize remaining structure fields */ | ||
| 343 | socket_setnonblocking(&sock); | ||
| 344 | un->sock = sock; | ||
| 345 | io_init(&un->io, (p_send) socket_send, (p_recv) socket_recv, | ||
| 346 | (p_error) socket_ioerror, &un->sock); | ||
| 347 | timeout_init(&un->tm, -1, -1); | ||
| 348 | buffer_init(&un->buf, &un->io, &un->tm); | ||
| 349 | return 1; | ||
| 350 | } else { | ||
| 351 | lua_pushnil(L); | ||
| 352 | lua_pushstring(L, socket_strerror(err)); | ||
| 353 | return 2; | ||
| 354 | } | ||
| 355 | } | ||
diff --git a/src/unixstream.h b/src/unixstream.h new file mode 100644 index 0000000..7916aff --- /dev/null +++ b/src/unixstream.h | |||
| @@ -0,0 +1,29 @@ | |||
| 1 | #ifndef UNIXSTREAM_H | ||
| 2 | #define UNIXSTREAM_H | ||
| 3 | /*=========================================================================*\ | ||
| 4 | * UNIX STREAM object | ||
| 5 | * LuaSocket toolkit | ||
| 6 | * | ||
| 7 | * The unixstream.h module is basicly a glue that puts together modules buffer.h, | ||
| 8 | * timeout.h socket.h and inet.h to provide the LuaSocket UNIX STREAM (AF_UNIX, | ||
| 9 | * SOCK_STREAM) support. | ||
| 10 | * | ||
| 11 | * Three classes are defined: master, client and server. The master class is | ||
| 12 | * a newly created unixstream object, that has not been bound or connected. Server | ||
| 13 | * objects are unixstream objects bound to some local address. Client objects are | ||
| 14 | * unixstream objects either connected to some address or returned by the accept | ||
| 15 | * method of a server object. | ||
| 16 | \*=========================================================================*/ | ||
| 17 | #include "unix.h" | ||
| 18 | |||
| 19 | #ifndef _WIN32 | ||
| 20 | #pragma GCC visibility push(hidden) | ||
| 21 | #endif | ||
| 22 | |||
| 23 | int unixstream_open(lua_State *L); | ||
| 24 | |||
| 25 | #ifndef _WIN32 | ||
| 26 | #pragma GCC visibility pop | ||
| 27 | #endif | ||
| 28 | |||
| 29 | #endif /* UNIXSTREAM_H */ | ||
diff --git a/src/url.lua b/src/url.lua index 7809535..8e0dc5c 100644 --- a/src/url.lua +++ b/src/url.lua | |||
| @@ -49,7 +49,7 @@ local function make_set(t) | |||
| 49 | return s | 49 | return s |
| 50 | end | 50 | end |
| 51 | 51 | ||
| 52 | -- these are allowed withing a path segment, along with alphanum | 52 | -- these are allowed within a path segment, along with alphanum |
| 53 | -- other characters must be escaped | 53 | -- other characters must be escaped |
| 54 | local segment_set = make_set { | 54 | local segment_set = make_set { |
| 55 | "-", "_", ".", "!", "~", "*", "'", "(", | 55 | "-", "_", ".", "!", "~", "*", "'", "(", |
| @@ -59,16 +59,16 @@ local segment_set = make_set { | |||
| 59 | local function protect_segment(s) | 59 | local function protect_segment(s) |
| 60 | return string.gsub(s, "([^A-Za-z0-9_])", function (c) | 60 | return string.gsub(s, "([^A-Za-z0-9_])", function (c) |
| 61 | if segment_set[c] then return c | 61 | if segment_set[c] then return c |
| 62 | else return string.format("%%%02x", string.byte(c)) end | 62 | else return string.format("%%%02X", string.byte(c)) end |
| 63 | end) | 63 | end) |
| 64 | end | 64 | end |
| 65 | 65 | ||
| 66 | ----------------------------------------------------------------------------- | 66 | ----------------------------------------------------------------------------- |
| 67 | -- Encodes a string into its escaped hexadecimal representation | 67 | -- Unencodes a escaped hexadecimal string into its binary representation |
| 68 | -- Input | 68 | -- Input |
| 69 | -- s: binary string to be encoded | 69 | -- s: escaped hexadecimal string to be unencoded |
| 70 | -- Returns | 70 | -- Returns |
| 71 | -- escaped representation of string binary | 71 | -- unescaped binary representation of escaped hexadecimal binary |
| 72 | ----------------------------------------------------------------------------- | 72 | ----------------------------------------------------------------------------- |
| 73 | function _M.unescape(s) | 73 | function _M.unescape(s) |
| 74 | return (string.gsub(s, "%%(%x%x)", function(hex) | 74 | return (string.gsub(s, "%%(%x%x)", function(hex) |
| @@ -77,6 +77,34 @@ function _M.unescape(s) | |||
| 77 | end | 77 | end |
| 78 | 78 | ||
| 79 | ----------------------------------------------------------------------------- | 79 | ----------------------------------------------------------------------------- |
| 80 | -- Removes '..' and '.' components appropriately from a path. | ||
| 81 | -- Input | ||
| 82 | -- path | ||
| 83 | -- Returns | ||
| 84 | -- dot-normalized path | ||
| 85 | local function remove_dot_components(path) | ||
| 86 | local marker = string.char(1) | ||
| 87 | repeat | ||
| 88 | local was = path | ||
| 89 | path = path:gsub('//', '/'..marker..'/', 1) | ||
| 90 | until path == was | ||
| 91 | repeat | ||
| 92 | local was = path | ||
| 93 | path = path:gsub('/%./', '/', 1) | ||
| 94 | until path == was | ||
| 95 | repeat | ||
| 96 | local was = path | ||
| 97 | path = path:gsub('[^/]+/%.%./([^/]+)', '%1', 1) | ||
| 98 | until path == was | ||
| 99 | path = path:gsub('[^/]+/%.%./*$', '') | ||
| 100 | path = path:gsub('/%.%.$', '/') | ||
| 101 | path = path:gsub('/%.$', '/') | ||
| 102 | path = path:gsub('^/%.%./', '/') | ||
| 103 | path = path:gsub(marker, '') | ||
| 104 | return path | ||
| 105 | end | ||
| 106 | |||
| 107 | ----------------------------------------------------------------------------- | ||
| 80 | -- Builds a path from a base path and a relative path | 108 | -- Builds a path from a base path and a relative path |
| 81 | -- Input | 109 | -- Input |
| 82 | -- base_path | 110 | -- base_path |
| @@ -85,23 +113,12 @@ end | |||
| 85 | -- corresponding absolute path | 113 | -- corresponding absolute path |
| 86 | ----------------------------------------------------------------------------- | 114 | ----------------------------------------------------------------------------- |
| 87 | local function absolute_path(base_path, relative_path) | 115 | local function absolute_path(base_path, relative_path) |
| 88 | if string.sub(relative_path, 1, 1) == "/" then return relative_path end | 116 | if string.sub(relative_path, 1, 1) == "/" then |
| 89 | local path = string.gsub(base_path, "[^/]*$", "") | 117 | return remove_dot_components(relative_path) end |
| 90 | path = path .. relative_path | 118 | base_path = base_path:gsub("[^/]*$", "") |
| 91 | path = string.gsub(path, "([^/]*%./)", function (s) | 119 | if not base_path:find'/$' then base_path = base_path .. '/' end |
| 92 | if s ~= "./" then return s else return "" end | 120 | local path = base_path .. relative_path |
| 93 | end) | 121 | path = remove_dot_components(path) |
| 94 | path = string.gsub(path, "/%.$", "/") | ||
| 95 | local reduced | ||
| 96 | while reduced ~= path do | ||
| 97 | reduced = path | ||
| 98 | path = string.gsub(reduced, "([^/]*/%.%./)", function (s) | ||
| 99 | if s ~= "../../" then return "" else return s end | ||
| 100 | end) | ||
| 101 | end | ||
| 102 | path = string.gsub(reduced, "([^/]*/%.%.)$", function (s) | ||
| 103 | if s ~= "../.." then return "" else return s end | ||
| 104 | end) | ||
| 105 | return path | 122 | return path |
| 106 | end | 123 | end |
| 107 | 124 | ||
| @@ -131,11 +148,6 @@ function _M.parse(url, default) | |||
| 131 | if not url or url == "" then return nil, "invalid url" end | 148 | if not url or url == "" then return nil, "invalid url" end |
| 132 | -- remove whitespace | 149 | -- remove whitespace |
| 133 | -- url = string.gsub(url, "%s", "") | 150 | -- url = string.gsub(url, "%s", "") |
| 134 | -- get fragment | ||
| 135 | url = string.gsub(url, "#(.*)$", function(f) | ||
| 136 | parsed.fragment = f | ||
| 137 | return "" | ||
| 138 | end) | ||
| 139 | -- get scheme | 151 | -- get scheme |
| 140 | url = string.gsub(url, "^([%w][%w%+%-%.]*)%:", | 152 | url = string.gsub(url, "^([%w][%w%+%-%.]*)%:", |
| 141 | function(s) parsed.scheme = s; return "" end) | 153 | function(s) parsed.scheme = s; return "" end) |
| @@ -144,6 +156,11 @@ function _M.parse(url, default) | |||
| 144 | parsed.authority = n | 156 | parsed.authority = n |
| 145 | return "" | 157 | return "" |
| 146 | end) | 158 | end) |
| 159 | -- get fragment | ||
| 160 | url = string.gsub(url, "#(.*)$", function(f) | ||
| 161 | parsed.fragment = f | ||
| 162 | return "" | ||
| 163 | end) | ||
| 147 | -- get query string | 164 | -- get query string |
| 148 | url = string.gsub(url, "%?(.*)", function(q) | 165 | url = string.gsub(url, "%?(.*)", function(q) |
| 149 | parsed.query = q | 166 | parsed.query = q |
| @@ -162,9 +179,9 @@ function _M.parse(url, default) | |||
| 162 | function(u) parsed.userinfo = u; return "" end) | 179 | function(u) parsed.userinfo = u; return "" end) |
| 163 | authority = string.gsub(authority, ":([^:%]]*)$", | 180 | authority = string.gsub(authority, ":([^:%]]*)$", |
| 164 | function(p) parsed.port = p; return "" end) | 181 | function(p) parsed.port = p; return "" end) |
| 165 | if authority ~= "" then | 182 | if authority ~= "" then |
| 166 | -- IPv6? | 183 | -- IPv6? |
| 167 | parsed.host = string.match(authority, "^%[(.+)%]$") or authority | 184 | parsed.host = string.match(authority, "^%[(.+)%]$") or authority |
| 168 | end | 185 | end |
| 169 | local userinfo = parsed.userinfo | 186 | local userinfo = parsed.userinfo |
| 170 | if not userinfo then return parsed end | 187 | if not userinfo then return parsed end |
| @@ -183,8 +200,9 @@ end | |||
| 183 | -- a stringing with the corresponding URL | 200 | -- a stringing with the corresponding URL |
| 184 | ----------------------------------------------------------------------------- | 201 | ----------------------------------------------------------------------------- |
| 185 | function _M.build(parsed) | 202 | function _M.build(parsed) |
| 186 | local ppath = _M.parse_path(parsed.path or "") | 203 | --local ppath = _M.parse_path(parsed.path or "") |
| 187 | local url = _M.build_path(ppath) | 204 | --local url = _M.build_path(ppath) |
| 205 | local url = parsed.path or "" | ||
| 188 | if parsed.params then url = url .. ";" .. parsed.params end | 206 | if parsed.params then url = url .. ";" .. parsed.params end |
| 189 | if parsed.query then url = url .. "?" .. parsed.query end | 207 | if parsed.query then url = url .. "?" .. parsed.query end |
| 190 | local authority = parsed.authority | 208 | local authority = parsed.authority |
| @@ -193,7 +211,7 @@ function _M.build(parsed) | |||
| 193 | if string.find(authority, ":") then -- IPv6? | 211 | if string.find(authority, ":") then -- IPv6? |
| 194 | authority = "[" .. authority .. "]" | 212 | authority = "[" .. authority .. "]" |
| 195 | end | 213 | end |
| 196 | if parsed.port then authority = authority .. ":" .. parsed.port end | 214 | if parsed.port then authority = authority .. ":" .. base.tostring(parsed.port) end |
| 197 | local userinfo = parsed.userinfo | 215 | local userinfo = parsed.userinfo |
| 198 | if parsed.user then | 216 | if parsed.user then |
| 199 | userinfo = parsed.user | 217 | userinfo = parsed.user |
| @@ -219,16 +237,21 @@ end | |||
| 219 | -- corresponding absolute url | 237 | -- corresponding absolute url |
| 220 | ----------------------------------------------------------------------------- | 238 | ----------------------------------------------------------------------------- |
| 221 | function _M.absolute(base_url, relative_url) | 239 | function _M.absolute(base_url, relative_url) |
| 240 | local base_parsed | ||
| 222 | if base.type(base_url) == "table" then | 241 | if base.type(base_url) == "table" then |
| 223 | base_parsed = base_url | 242 | base_parsed = base_url |
| 224 | base_url = _M.build(base_parsed) | 243 | base_url = _M.build(base_parsed) |
| 225 | else | 244 | else |
| 226 | base_parsed = _M.parse(base_url) | 245 | base_parsed = _M.parse(base_url) |
| 227 | end | 246 | end |
| 247 | local result | ||
| 228 | local relative_parsed = _M.parse(relative_url) | 248 | local relative_parsed = _M.parse(relative_url) |
| 229 | if not base_parsed then return relative_url | 249 | if not base_parsed then |
| 230 | elseif not relative_parsed then return base_url | 250 | result = relative_url |
| 231 | elseif relative_parsed.scheme then return relative_url | 251 | elseif not relative_parsed then |
| 252 | result = base_url | ||
| 253 | elseif relative_parsed.scheme then | ||
| 254 | result = relative_url | ||
| 232 | else | 255 | else |
| 233 | relative_parsed.scheme = base_parsed.scheme | 256 | relative_parsed.scheme = base_parsed.scheme |
| 234 | if not relative_parsed.authority then | 257 | if not relative_parsed.authority then |
| @@ -241,13 +264,14 @@ function _M.absolute(base_url, relative_url) | |||
| 241 | relative_parsed.query = base_parsed.query | 264 | relative_parsed.query = base_parsed.query |
| 242 | end | 265 | end |
| 243 | end | 266 | end |
| 244 | else | 267 | else |
| 245 | relative_parsed.path = absolute_path(base_parsed.path or "", | 268 | relative_parsed.path = absolute_path(base_parsed.path or "", |
| 246 | relative_parsed.path) | 269 | relative_parsed.path) |
| 247 | end | 270 | end |
| 248 | end | 271 | end |
| 249 | return _M.build(relative_parsed) | 272 | result = _M.build(relative_parsed) |
| 250 | end | 273 | end |
| 274 | return remove_dot_components(result) | ||
| 251 | end | 275 | end |
| 252 | 276 | ||
| 253 | ----------------------------------------------------------------------------- | 277 | ----------------------------------------------------------------------------- |
diff --git a/src/usocket.c b/src/usocket.c index 8adc573..7965db6 100644 --- a/src/usocket.c +++ b/src/usocket.c | |||
| @@ -6,12 +6,14 @@ | |||
| 6 | * The penalty of calling select to avoid busy-wait is only paid when | 6 | * The penalty of calling select to avoid busy-wait is only paid when |
| 7 | * the I/O call fail in the first place. | 7 | * the I/O call fail in the first place. |
| 8 | \*=========================================================================*/ | 8 | \*=========================================================================*/ |
| 9 | #include <string.h> | 9 | #include "luasocket.h" |
| 10 | #include <signal.h> | ||
| 11 | 10 | ||
| 12 | #include "socket.h" | 11 | #include "socket.h" |
| 13 | #include "pierror.h" | 12 | #include "pierror.h" |
| 14 | 13 | ||
| 14 | #include <string.h> | ||
| 15 | #include <signal.h> | ||
| 16 | |||
| 15 | /*-------------------------------------------------------------------------*\ | 17 | /*-------------------------------------------------------------------------*\ |
| 16 | * Wait for readable/writable/connected socket with timeout | 18 | * Wait for readable/writable/connected socket with timeout |
| 17 | \*-------------------------------------------------------------------------*/ | 19 | \*-------------------------------------------------------------------------*/ |
| @@ -76,7 +78,7 @@ int socket_waitfd(p_socket ps, int sw, p_timeout tm) { | |||
| 76 | * Initializes module | 78 | * Initializes module |
| 77 | \*-------------------------------------------------------------------------*/ | 79 | \*-------------------------------------------------------------------------*/ |
| 78 | int socket_open(void) { | 80 | int socket_open(void) { |
| 79 | /* instals a handler to ignore sigpipe or it will crash us */ | 81 | /* installs a handler to ignore sigpipe or it will crash us */ |
| 80 | signal(SIGPIPE, SIG_IGN); | 82 | signal(SIGPIPE, SIG_IGN); |
| 81 | return 1; | 83 | return 1; |
| 82 | } | 84 | } |
| @@ -234,7 +236,7 @@ int socket_sendto(p_socket ps, const char *data, size_t count, size_t *sent, | |||
| 234 | *sent = 0; | 236 | *sent = 0; |
| 235 | if (*ps == SOCKET_INVALID) return IO_CLOSED; | 237 | if (*ps == SOCKET_INVALID) return IO_CLOSED; |
| 236 | for ( ;; ) { | 238 | for ( ;; ) { |
| 237 | long put = (long) sendto(*ps, data, count, 0, addr, len); | 239 | long put = (long) sendto(*ps, data, count, 0, addr, len); |
| 238 | if (put >= 0) { | 240 | if (put >= 0) { |
| 239 | *sent = put; | 241 | *sent = put; |
| 240 | return IO_DONE; | 242 | return IO_DONE; |
| @@ -438,14 +440,15 @@ const char *socket_gaistrerror(int err) { | |||
| 438 | case EAI_FAMILY: return PIE_FAMILY; | 440 | case EAI_FAMILY: return PIE_FAMILY; |
| 439 | case EAI_MEMORY: return PIE_MEMORY; | 441 | case EAI_MEMORY: return PIE_MEMORY; |
| 440 | case EAI_NONAME: return PIE_NONAME; | 442 | case EAI_NONAME: return PIE_NONAME; |
| 443 | #ifdef EAI_OVERFLOW | ||
| 441 | case EAI_OVERFLOW: return PIE_OVERFLOW; | 444 | case EAI_OVERFLOW: return PIE_OVERFLOW; |
| 445 | #endif | ||
| 442 | #ifdef EAI_PROTOCOL | 446 | #ifdef EAI_PROTOCOL |
| 443 | case EAI_PROTOCOL: return PIE_PROTOCOL; | 447 | case EAI_PROTOCOL: return PIE_PROTOCOL; |
| 444 | #endif | 448 | #endif |
| 445 | case EAI_SERVICE: return PIE_SERVICE; | 449 | case EAI_SERVICE: return PIE_SERVICE; |
| 446 | case EAI_SOCKTYPE: return PIE_SOCKTYPE; | 450 | case EAI_SOCKTYPE: return PIE_SOCKTYPE; |
| 447 | case EAI_SYSTEM: return strerror(errno); | 451 | case EAI_SYSTEM: return strerror(errno); |
| 448 | default: return gai_strerror(err); | 452 | default: return LUA_GAI_STRERROR(err); |
| 449 | } | 453 | } |
| 450 | } | 454 | } |
| 451 | |||
diff --git a/src/wsocket.c b/src/wsocket.c index 8ecb0fc..6cb1e41 100644..100755 --- a/src/wsocket.c +++ b/src/wsocket.c | |||
| @@ -5,6 +5,8 @@ | |||
| 5 | * The penalty of calling select to avoid busy-wait is only paid when | 5 | * The penalty of calling select to avoid busy-wait is only paid when |
| 6 | * the I/O call fail in the first place. | 6 | * the I/O call fail in the first place. |
| 7 | \*=========================================================================*/ | 7 | \*=========================================================================*/ |
| 8 | #include "luasocket.h" | ||
| 9 | |||
| 8 | #include <string.h> | 10 | #include <string.h> |
| 9 | 11 | ||
| 10 | #include "socket.h" | 12 | #include "socket.h" |
| @@ -131,11 +133,11 @@ int socket_connect(p_socket ps, SA *addr, socklen_t len, p_timeout tm) { | |||
| 131 | /* we wait until something happens */ | 133 | /* we wait until something happens */ |
| 132 | err = socket_waitfd(ps, WAITFD_C, tm); | 134 | err = socket_waitfd(ps, WAITFD_C, tm); |
| 133 | if (err == IO_CLOSED) { | 135 | if (err == IO_CLOSED) { |
| 134 | int len = sizeof(err); | 136 | int elen = sizeof(err); |
| 135 | /* give windows time to set the error (yes, disgusting) */ | 137 | /* give windows time to set the error (yes, disgusting) */ |
| 136 | Sleep(10); | 138 | Sleep(10); |
| 137 | /* find out why we failed */ | 139 | /* find out why we failed */ |
| 138 | getsockopt(*ps, SOL_SOCKET, SO_ERROR, (char *)&err, &len); | 140 | getsockopt(*ps, SOL_SOCKET, SO_ERROR, (char *)&err, &elen); |
| 139 | /* we KNOW there was an error. if 'why' is 0, we will return | 141 | /* we KNOW there was an error. if 'why' is 0, we will return |
| 140 | * "unknown error", but it's not really our fault */ | 142 | * "unknown error", but it's not really our fault */ |
| 141 | return err > 0? err: IO_UNKNOWN; | 143 | return err > 0? err: IO_UNKNOWN; |
| @@ -358,7 +360,7 @@ const char *socket_ioerror(p_socket ps, int err) { | |||
| 358 | static const char *wstrerror(int err) { | 360 | static const char *wstrerror(int err) { |
| 359 | switch (err) { | 361 | switch (err) { |
| 360 | case WSAEINTR: return "Interrupted function call"; | 362 | case WSAEINTR: return "Interrupted function call"; |
| 361 | case WSAEACCES: return PIE_ACCESS; // "Permission denied"; | 363 | case WSAEACCES: return PIE_ACCESS; /* "Permission denied"; */ |
| 362 | case WSAEFAULT: return "Bad address"; | 364 | case WSAEFAULT: return "Bad address"; |
| 363 | case WSAEINVAL: return "Invalid argument"; | 365 | case WSAEINVAL: return "Invalid argument"; |
| 364 | case WSAEMFILE: return "Too many open files"; | 366 | case WSAEMFILE: return "Too many open files"; |
| @@ -371,23 +373,23 @@ static const char *wstrerror(int err) { | |||
| 371 | case WSAEPROTOTYPE: return "Protocol wrong type for socket"; | 373 | case WSAEPROTOTYPE: return "Protocol wrong type for socket"; |
| 372 | case WSAENOPROTOOPT: return "Bad protocol option"; | 374 | case WSAENOPROTOOPT: return "Bad protocol option"; |
| 373 | case WSAEPROTONOSUPPORT: return "Protocol not supported"; | 375 | case WSAEPROTONOSUPPORT: return "Protocol not supported"; |
| 374 | case WSAESOCKTNOSUPPORT: return PIE_SOCKTYPE; // "Socket type not supported"; | 376 | case WSAESOCKTNOSUPPORT: return PIE_SOCKTYPE; /* "Socket type not supported"; */ |
| 375 | case WSAEOPNOTSUPP: return "Operation not supported"; | 377 | case WSAEOPNOTSUPP: return "Operation not supported"; |
| 376 | case WSAEPFNOSUPPORT: return "Protocol family not supported"; | 378 | case WSAEPFNOSUPPORT: return "Protocol family not supported"; |
| 377 | case WSAEAFNOSUPPORT: return PIE_FAMILY; // "Address family not supported by protocol family"; | 379 | case WSAEAFNOSUPPORT: return PIE_FAMILY; /* "Address family not supported by protocol family"; */ |
| 378 | case WSAEADDRINUSE: return PIE_ADDRINUSE; // "Address already in use"; | 380 | case WSAEADDRINUSE: return PIE_ADDRINUSE; /* "Address already in use"; */ |
| 379 | case WSAEADDRNOTAVAIL: return "Cannot assign requested address"; | 381 | case WSAEADDRNOTAVAIL: return "Cannot assign requested address"; |
| 380 | case WSAENETDOWN: return "Network is down"; | 382 | case WSAENETDOWN: return "Network is down"; |
| 381 | case WSAENETUNREACH: return "Network is unreachable"; | 383 | case WSAENETUNREACH: return "Network is unreachable"; |
| 382 | case WSAENETRESET: return "Network dropped connection on reset"; | 384 | case WSAENETRESET: return "Network dropped connection on reset"; |
| 383 | case WSAECONNABORTED: return "Software caused connection abort"; | 385 | case WSAECONNABORTED: return "Software caused connection abort"; |
| 384 | case WSAECONNRESET: return PIE_CONNRESET; // "Connection reset by peer"; | 386 | case WSAECONNRESET: return PIE_CONNRESET; /* "Connection reset by peer"; */ |
| 385 | case WSAENOBUFS: return "No buffer space available"; | 387 | case WSAENOBUFS: return "No buffer space available"; |
| 386 | case WSAEISCONN: return PIE_ISCONN; // "Socket is already connected"; | 388 | case WSAEISCONN: return PIE_ISCONN; /* "Socket is already connected"; */ |
| 387 | case WSAENOTCONN: return "Socket is not connected"; | 389 | case WSAENOTCONN: return "Socket is not connected"; |
| 388 | case WSAESHUTDOWN: return "Cannot send after socket shutdown"; | 390 | case WSAESHUTDOWN: return "Cannot send after socket shutdown"; |
| 389 | case WSAETIMEDOUT: return PIE_TIMEDOUT; // "Connection timed out"; | 391 | case WSAETIMEDOUT: return PIE_TIMEDOUT; /* "Connection timed out"; */ |
| 390 | case WSAECONNREFUSED: return PIE_CONNREFUSED; // "Connection refused"; | 392 | case WSAECONNREFUSED: return PIE_CONNREFUSED; /* "Connection refused"; */ |
| 391 | case WSAEHOSTDOWN: return "Host is down"; | 393 | case WSAEHOSTDOWN: return "Host is down"; |
| 392 | case WSAEHOSTUNREACH: return "No route to host"; | 394 | case WSAEHOSTUNREACH: return "No route to host"; |
| 393 | case WSAEPROCLIM: return "Too many processes"; | 395 | case WSAEPROCLIM: return "Too many processes"; |
| @@ -396,9 +398,9 @@ static const char *wstrerror(int err) { | |||
| 396 | case WSANOTINITIALISED: | 398 | case WSANOTINITIALISED: |
| 397 | return "Successful WSAStartup not yet performed"; | 399 | return "Successful WSAStartup not yet performed"; |
| 398 | case WSAEDISCON: return "Graceful shutdown in progress"; | 400 | case WSAEDISCON: return "Graceful shutdown in progress"; |
| 399 | case WSAHOST_NOT_FOUND: return PIE_HOST_NOT_FOUND; // "Host not found"; | 401 | case WSAHOST_NOT_FOUND: return PIE_HOST_NOT_FOUND; /* "Host not found"; */ |
| 400 | case WSATRY_AGAIN: return "Nonauthoritative host not found"; | 402 | case WSATRY_AGAIN: return "Nonauthoritative host not found"; |
| 401 | case WSANO_RECOVERY: return PIE_FAIL; // "Nonrecoverable name lookup error"; | 403 | case WSANO_RECOVERY: return PIE_FAIL; /* "Nonrecoverable name lookup error"; */ |
| 402 | case WSANO_DATA: return "Valid name, no data record of requested type"; | 404 | case WSANO_DATA: return "Valid name, no data record of requested type"; |
| 403 | default: return "Unknown error"; | 405 | default: return "Unknown error"; |
| 404 | } | 406 | } |
| @@ -427,7 +429,6 @@ const char *socket_gaistrerror(int err) { | |||
| 427 | #ifdef EAI_SYSTEM | 429 | #ifdef EAI_SYSTEM |
| 428 | case EAI_SYSTEM: return strerror(errno); | 430 | case EAI_SYSTEM: return strerror(errno); |
| 429 | #endif | 431 | #endif |
| 430 | default: return gai_strerror(err); | 432 | default: return LUA_GAI_STRERROR(err); |
| 431 | } | 433 | } |
| 432 | } | 434 | } |
| 433 | |||
