diff options
| author | Diego Nehab <diego@tecgraf.puc-rio.br> | 2003-05-25 01:54:13 +0000 |
|---|---|---|
| committer | Diego Nehab <diego@tecgraf.puc-rio.br> | 2003-05-25 01:54:13 +0000 |
| commit | 0f6c8d50a99997ac7829864b1c93362b50f1bbf3 (patch) | |
| tree | d0cefe3a05484e65b7b7e79d8cae4a1d2e6d19fb /src | |
| parent | c1ef3e7103cc652d2004ef1ddc9409b946207f33 (diff) | |
| download | luasocket-0f6c8d50a99997ac7829864b1c93362b50f1bbf3.tar.gz luasocket-0f6c8d50a99997ac7829864b1c93362b50f1bbf3.tar.bz2 luasocket-0f6c8d50a99997ac7829864b1c93362b50f1bbf3.zip | |
Porting to LUA 5.0 final
Diffstat (limited to 'src')
| -rw-r--r-- | src/auxiliar.c | 113 | ||||
| -rw-r--r-- | src/auxiliar.h | 26 | ||||
| -rw-r--r-- | src/buffer.c | 275 | ||||
| -rw-r--r-- | src/buffer.h | 26 | ||||
| -rw-r--r-- | src/ftp.lua | 57 | ||||
| -rw-r--r-- | src/http.lua | 35 | ||||
| -rw-r--r-- | src/inet.c | 170 | ||||
| -rw-r--r-- | src/inet.h | 36 | ||||
| -rw-r--r-- | src/io.c | 8 | ||||
| -rw-r--r-- | src/io.h | 34 | ||||
| -rw-r--r-- | src/luasocket.c | 64 | ||||
| -rw-r--r-- | src/luasocket.h | 8 | ||||
| -rw-r--r-- | src/mbox.lua | 20 | ||||
| -rw-r--r-- | src/smtp.lua | 39 | ||||
| -rw-r--r-- | src/tcp.c | 222 | ||||
| -rw-r--r-- | src/tcp.h | 20 | ||||
| -rw-r--r-- | src/timeout.c | 116 | ||||
| -rw-r--r-- | src/timeout.h | 32 | ||||
| -rw-r--r-- | src/udp.c | 404 | ||||
| -rw-r--r-- | src/udp.h | 27 | ||||
| -rw-r--r-- | src/usocket.c (renamed from src/unix.c) | 229 | ||||
| -rw-r--r-- | src/usocket.h (renamed from src/unix.h) | 18 |
22 files changed, 1127 insertions, 852 deletions
diff --git a/src/auxiliar.c b/src/auxiliar.c new file mode 100644 index 0000000..5e5ba1a --- /dev/null +++ b/src/auxiliar.c | |||
| @@ -0,0 +1,113 @@ | |||
| 1 | /*=========================================================================*\ | ||
| 2 | * Auxiliar routines for class hierarchy manipulation | ||
| 3 | * | ||
| 4 | * RCS ID: $Id$ | ||
| 5 | \*=========================================================================*/ | ||
| 6 | #include "aux.h" | ||
| 7 | |||
| 8 | /*=========================================================================*\ | ||
| 9 | * Internal function prototypes | ||
| 10 | \*=========================================================================*/ | ||
| 11 | static void *aux_getgroupudata(lua_State *L, const char *group, int objidx); | ||
| 12 | |||
| 13 | /*=========================================================================*\ | ||
| 14 | * Exported functions | ||
| 15 | \*=========================================================================*/ | ||
| 16 | /*-------------------------------------------------------------------------*\ | ||
| 17 | * Creates a new class. A class has methods given by the func array and the | ||
| 18 | * field 'class' tells the object class. The table 'group' list the class | ||
| 19 | * groups the object belongs to. | ||
| 20 | \*-------------------------------------------------------------------------*/ | ||
| 21 | void aux_newclass(lua_State *L, const char *name, luaL_reg *func) | ||
| 22 | { | ||
| 23 | luaL_newmetatable(L, name); | ||
| 24 | lua_pushstring(L, "__index"); | ||
| 25 | lua_newtable(L); | ||
| 26 | luaL_openlib(L, NULL, func, 0); | ||
| 27 | lua_pushstring(L, "class"); | ||
| 28 | lua_pushstring(L, name); | ||
| 29 | lua_settable(L, -3); | ||
| 30 | lua_settable(L, -3); | ||
| 31 | lua_pushstring(L, "group"); | ||
| 32 | lua_newtable(L); | ||
| 33 | lua_settable(L, -3); | ||
| 34 | lua_pop(L, 1); | ||
| 35 | } | ||
| 36 | |||
| 37 | /*-------------------------------------------------------------------------*\ | ||
| 38 | * Add group to object list of groups. | ||
| 39 | \*-------------------------------------------------------------------------*/ | ||
| 40 | void aux_add2group(lua_State *L, const char *name, const char *group) | ||
| 41 | { | ||
| 42 | luaL_getmetatable(L, name); | ||
| 43 | lua_pushstring(L, "group"); | ||
| 44 | lua_gettable(L, -2); | ||
| 45 | lua_pushstring(L, group); | ||
| 46 | lua_pushnumber(L, 1); | ||
| 47 | lua_settable(L, -3); | ||
| 48 | lua_pop(L, 2); | ||
| 49 | } | ||
| 50 | |||
| 51 | /*-------------------------------------------------------------------------*\ | ||
| 52 | * Get a userdata making sure the object belongs to a given class. | ||
| 53 | \*-------------------------------------------------------------------------*/ | ||
| 54 | void *aux_checkclass(lua_State *L, const char *name, int objidx) | ||
| 55 | { | ||
| 56 | void *data = luaL_checkudata(L, objidx, name); | ||
| 57 | if (!data) { | ||
| 58 | char msg[45]; | ||
| 59 | sprintf(msg, "%.35s expected", name); | ||
| 60 | luaL_argerror(L, objidx, msg); | ||
| 61 | } | ||
| 62 | return data; | ||
| 63 | } | ||
| 64 | |||
| 65 | /*-------------------------------------------------------------------------*\ | ||
| 66 | * Get a userdata making sure the object belongs to a given group. | ||
| 67 | \*-------------------------------------------------------------------------*/ | ||
| 68 | void *aux_checkgroup(lua_State *L, const char *group, int objidx) | ||
| 69 | { | ||
| 70 | void *data = aux_getgroupudata(L, group, objidx); | ||
| 71 | if (!data) { | ||
| 72 | char msg[45]; | ||
| 73 | sprintf(msg, "%.35s expected", group); | ||
| 74 | luaL_argerror(L, objidx, msg); | ||
| 75 | } | ||
| 76 | return data; | ||
| 77 | } | ||
| 78 | |||
| 79 | /*-------------------------------------------------------------------------*\ | ||
| 80 | * Set object class. | ||
| 81 | \*-------------------------------------------------------------------------*/ | ||
| 82 | void aux_setclass(lua_State *L, const char *name, int objidx) | ||
| 83 | { | ||
| 84 | luaL_getmetatable(L, name); | ||
| 85 | if (objidx < 0) objidx--; | ||
| 86 | lua_setmetatable(L, objidx); | ||
| 87 | } | ||
| 88 | |||
| 89 | /*=========================================================================*\ | ||
| 90 | * Internal functions | ||
| 91 | \*=========================================================================*/ | ||
| 92 | /*-------------------------------------------------------------------------*\ | ||
| 93 | * Get a userdata if object belongs to a given group. | ||
| 94 | \*-------------------------------------------------------------------------*/ | ||
| 95 | static void *aux_getgroupudata(lua_State *L, const char *group, int objidx) | ||
| 96 | { | ||
| 97 | if (!lua_getmetatable(L, objidx)) return NULL; | ||
| 98 | lua_pushstring(L, "group"); | ||
| 99 | lua_gettable(L, -2); | ||
| 100 | if (lua_isnil(L, -1)) { | ||
| 101 | lua_pop(L, 2); | ||
| 102 | return NULL; | ||
| 103 | } | ||
| 104 | lua_pushstring(L, group); | ||
| 105 | lua_gettable(L, -2); | ||
| 106 | if (lua_isnil(L, -1)) { | ||
| 107 | lua_pop(L, 3); | ||
| 108 | return NULL; | ||
| 109 | } | ||
| 110 | lua_pop(L, 3); | ||
| 111 | return lua_touserdata(L, objidx); | ||
| 112 | } | ||
| 113 | |||
diff --git a/src/auxiliar.h b/src/auxiliar.h new file mode 100644 index 0000000..2681a84 --- /dev/null +++ b/src/auxiliar.h | |||
| @@ -0,0 +1,26 @@ | |||
| 1 | /*=========================================================================*\ | ||
| 2 | * Auxiliar routines for class hierarchy manipulation | ||
| 3 | * | ||
| 4 | * RCS ID: $Id$ | ||
| 5 | \*=========================================================================*/ | ||
| 6 | #ifndef AUX_H | ||
| 7 | #define AUX_H | ||
| 8 | |||
| 9 | #include <lua.h> | ||
| 10 | #include <lauxlib.h> | ||
| 11 | |||
| 12 | void aux_newclass(lua_State *L, const char *name, luaL_reg *func); | ||
| 13 | void aux_add2group(lua_State *L, const char *name, const char *group); | ||
| 14 | void *aux_checkclass(lua_State *L, const char *name, int objidx); | ||
| 15 | void *aux_checkgroup(lua_State *L, const char *group, int objidx); | ||
| 16 | void aux_setclass(lua_State *L, const char *name, int objidx); | ||
| 17 | |||
| 18 | /* min and max macros */ | ||
| 19 | #ifndef MIN | ||
| 20 | #define MIN(x, y) ((x) < (y) ? x : y) | ||
| 21 | #endif | ||
| 22 | #ifndef MAX | ||
| 23 | #define MAX(x, y) ((x) > (y) ? x : y) | ||
| 24 | #endif | ||
| 25 | |||
| 26 | #endif | ||
diff --git a/src/buffer.c b/src/buffer.c index 73df8b3..c5ef66c 100644 --- a/src/buffer.c +++ b/src/buffer.c | |||
| @@ -1,28 +1,24 @@ | |||
| 1 | /*=========================================================================*\ | 1 | /*=========================================================================*\ |
| 2 | * Buffered input/output routines | 2 | * Buffered input/output routines |
| 3 | * Lua methods: | ||
| 4 | * send: unbuffered send using C base_send | ||
| 5 | * receive: buffered read using C base_receive | ||
| 6 | * | 3 | * |
| 7 | * RCS ID: $Id$ | 4 | * RCS ID: $Id$ |
| 8 | \*=========================================================================*/ | 5 | \*=========================================================================*/ |
| 9 | #include <lua.h> | 6 | #include <lua.h> |
| 10 | #include <lauxlib.h> | 7 | #include <lauxlib.h> |
| 11 | 8 | ||
| 12 | #include "lsbuf.h" | 9 | #include "error.h" |
| 10 | #include "aux.h" | ||
| 11 | #include "buf.h" | ||
| 13 | 12 | ||
| 14 | /*=========================================================================*\ | 13 | /*=========================================================================*\ |
| 15 | * Internal function prototypes. | 14 | * Internal function prototypes |
| 16 | \*=========================================================================*/ | 15 | \*=========================================================================*/ |
| 17 | static int sendraw(lua_State *L, p_buf buf, cchar *data, size_t len, | ||
| 18 | size_t *done); | ||
| 19 | static int recvraw(lua_State *L, p_buf buf, size_t wanted); | 16 | static int recvraw(lua_State *L, p_buf buf, size_t wanted); |
| 20 | static int recvdosline(lua_State *L, p_buf buf); | 17 | static int recvline(lua_State *L, p_buf buf); |
| 21 | static int recvunixline(lua_State *L, p_buf buf); | ||
| 22 | static int recvall(lua_State *L, p_buf buf); | 18 | static int recvall(lua_State *L, p_buf buf); |
| 23 | 19 | static int buf_get(p_buf buf, const char **data, size_t *count); | |
| 24 | static int buf_contents(lua_State *L, p_buf buf, cchar **data, size_t *len); | 20 | static void buf_skip(p_buf buf, size_t count); |
| 25 | static void buf_skip(lua_State *L, p_buf buf, size_t len); | 21 | static int sendraw(p_buf buf, const char *data, size_t count, size_t *sent); |
| 26 | 22 | ||
| 27 | /*=========================================================================*\ | 23 | /*=========================================================================*\ |
| 28 | * Exported functions | 24 | * Exported functions |
| @@ -37,98 +33,69 @@ void buf_open(lua_State *L) | |||
| 37 | 33 | ||
| 38 | /*-------------------------------------------------------------------------*\ | 34 | /*-------------------------------------------------------------------------*\ |
| 39 | * Initializes C structure | 35 | * Initializes C structure |
| 40 | * Input | ||
| 41 | * buf: buffer structure to initialize | ||
| 42 | * base: socket object to associate with buffer structure | ||
| 43 | \*-------------------------------------------------------------------------*/ | 36 | \*-------------------------------------------------------------------------*/ |
| 44 | void buf_init(lua_State *L, p_buf buf, p_base base) | 37 | void buf_init(p_buf buf, p_io io, p_tm tm) |
| 45 | { | 38 | { |
| 46 | (void) L; | 39 | buf->first = buf->last = 0; |
| 47 | buf->buf_first = buf->buf_last = 0; | 40 | buf->io = io; |
| 48 | buf->buf_base = base; | 41 | buf->tm = tm; |
| 49 | } | 42 | } |
| 50 | 43 | ||
| 51 | /*-------------------------------------------------------------------------*\ | 44 | /*-------------------------------------------------------------------------*\ |
| 52 | * Send data through buffered object | 45 | * Send data through buffered object |
| 53 | * Input | ||
| 54 | * buf: buffer structure to be used | ||
| 55 | * Lua Input: self, a_1 [, a_2, a_3 ... a_n] | ||
| 56 | * self: socket object | ||
| 57 | * a_i: strings to be sent. | ||
| 58 | * Lua Returns | ||
| 59 | * On success: nil, followed by the total number of bytes sent | ||
| 60 | * On error: error message | ||
| 61 | \*-------------------------------------------------------------------------*/ | 46 | \*-------------------------------------------------------------------------*/ |
| 62 | int buf_send(lua_State *L, p_buf buf) | 47 | int buf_meth_send(lua_State *L, p_buf buf) |
| 63 | { | 48 | { |
| 64 | int top = lua_gettop(L); | 49 | int top = lua_gettop(L); |
| 65 | size_t total = 0; | 50 | size_t total = 0; |
| 66 | int err = PRIV_DONE; | 51 | int arg, err = IO_DONE; |
| 67 | int arg; | 52 | p_tm tm = buf->tm; |
| 68 | p_base base = buf->buf_base; | 53 | tm_markstart(tm); |
| 69 | tm_markstart(&base->base_tm); | ||
| 70 | for (arg = 2; arg <= top; arg++) { /* first arg is socket object */ | 54 | for (arg = 2; arg <= top; arg++) { /* first arg is socket object */ |
| 71 | size_t done, len; | 55 | size_t sent, count; |
| 72 | cchar *data = luaL_optlstring(L, arg, NULL, &len); | 56 | const char *data = luaL_optlstring(L, arg, NULL, &count); |
| 73 | if (!data || err != PRIV_DONE) break; | 57 | if (!data || err != IO_DONE) break; |
| 74 | err = sendraw(L, buf, data, len, &done); | 58 | err = sendraw(buf, data, count, &sent); |
| 75 | total += done; | 59 | total += sent; |
| 76 | } | 60 | } |
| 77 | priv_pusherror(L, err); | ||
| 78 | lua_pushnumber(L, total); | 61 | lua_pushnumber(L, total); |
| 62 | error_push(L, err); | ||
| 79 | #ifdef LUASOCKET_DEBUG | 63 | #ifdef LUASOCKET_DEBUG |
| 80 | /* push time elapsed during operation as the last return value */ | 64 | /* push time elapsed during operation as the last return value */ |
| 81 | lua_pushnumber(L, tm_getelapsed(&base->base_tm)/1000.0); | 65 | lua_pushnumber(L, (tm_gettime() - tm_getstart(tm))/1000.0); |
| 82 | #endif | 66 | #endif |
| 83 | return lua_gettop(L) - top; | 67 | return lua_gettop(L) - top; |
| 84 | } | 68 | } |
| 85 | 69 | ||
| 86 | /*-------------------------------------------------------------------------*\ | 70 | /*-------------------------------------------------------------------------*\ |
| 87 | * Receive data from a buffered object | 71 | * Receive data from a buffered object |
| 88 | * Input | ||
| 89 | * buf: buffer structure to be used | ||
| 90 | * Lua Input: self [pat_1, pat_2 ... pat_n] | ||
| 91 | * self: socket object | ||
| 92 | * pat_i: may be one of the following | ||
| 93 | * "*l": reads a text line, defined as a string of caracters terminates | ||
| 94 | * by a LF character, preceded or not by a CR character. This is | ||
| 95 | * the default pattern | ||
| 96 | * "*lu": reads a text line, terminanted by a CR character only. (Unix mode) | ||
| 97 | * "*a": reads until connection closed | ||
| 98 | * number: reads 'number' characters from the socket object | ||
| 99 | * Lua Returns | ||
| 100 | * On success: one string for each pattern | ||
| 101 | * On error: all strings for which there was no error, followed by one | ||
| 102 | * nil value for the remaining strings, followed by an error code | ||
| 103 | \*-------------------------------------------------------------------------*/ | 72 | \*-------------------------------------------------------------------------*/ |
| 104 | int buf_receive(lua_State *L, p_buf buf) | 73 | int buf_meth_receive(lua_State *L, p_buf buf) |
| 105 | { | 74 | { |
| 106 | int top = lua_gettop(L); | 75 | int top = lua_gettop(L); |
| 107 | int arg, err = PRIV_DONE; | 76 | int arg, err = IO_DONE; |
| 108 | p_base base = buf->buf_base; | 77 | p_tm tm = buf->tm; |
| 109 | tm_markstart(&base->base_tm); | 78 | tm_markstart(tm); |
| 110 | /* push default pattern if need be */ | 79 | /* push default pattern if need be */ |
| 111 | if (top < 2) { | 80 | if (top < 2) { |
| 112 | lua_pushstring(L, "*l"); | 81 | lua_pushstring(L, "*l"); |
| 113 | top++; | 82 | top++; |
| 114 | } | 83 | } |
| 115 | /* make sure we have enough stack space */ | 84 | /* make sure we have enough stack space for all returns */ |
| 116 | luaL_checkstack(L, top+LUA_MINSTACK, "too many arguments"); | 85 | luaL_checkstack(L, top+LUA_MINSTACK, "too many arguments"); |
| 117 | /* receive all patterns */ | 86 | /* receive all patterns */ |
| 118 | for (arg = 2; arg <= top && err == PRIV_DONE; arg++) { | 87 | for (arg = 2; arg <= top && err == IO_DONE; arg++) { |
| 119 | if (!lua_isnumber(L, arg)) { | 88 | if (!lua_isnumber(L, arg)) { |
| 120 | static cchar *patternnames[] = {"*l", "*lu", "*a", "*w", NULL}; | 89 | static const char *patternnames[] = {"*l", "*a", NULL}; |
| 121 | cchar *pattern = luaL_optstring(L, arg, NULL); | 90 | const char *pattern = lua_isnil(L, arg) ? |
| 91 | "*l" : luaL_checkstring(L, arg); | ||
| 122 | /* get next pattern */ | 92 | /* get next pattern */ |
| 123 | switch (luaL_findstring(pattern, patternnames)) { | 93 | switch (luaL_findstring(pattern, patternnames)) { |
| 124 | case 0: /* DOS line pattern */ | 94 | case 0: /* line pattern */ |
| 125 | err = recvdosline(L, buf); break; | 95 | err = recvline(L, buf); break; |
| 126 | case 1: /* Unix line pattern */ | 96 | case 1: /* until closed pattern */ |
| 127 | err = recvunixline(L, buf); break; | 97 | err = recvall(L, buf); |
| 128 | case 2: /* Until closed pattern */ | 98 | if (err == IO_CLOSED) err = IO_DONE; |
| 129 | err = recvall(L, buf); break; | ||
| 130 | case 3: /* Word pattern */ | ||
| 131 | luaL_argcheck(L, 0, arg, "word patterns are deprecated"); | ||
| 132 | break; | 99 | break; |
| 133 | default: /* else it is an error */ | 100 | default: /* else it is an error */ |
| 134 | luaL_argcheck(L, 0, arg, "invalid receive pattern"); | 101 | luaL_argcheck(L, 0, arg, "invalid receive pattern"); |
| @@ -140,25 +107,20 @@ int buf_receive(lua_State *L, p_buf buf) | |||
| 140 | /* push nil for each pattern after an error */ | 107 | /* push nil for each pattern after an error */ |
| 141 | for ( ; arg <= top; arg++) lua_pushnil(L); | 108 | for ( ; arg <= top; arg++) lua_pushnil(L); |
| 142 | /* last return is an error code */ | 109 | /* last return is an error code */ |
| 143 | priv_pusherror(L, err); | 110 | error_push(L, err); |
| 144 | #ifdef LUASOCKET_DEBUG | 111 | #ifdef LUASOCKET_DEBUG |
| 145 | /* push time elapsed during operation as the last return value */ | 112 | /* push time elapsed during operation as the last return value */ |
| 146 | lua_pushnumber(L, tm_getelapsed(&base->base_tm)/1000.0); | 113 | lua_pushnumber(L, (tm_gettime() - tm_getstart(tm))/1000.0); |
| 147 | #endif | 114 | #endif |
| 148 | return lua_gettop(L) - top; | 115 | return lua_gettop(L) - top; |
| 149 | } | 116 | } |
| 150 | 117 | ||
| 151 | /*-------------------------------------------------------------------------*\ | 118 | /*-------------------------------------------------------------------------*\ |
| 152 | * Determines if there is any data in the read buffer | 119 | * Determines if there is any data in the read buffer |
| 153 | * Input | ||
| 154 | * buf: buffer structure to be used | ||
| 155 | * Returns | ||
| 156 | * 1 if empty, 0 if there is data | ||
| 157 | \*-------------------------------------------------------------------------*/ | 120 | \*-------------------------------------------------------------------------*/ |
| 158 | int buf_isempty(lua_State *L, p_buf buf) | 121 | int buf_isempty(p_buf buf) |
| 159 | { | 122 | { |
| 160 | (void) L; | 123 | return buf->first >= buf->last; |
| 161 | return buf->buf_first >= buf->buf_last; | ||
| 162 | } | 124 | } |
| 163 | 125 | ||
| 164 | /*=========================================================================*\ | 126 | /*=========================================================================*\ |
| @@ -166,24 +128,16 @@ int buf_isempty(lua_State *L, p_buf buf) | |||
| 166 | \*=========================================================================*/ | 128 | \*=========================================================================*/ |
| 167 | /*-------------------------------------------------------------------------*\ | 129 | /*-------------------------------------------------------------------------*\ |
| 168 | * Sends a raw block of data through a buffered object. | 130 | * Sends a raw block of data through a buffered object. |
| 169 | * Input | ||
| 170 | * buf: buffer structure to be used | ||
| 171 | * data: data to be sent | ||
| 172 | * len: number of bytes to send | ||
| 173 | * Output | ||
| 174 | * sent: number of bytes sent | ||
| 175 | * Returns | ||
| 176 | * operation error code. | ||
| 177 | \*-------------------------------------------------------------------------*/ | 131 | \*-------------------------------------------------------------------------*/ |
| 178 | static int sendraw(lua_State *L, p_buf buf, cchar *data, size_t len, | 132 | static int sendraw(p_buf buf, const char *data, size_t count, size_t *sent) |
| 179 | size_t *sent) | ||
| 180 | { | 133 | { |
| 181 | p_base base = buf->buf_base; | 134 | p_io io = buf->io; |
| 135 | p_tm tm = buf->tm; | ||
| 182 | size_t total = 0; | 136 | size_t total = 0; |
| 183 | int err = PRIV_DONE; | 137 | int err = IO_DONE; |
| 184 | while (total < len && err == PRIV_DONE) { | 138 | while (total < count && err == IO_DONE) { |
| 185 | size_t done; | 139 | size_t done; |
| 186 | err = base->base_send(L, base, data + total, len - total, &done); | 140 | err = io->send(io->ctx, data+total, count-total, &done, tm_get(tm)); |
| 187 | total += done; | 141 | total += done; |
| 188 | } | 142 | } |
| 189 | *sent = total; | 143 | *sent = total; |
| @@ -192,25 +146,21 @@ static int sendraw(lua_State *L, p_buf buf, cchar *data, size_t len, | |||
| 192 | 146 | ||
| 193 | /*-------------------------------------------------------------------------*\ | 147 | /*-------------------------------------------------------------------------*\ |
| 194 | * Reads a raw block of data from a buffered object. | 148 | * Reads a raw block of data from a buffered object. |
| 195 | * Input | ||
| 196 | * buf: buffer structure | ||
| 197 | * wanted: number of bytes to be read | ||
| 198 | * Returns | ||
| 199 | * operation error code. | ||
| 200 | \*-------------------------------------------------------------------------*/ | 149 | \*-------------------------------------------------------------------------*/ |
| 201 | static int recvraw(lua_State *L, p_buf buf, size_t wanted) | 150 | static |
| 151 | int recvraw(lua_State *L, p_buf buf, size_t wanted) | ||
| 202 | { | 152 | { |
| 203 | int err = PRIV_DONE; | 153 | int err = IO_DONE; |
| 204 | size_t total = 0; | 154 | size_t total = 0; |
| 205 | luaL_Buffer b; | 155 | luaL_Buffer b; |
| 206 | luaL_buffinit(L, &b); | 156 | luaL_buffinit(L, &b); |
| 207 | while (total < wanted && err == PRIV_DONE) { | 157 | while (total < wanted && err == IO_DONE) { |
| 208 | size_t len; cchar *data; | 158 | size_t count; const char *data; |
| 209 | err = buf_contents(L, buf, &data, &len); | 159 | err = buf_get(buf, &data, &count); |
| 210 | len = MIN(len, wanted - total); | 160 | count = MIN(count, wanted - total); |
| 211 | luaL_addlstring(&b, data, len); | 161 | luaL_addlstring(&b, data, count); |
| 212 | buf_skip(L, buf, len); | 162 | buf_skip(buf, count); |
| 213 | total += len; | 163 | total += count; |
| 214 | } | 164 | } |
| 215 | luaL_pushresult(&b); | 165 | luaL_pushresult(&b); |
| 216 | return err; | 166 | return err; |
| @@ -218,21 +168,18 @@ static int recvraw(lua_State *L, p_buf buf, size_t wanted) | |||
| 218 | 168 | ||
| 219 | /*-------------------------------------------------------------------------*\ | 169 | /*-------------------------------------------------------------------------*\ |
| 220 | * Reads everything until the connection is closed | 170 | * Reads everything until the connection is closed |
| 221 | * Input | ||
| 222 | * buf: buffer structure | ||
| 223 | * Result | ||
| 224 | * operation error code. | ||
| 225 | \*-------------------------------------------------------------------------*/ | 171 | \*-------------------------------------------------------------------------*/ |
| 226 | static int recvall(lua_State *L, p_buf buf) | 172 | static |
| 173 | int recvall(lua_State *L, p_buf buf) | ||
| 227 | { | 174 | { |
| 228 | int err = PRIV_DONE; | 175 | int err = IO_DONE; |
| 229 | luaL_Buffer b; | 176 | luaL_Buffer b; |
| 230 | luaL_buffinit(L, &b); | 177 | luaL_buffinit(L, &b); |
| 231 | while (err == PRIV_DONE) { | 178 | while (err == IO_DONE) { |
| 232 | cchar *data; size_t len; | 179 | const char *data; size_t count; |
| 233 | err = buf_contents(L, buf, &data, &len); | 180 | err = buf_get(buf, &data, &count); |
| 234 | luaL_addlstring(&b, data, len); | 181 | luaL_addlstring(&b, data, count); |
| 235 | buf_skip(L, buf, len); | 182 | buf_skip(buf, count); |
| 236 | } | 183 | } |
| 237 | luaL_pushresult(&b); | 184 | luaL_pushresult(&b); |
| 238 | return err; | 185 | return err; |
| @@ -241,61 +188,27 @@ static int recvall(lua_State *L, p_buf buf) | |||
| 241 | /*-------------------------------------------------------------------------*\ | 188 | /*-------------------------------------------------------------------------*\ |
| 242 | * Reads a line terminated by a CR LF pair or just by a LF. The CR and LF | 189 | * Reads a line terminated by a CR LF pair or just by a LF. The CR and LF |
| 243 | * are not returned by the function and are discarded from the buffer. | 190 | * are not returned by the function and are discarded from the buffer. |
| 244 | * Input | ||
| 245 | * buf: buffer structure | ||
| 246 | * Result | ||
| 247 | * operation error code. PRIV_DONE, PRIV_TIMEOUT or PRIV_CLOSED | ||
| 248 | \*-------------------------------------------------------------------------*/ | 191 | \*-------------------------------------------------------------------------*/ |
| 249 | static int recvdosline(lua_State *L, p_buf buf) | 192 | static |
| 193 | int recvline(lua_State *L, p_buf buf) | ||
| 250 | { | 194 | { |
| 251 | int err = 0; | 195 | int err = 0; |
| 252 | luaL_Buffer b; | 196 | luaL_Buffer b; |
| 253 | luaL_buffinit(L, &b); | 197 | luaL_buffinit(L, &b); |
| 254 | while (err == PRIV_DONE) { | 198 | while (err == IO_DONE) { |
| 255 | size_t len, pos; cchar *data; | 199 | size_t count, pos; const char *data; |
| 256 | err = buf_contents(L, buf, &data, &len); | 200 | err = buf_get(buf, &data, &count); |
| 257 | pos = 0; | 201 | pos = 0; |
| 258 | while (pos < len && data[pos] != '\n') { | 202 | while (pos < count && data[pos] != '\n') { |
| 259 | /* we ignore all \r's */ | 203 | /* we ignore all \r's */ |
| 260 | if (data[pos] != '\r') luaL_putchar(&b, data[pos]); | 204 | if (data[pos] != '\r') luaL_putchar(&b, data[pos]); |
| 261 | pos++; | 205 | pos++; |
| 262 | } | 206 | } |
| 263 | if (pos < len) { /* found '\n' */ | 207 | if (pos < count) { /* found '\n' */ |
| 264 | buf_skip(L, buf, pos+1); /* skip '\n' too */ | 208 | buf_skip(buf, pos+1); /* skip '\n' too */ |
| 265 | break; /* we are done */ | ||
| 266 | } else /* reached the end of the buffer */ | ||
| 267 | buf_skip(L, buf, pos); | ||
| 268 | } | ||
| 269 | luaL_pushresult(&b); | ||
| 270 | return err; | ||
| 271 | } | ||
| 272 | |||
| 273 | /*-------------------------------------------------------------------------*\ | ||
| 274 | * Reads a line terminated by a LF character, which is not returned by | ||
| 275 | * the function, and is skipped in the buffer. | ||
| 276 | * Input | ||
| 277 | * buf: buffer structure | ||
| 278 | * Returns | ||
| 279 | * operation error code. PRIV_DONE, PRIV_TIMEOUT or PRIV_CLOSED | ||
| 280 | \*-------------------------------------------------------------------------*/ | ||
| 281 | static int recvunixline(lua_State *L, p_buf buf) | ||
| 282 | { | ||
| 283 | int err = PRIV_DONE; | ||
| 284 | luaL_Buffer b; | ||
| 285 | luaL_buffinit(L, &b); | ||
| 286 | while (err == 0) { | ||
| 287 | size_t pos, len; cchar *data; | ||
| 288 | err = buf_contents(L, buf, &data, &len); | ||
| 289 | pos = 0; | ||
| 290 | while (pos < len && data[pos] != '\n') { | ||
| 291 | luaL_putchar(&b, data[pos]); | ||
| 292 | pos++; | ||
| 293 | } | ||
| 294 | if (pos < len) { /* found '\n' */ | ||
| 295 | buf_skip(L, buf, pos+1); /* skip '\n' too */ | ||
| 296 | break; /* we are done */ | 209 | break; /* we are done */ |
| 297 | } else /* reached the end of the buffer */ | 210 | } else /* reached the end of the buffer */ |
| 298 | buf_skip(L, buf, pos); | 211 | buf_skip(buf, pos); |
| 299 | } | 212 | } |
| 300 | luaL_pushresult(&b); | 213 | luaL_pushresult(&b); |
| 301 | return err; | 214 | return err; |
| @@ -303,38 +216,32 @@ static int recvunixline(lua_State *L, p_buf buf) | |||
| 303 | 216 | ||
| 304 | /*-------------------------------------------------------------------------*\ | 217 | /*-------------------------------------------------------------------------*\ |
| 305 | * Skips a given number of bytes in read buffer | 218 | * Skips a given number of bytes in read buffer |
| 306 | * Input | ||
| 307 | * buf: buffer structure | ||
| 308 | * len: number of bytes to skip | ||
| 309 | \*-------------------------------------------------------------------------*/ | 219 | \*-------------------------------------------------------------------------*/ |
| 310 | static void buf_skip(lua_State *L, p_buf buf, size_t len) | 220 | static |
| 221 | void buf_skip(p_buf buf, size_t count) | ||
| 311 | { | 222 | { |
| 312 | buf->buf_first += len; | 223 | buf->first += count; |
| 313 | if (buf_isempty(L, buf)) buf->buf_first = buf->buf_last = 0; | 224 | if (buf_isempty(buf)) |
| 225 | buf->first = buf->last = 0; | ||
| 314 | } | 226 | } |
| 315 | 227 | ||
| 316 | /*-------------------------------------------------------------------------*\ | 228 | /*-------------------------------------------------------------------------*\ |
| 317 | * Return any data available in buffer, or get more data from transport layer | 229 | * Return any data available in buffer, or get more data from transport layer |
| 318 | * if buffer is empty. | 230 | * if buffer is empty. |
| 319 | * Input | ||
| 320 | * buf: buffer structure | ||
| 321 | * Output | ||
| 322 | * data: pointer to buffer start | ||
| 323 | * len: buffer buffer length | ||
| 324 | * Returns | ||
| 325 | * PRIV_DONE, PRIV_CLOSED, PRIV_TIMEOUT ... | ||
| 326 | \*-------------------------------------------------------------------------*/ | 231 | \*-------------------------------------------------------------------------*/ |
| 327 | static int buf_contents(lua_State *L, p_buf buf, cchar **data, size_t *len) | 232 | static |
| 233 | int buf_get(p_buf buf, const char **data, size_t *count) | ||
| 328 | { | 234 | { |
| 329 | int err = PRIV_DONE; | 235 | int err = IO_DONE; |
| 330 | p_base base = buf->buf_base; | 236 | p_io io = buf->io; |
| 331 | if (buf_isempty(L, buf)) { | 237 | p_tm tm = buf->tm; |
| 332 | size_t done; | 238 | if (buf_isempty(buf)) { |
| 333 | err = base->base_receive(L, base, buf->buf_data, BUF_SIZE, &done); | 239 | size_t got; |
| 334 | buf->buf_first = 0; | 240 | err = io->recv(io->ctx, buf->data, BUF_SIZE, &got, tm_get(tm)); |
| 335 | buf->buf_last = done; | 241 | buf->first = 0; |
| 242 | buf->last = got; | ||
| 336 | } | 243 | } |
| 337 | *len = buf->buf_last - buf->buf_first; | 244 | *count = buf->last - buf->first; |
| 338 | *data = buf->buf_data + buf->buf_first; | 245 | *data = buf->data + buf->first; |
| 339 | return err; | 246 | return err; |
| 340 | } | 247 | } |
diff --git a/src/buffer.h b/src/buffer.h index 4943e3b..3ffc145 100644 --- a/src/buffer.h +++ b/src/buffer.h | |||
| @@ -3,11 +3,12 @@ | |||
| 3 | * | 3 | * |
| 4 | * RCS ID: $Id$ | 4 | * RCS ID: $Id$ |
| 5 | \*=========================================================================*/ | 5 | \*=========================================================================*/ |
| 6 | #ifndef BUF_H_ | 6 | #ifndef BUF_H |
| 7 | #define BUF_H_ | 7 | #define BUF_H |
| 8 | 8 | ||
| 9 | #include <lua.h> | 9 | #include <lua.h> |
| 10 | #include "lsbase.h" | 10 | #include "io.h" |
| 11 | #include "tm.h" | ||
| 11 | 12 | ||
| 12 | /* buffer size in bytes */ | 13 | /* buffer size in bytes */ |
| 13 | #define BUF_SIZE 8192 | 14 | #define BUF_SIZE 8192 |
| @@ -15,10 +16,11 @@ | |||
| 15 | /*-------------------------------------------------------------------------*\ | 16 | /*-------------------------------------------------------------------------*\ |
| 16 | * Buffer control structure | 17 | * Buffer control structure |
| 17 | \*-------------------------------------------------------------------------*/ | 18 | \*-------------------------------------------------------------------------*/ |
| 18 | typedef struct t_buf_tag { | 19 | typedef struct t_buf_ { |
| 19 | size_t buf_first, buf_last; | 20 | p_io io; /* IO driver used for this buffer */ |
| 20 | char buf_data[BUF_SIZE]; | 21 | p_tm tm; /* timeout management for this buffer */ |
| 21 | p_base buf_base; | 22 | size_t first, last; /* index of first and last bytes of stored data */ |
| 23 | char data[BUF_SIZE]; /* storage space for buffer data */ | ||
| 22 | } t_buf; | 24 | } t_buf; |
| 23 | typedef t_buf *p_buf; | 25 | typedef t_buf *p_buf; |
| 24 | 26 | ||
| @@ -26,9 +28,9 @@ typedef t_buf *p_buf; | |||
| 26 | * Exported functions | 28 | * Exported functions |
| 27 | \*-------------------------------------------------------------------------*/ | 29 | \*-------------------------------------------------------------------------*/ |
| 28 | void buf_open(lua_State *L); | 30 | void buf_open(lua_State *L); |
| 29 | void buf_init(lua_State *L, p_buf buf, p_base base); | 31 | void buf_init(p_buf buf, p_io io, p_tm tm); |
| 30 | int buf_send(lua_State *L, p_buf buf); | 32 | int buf_meth_send(lua_State *L, p_buf buf); |
| 31 | int buf_receive(lua_State *L, p_buf buf); | 33 | int buf_meth_receive(lua_State *L, p_buf buf); |
| 32 | int buf_isempty(lua_State *L, p_buf buf); | 34 | int buf_isempty(p_buf buf); |
| 33 | 35 | ||
| 34 | #endif /* BUF_H_ */ | 36 | #endif /* BUF_H */ |
diff --git a/src/ftp.lua b/src/ftp.lua index 4017eb5..c48f2c7 100644 --- a/src/ftp.lua +++ b/src/ftp.lua | |||
| @@ -7,7 +7,8 @@ | |||
| 7 | ----------------------------------------------------------------------------- | 7 | ----------------------------------------------------------------------------- |
| 8 | 8 | ||
| 9 | local Public, Private = {}, {} | 9 | local Public, Private = {}, {} |
| 10 | socket.ftp = Public | 10 | local socket = _G[LUASOCKET_LIBNAME] -- get LuaSocket namespace |
| 11 | socket.ftp = Public -- create ftp sub namespace | ||
| 11 | 12 | ||
| 12 | ----------------------------------------------------------------------------- | 13 | ----------------------------------------------------------------------------- |
| 13 | -- Program constants | 14 | -- Program constants |
| @@ -23,32 +24,42 @@ Public.EMAIL = "anonymous@anonymous.org" | |||
| 23 | Public.BLOCKSIZE = 8192 | 24 | Public.BLOCKSIZE = 8192 |
| 24 | 25 | ||
| 25 | ----------------------------------------------------------------------------- | 26 | ----------------------------------------------------------------------------- |
| 26 | -- Tries to send DOS mode lines. Closes socket on error. | 27 | -- Tries to get a pattern from the server and closes socket on error |
| 27 | -- Input | 28 | -- sock: socket connected to the server |
| 28 | -- sock: server socket | 29 | -- pattern: pattern to receive |
| 29 | -- line: string to be sent | ||
| 30 | -- Returns | 30 | -- Returns |
| 31 | -- err: message in case of error, nil if successfull | 31 | -- received pattern on success |
| 32 | -- nil followed by error message on error | ||
| 32 | ----------------------------------------------------------------------------- | 33 | ----------------------------------------------------------------------------- |
| 33 | function Private.try_sendline(sock, line) | 34 | function Private.try_receive(sock, pattern) |
| 34 | local err = sock:send(line .. "\r\n") | 35 | local data, err = sock:receive(pattern) |
| 35 | if err then sock:close() end | 36 | if not data then sock:close() end |
| 36 | return err | 37 | return data, err |
| 37 | end | 38 | end |
| 38 | 39 | ||
| 39 | ----------------------------------------------------------------------------- | 40 | ----------------------------------------------------------------------------- |
| 40 | -- Tries to get a pattern from the server and closes socket on error | 41 | -- Tries to send data to the server and closes socket on error |
| 41 | -- sock: socket connected to the server | 42 | -- sock: socket connected to the server |
| 42 | -- ...: pattern to receive | 43 | -- data: data to send |
| 43 | -- Returns | 44 | -- Returns |
| 44 | -- ...: received pattern | 45 | -- err: error message if any, nil if successfull |
| 45 | -- err: error message if any | ||
| 46 | ----------------------------------------------------------------------------- | 46 | ----------------------------------------------------------------------------- |
| 47 | function Private.try_receive(...) | 47 | function Private.try_send(sock, data) |
| 48 | local sock = arg[1] | 48 | local sent, err = sock:send(data) |
| 49 | local data, err = sock.receive(unpack(arg)) | 49 | if not sent then sock:close() end |
| 50 | if err then sock:close() end | 50 | return err |
| 51 | return data, err | 51 | end |
| 52 | |||
| 53 | ----------------------------------------------------------------------------- | ||
| 54 | -- Tries to send DOS mode lines. Closes socket on error. | ||
| 55 | -- Input | ||
| 56 | -- sock: server socket | ||
| 57 | -- line: string to be sent | ||
| 58 | -- Returns | ||
| 59 | -- err: message in case of error, nil if successfull | ||
| 60 | ----------------------------------------------------------------------------- | ||
| 61 | function Private.try_sendline(sock, line) | ||
| 62 | return Private.try_send(sock, line .. "\r\n") | ||
| 52 | end | 63 | end |
| 53 | 64 | ||
| 54 | ----------------------------------------------------------------------------- | 65 | ----------------------------------------------------------------------------- |
| @@ -307,20 +318,20 @@ end | |||
| 307 | -- nil if successfull, or an error message in case of error | 318 | -- nil if successfull, or an error message in case of error |
| 308 | ----------------------------------------------------------------------------- | 319 | ----------------------------------------------------------------------------- |
| 309 | function Private.send_indirect(data, send_cb, chunk, size) | 320 | function Private.send_indirect(data, send_cb, chunk, size) |
| 310 | local sent, err | 321 | local total, sent, err |
| 311 | sent = 0 | 322 | total = 0 |
| 312 | while 1 do | 323 | while 1 do |
| 313 | if type(chunk) ~= "string" or type(size) ~= "number" then | 324 | if type(chunk) ~= "string" or type(size) ~= "number" then |
| 314 | data:close() | 325 | data:close() |
| 315 | if not chunk and type(size) == "string" then return size | 326 | if not chunk and type(size) == "string" then return size |
| 316 | else return "invalid callback return" end | 327 | else return "invalid callback return" end |
| 317 | end | 328 | end |
| 318 | err = data:send(chunk) | 329 | sent, err = data:send(chunk) |
| 319 | if err then | 330 | if err then |
| 320 | data:close() | 331 | data:close() |
| 321 | return err | 332 | return err |
| 322 | end | 333 | end |
| 323 | sent = sent + string.len(chunk) | 334 | total = total + sent |
| 324 | if sent >= size then break end | 335 | if sent >= size then break end |
| 325 | chunk, size = send_cb() | 336 | chunk, size = send_cb() |
| 326 | end | 337 | end |
diff --git a/src/http.lua b/src/http.lua index 59645ee..d531a2f 100644 --- a/src/http.lua +++ b/src/http.lua | |||
| @@ -7,7 +7,8 @@ | |||
| 7 | ----------------------------------------------------------------------------- | 7 | ----------------------------------------------------------------------------- |
| 8 | 8 | ||
| 9 | local Public, Private = {}, {} | 9 | local Public, Private = {}, {} |
| 10 | socket.http = Public | 10 | local socket = _G[LUASOCKET_LIBNAME] -- get LuaSocket namespace |
| 11 | socket.http = Public -- create http sub namespace | ||
| 11 | 12 | ||
| 12 | ----------------------------------------------------------------------------- | 13 | ----------------------------------------------------------------------------- |
| 13 | -- Program constants | 14 | -- Program constants |
| @@ -24,19 +25,15 @@ Public.BLOCKSIZE = 8192 | |||
| 24 | ----------------------------------------------------------------------------- | 25 | ----------------------------------------------------------------------------- |
| 25 | -- Tries to get a pattern from the server and closes socket on error | 26 | -- Tries to get a pattern from the server and closes socket on error |
| 26 | -- sock: socket connected to the server | 27 | -- sock: socket connected to the server |
| 27 | -- ...: pattern to receive | 28 | -- pattern: pattern to receive |
| 28 | -- Returns | 29 | -- Returns |
| 29 | -- ...: received pattern | 30 | -- received pattern on success |
| 30 | -- err: error message if any | 31 | -- nil followed by error message on error |
| 31 | ----------------------------------------------------------------------------- | 32 | ----------------------------------------------------------------------------- |
| 32 | function Private.try_receive(...) | 33 | function Private.try_receive(sock, pattern) |
| 33 | local sock = arg[1] | 34 | local data, err = sock:receive(pattern) |
| 34 | local data, err = sock.receive(unpack(arg)) | 35 | if not data then sock:close() end |
| 35 | if err then | 36 | return data, err |
| 36 | sock:close() | ||
| 37 | return nil, err | ||
| 38 | end | ||
| 39 | return data | ||
| 40 | end | 37 | end |
| 41 | 38 | ||
| 42 | ----------------------------------------------------------------------------- | 39 | ----------------------------------------------------------------------------- |
| @@ -47,8 +44,8 @@ end | |||
| 47 | -- err: error message if any, nil if successfull | 44 | -- err: error message if any, nil if successfull |
| 48 | ----------------------------------------------------------------------------- | 45 | ----------------------------------------------------------------------------- |
| 49 | function Private.try_send(sock, data) | 46 | function Private.try_send(sock, data) |
| 50 | local err = sock:send(data) | 47 | local sent, err = sock:send(data) |
| 51 | if err then sock:close() end | 48 | if not sent then sock:close() end |
| 52 | return err | 49 | return err |
| 53 | end | 50 | end |
| 54 | 51 | ||
| @@ -285,21 +282,21 @@ end | |||
| 285 | -- nil if successfull, or an error message in case of error | 282 | -- nil if successfull, or an error message in case of error |
| 286 | ----------------------------------------------------------------------------- | 283 | ----------------------------------------------------------------------------- |
| 287 | function Private.send_indirect(data, send_cb, chunk, size) | 284 | function Private.send_indirect(data, send_cb, chunk, size) |
| 288 | local sent, err | 285 | local total, sent, err |
| 289 | sent = 0 | 286 | total = 0 |
| 290 | while 1 do | 287 | while 1 do |
| 291 | if type(chunk) ~= "string" or type(size) ~= "number" then | 288 | if type(chunk) ~= "string" or type(size) ~= "number" then |
| 292 | data:close() | 289 | data:close() |
| 293 | if not chunk and type(size) == "string" then return size | 290 | if not chunk and type(size) == "string" then return size |
| 294 | else return "invalid callback return" end | 291 | else return "invalid callback return" end |
| 295 | end | 292 | end |
| 296 | err = data:send(chunk) | 293 | sent, err = data:send(chunk) |
| 297 | if err then | 294 | if err then |
| 298 | data:close() | 295 | data:close() |
| 299 | return err | 296 | return err |
| 300 | end | 297 | end |
| 301 | sent = sent + string.len(chunk) | 298 | total = total + sent |
| 302 | if sent >= size then break end | 299 | if total >= size then break end |
| 303 | chunk, size = send_cb() | 300 | chunk, size = send_cb() |
| 304 | end | 301 | end |
| 305 | end | 302 | end |
| @@ -1,12 +1,5 @@ | |||
| 1 | /*=========================================================================*\ | 1 | /*=========================================================================*\ |
| 2 | * Internet domain class: inherits from the Socket class, and implement | 2 | * Internet domain functions |
| 3 | * a few methods shared by all internet related objects | ||
| 4 | * Lua methods: | ||
| 5 | * getpeername: gets socket peer ip address and port | ||
| 6 | * getsockname: gets local socket ip address and port | ||
| 7 | * Global Lua fuctions: | ||
| 8 | * toip: gets resolver info on host name | ||
| 9 | * tohostname: gets resolver info on dotted-quad | ||
| 10 | * | 3 | * |
| 11 | * RCS ID: $Id$ | 4 | * RCS ID: $Id$ |
| 12 | \*=========================================================================*/ | 5 | \*=========================================================================*/ |
| @@ -15,23 +8,27 @@ | |||
| 15 | #include <lua.h> | 8 | #include <lua.h> |
| 16 | #include <lauxlib.h> | 9 | #include <lauxlib.h> |
| 17 | 10 | ||
| 18 | #include "lsinet.h" | 11 | #include "luasocket.h" |
| 19 | #include "lssock.h" | 12 | #include "inet.h" |
| 20 | #include "lscompat.h" | ||
| 21 | 13 | ||
| 22 | /*=========================================================================*\ | 14 | /*=========================================================================*\ |
| 23 | * Internal function prototypes. | 15 | * Internal function prototypes. |
| 24 | \*=========================================================================*/ | 16 | \*=========================================================================*/ |
| 25 | static int inet_lua_toip(lua_State *L); | 17 | static int inet_global_toip(lua_State *L); |
| 26 | static int inet_lua_tohostname(lua_State *L); | 18 | static int inet_global_tohostname(lua_State *L); |
| 27 | static int inet_lua_getpeername(lua_State *L); | 19 | |
| 28 | static int inet_lua_getsockname(lua_State *L); | ||
| 29 | static void inet_pushresolved(lua_State *L, struct hostent *hp); | 20 | static void inet_pushresolved(lua_State *L, struct hostent *hp); |
| 30 | 21 | ||
| 31 | #ifdef COMPAT_INETATON | 22 | #ifdef INET_ATON |
| 32 | static int inet_aton(cchar *cp, struct in_addr *inp); | 23 | static int inet_aton(const char *cp, struct in_addr *inp); |
| 33 | #endif | 24 | #endif |
| 34 | 25 | ||
| 26 | static luaL_reg func[] = { | ||
| 27 | { "toip", inet_global_toip }, | ||
| 28 | { "tohostname", inet_global_tohostname }, | ||
| 29 | { NULL, NULL} | ||
| 30 | }; | ||
| 31 | |||
| 35 | /*=========================================================================*\ | 32 | /*=========================================================================*\ |
| 36 | * Exported functions | 33 | * Exported functions |
| 37 | \*=========================================================================*/ | 34 | \*=========================================================================*/ |
| @@ -40,39 +37,7 @@ static int inet_aton(cchar *cp, struct in_addr *inp); | |||
| 40 | \*-------------------------------------------------------------------------*/ | 37 | \*-------------------------------------------------------------------------*/ |
| 41 | void inet_open(lua_State *L) | 38 | void inet_open(lua_State *L) |
| 42 | { | 39 | { |
| 43 | lua_pushcfunction(L, inet_lua_toip); | 40 | luaL_openlib(L, LUASOCKET_LIBNAME, func, 0); |
| 44 | priv_newglobal(L, "toip"); | ||
| 45 | lua_pushcfunction(L, inet_lua_tohostname); | ||
| 46 | priv_newglobal(L, "tohostname"); | ||
| 47 | priv_newglobalmethod(L, "getsockname"); | ||
| 48 | priv_newglobalmethod(L, "getpeername"); | ||
| 49 | } | ||
| 50 | |||
| 51 | /*-------------------------------------------------------------------------*\ | ||
| 52 | * Hook lua methods to methods table. | ||
| 53 | * Input | ||
| 54 | * lsclass: class name | ||
| 55 | \*-------------------------------------------------------------------------*/ | ||
| 56 | void inet_inherit(lua_State *L, cchar *lsclass) | ||
| 57 | { | ||
| 58 | unsigned int i; | ||
| 59 | static struct luaL_reg funcs[] = { | ||
| 60 | {"getsockname", inet_lua_getsockname}, | ||
| 61 | {"getpeername", inet_lua_getpeername}, | ||
| 62 | }; | ||
| 63 | sock_inherit(L, lsclass); | ||
| 64 | for (i = 0; i < sizeof(funcs)/sizeof(funcs[0]); i++) { | ||
| 65 | lua_pushcfunction(L, funcs[i].func); | ||
| 66 | priv_setmethod(L, lsclass, funcs[i].name); | ||
| 67 | } | ||
| 68 | } | ||
| 69 | |||
| 70 | /*-------------------------------------------------------------------------*\ | ||
| 71 | * Constructs the object | ||
| 72 | \*-------------------------------------------------------------------------*/ | ||
| 73 | void inet_construct(lua_State *L, p_inet inet) | ||
| 74 | { | ||
| 75 | sock_construct(L, (p_sock) inet); | ||
| 76 | } | 41 | } |
| 77 | 42 | ||
| 78 | /*=========================================================================*\ | 43 | /*=========================================================================*\ |
| @@ -87,17 +52,18 @@ void inet_construct(lua_State *L, p_inet inet) | |||
| 87 | * On success: first IP address followed by a resolved table | 52 | * On success: first IP address followed by a resolved table |
| 88 | * On error: nil, followed by an error message | 53 | * On error: nil, followed by an error message |
| 89 | \*-------------------------------------------------------------------------*/ | 54 | \*-------------------------------------------------------------------------*/ |
| 90 | static int inet_lua_toip(lua_State *L) | 55 | static int inet_global_toip(lua_State *L) |
| 91 | { | 56 | { |
| 92 | cchar *address = luaL_checkstring(L, 1); | 57 | const char *address = luaL_checkstring(L, 1); |
| 93 | struct in_addr addr; | 58 | struct in_addr addr; |
| 94 | struct hostent *hp; | 59 | struct hostent *hp; |
| 95 | if (inet_aton(address, &addr)) | 60 | if (inet_aton(address, &addr)) |
| 96 | hp = gethostbyaddr((char *) &addr, sizeof(addr), AF_INET); | 61 | hp = gethostbyaddr((char *) &addr, sizeof(addr), AF_INET); |
| 97 | else hp = gethostbyname(address); | 62 | else |
| 63 | hp = gethostbyname(address); | ||
| 98 | if (!hp) { | 64 | if (!hp) { |
| 99 | lua_pushnil(L); | 65 | lua_pushnil(L); |
| 100 | lua_pushstring(L, compat_hoststrerror()); | 66 | lua_pushstring(L, sock_hoststrerror()); |
| 101 | return 2; | 67 | return 2; |
| 102 | } | 68 | } |
| 103 | addr = *((struct in_addr *) hp->h_addr); | 69 | addr = *((struct in_addr *) hp->h_addr); |
| @@ -115,17 +81,18 @@ static int inet_lua_toip(lua_State *L) | |||
| 115 | * On success: canonic name followed by a resolved table | 81 | * On success: canonic name followed by a resolved table |
| 116 | * On error: nil, followed by an error message | 82 | * On error: nil, followed by an error message |
| 117 | \*-------------------------------------------------------------------------*/ | 83 | \*-------------------------------------------------------------------------*/ |
| 118 | static int inet_lua_tohostname(lua_State *L) | 84 | static int inet_global_tohostname(lua_State *L) |
| 119 | { | 85 | { |
| 120 | cchar *address = luaL_checkstring(L, 1); | 86 | const char *address = luaL_checkstring(L, 1); |
| 121 | struct in_addr addr; | 87 | struct in_addr addr; |
| 122 | struct hostent *hp; | 88 | struct hostent *hp; |
| 123 | if (inet_aton(address, &addr)) | 89 | if (inet_aton(address, &addr)) |
| 124 | hp = gethostbyaddr((char *) &addr, sizeof(addr), AF_INET); | 90 | hp = gethostbyaddr((char *) &addr, sizeof(addr), AF_INET); |
| 125 | else hp = gethostbyname(address); | 91 | else |
| 92 | hp = gethostbyname(address); | ||
| 126 | if (!hp) { | 93 | if (!hp) { |
| 127 | lua_pushnil(L); | 94 | lua_pushnil(L); |
| 128 | lua_pushstring(L, compat_hoststrerror()); | 95 | lua_pushstring(L, sock_hoststrerror()); |
| 129 | return 2; | 96 | return 2; |
| 130 | } | 97 | } |
| 131 | lua_pushstring(L, hp->h_name); | 98 | lua_pushstring(L, hp->h_name); |
| @@ -138,18 +105,17 @@ static int inet_lua_tohostname(lua_State *L) | |||
| 138 | \*=========================================================================*/ | 105 | \*=========================================================================*/ |
| 139 | /*-------------------------------------------------------------------------*\ | 106 | /*-------------------------------------------------------------------------*\ |
| 140 | * Retrieves socket peer name | 107 | * Retrieves socket peer name |
| 141 | * Lua Input: sock | 108 | * Input: |
| 142 | * sock: socket | 109 | * sock: socket |
| 143 | * Lua Returns | 110 | * Lua Returns |
| 144 | * On success: ip address and port of peer | 111 | * On success: ip address and port of peer |
| 145 | * On error: nil | 112 | * On error: nil |
| 146 | \*-------------------------------------------------------------------------*/ | 113 | \*-------------------------------------------------------------------------*/ |
| 147 | static int inet_lua_getpeername(lua_State *L) | 114 | int inet_meth_getpeername(lua_State *L, p_sock ps) |
| 148 | { | 115 | { |
| 149 | p_sock sock = (p_sock) lua_touserdata(L, 1); | ||
| 150 | struct sockaddr_in peer; | 116 | struct sockaddr_in peer; |
| 151 | size_t peer_len = sizeof(peer); | 117 | size_t peer_len = sizeof(peer); |
| 152 | if (getpeername(sock->fd, (SA *) &peer, &peer_len) < 0) { | 118 | if (getpeername(*ps, (SA *) &peer, &peer_len) < 0) { |
| 153 | lua_pushnil(L); | 119 | lua_pushnil(L); |
| 154 | return 1; | 120 | return 1; |
| 155 | } | 121 | } |
| @@ -160,18 +126,17 @@ static int inet_lua_getpeername(lua_State *L) | |||
| 160 | 126 | ||
| 161 | /*-------------------------------------------------------------------------*\ | 127 | /*-------------------------------------------------------------------------*\ |
| 162 | * Retrieves socket local name | 128 | * Retrieves socket local name |
| 163 | * Lua Input: sock | 129 | * Input: |
| 164 | * sock: socket | 130 | * sock: socket |
| 165 | * Lua Returns | 131 | * Lua Returns |
| 166 | * On success: local ip address and port | 132 | * On success: local ip address and port |
| 167 | * On error: nil | 133 | * On error: nil |
| 168 | \*-------------------------------------------------------------------------*/ | 134 | \*-------------------------------------------------------------------------*/ |
| 169 | static int inet_lua_getsockname(lua_State *L) | 135 | int inet_meth_getsockname(lua_State *L, p_sock ps) |
| 170 | { | 136 | { |
| 171 | p_sock sock = (p_sock) lua_touserdata(L, 1); | ||
| 172 | struct sockaddr_in local; | 137 | struct sockaddr_in local; |
| 173 | size_t local_len = sizeof(local); | 138 | size_t local_len = sizeof(local); |
| 174 | if (getsockname(sock->fd, (SA *) &local, &local_len) < 0) { | 139 | if (getsockname(*ps, (SA *) &local, &local_len) < 0) { |
| 175 | lua_pushnil(L); | 140 | lua_pushnil(L); |
| 176 | return 1; | 141 | return 1; |
| 177 | } | 142 | } |
| @@ -222,47 +187,53 @@ static void inet_pushresolved(lua_State *L, struct hostent *hp) | |||
| 222 | } | 187 | } |
| 223 | 188 | ||
| 224 | /*-------------------------------------------------------------------------*\ | 189 | /*-------------------------------------------------------------------------*\ |
| 225 | * Tries to create a TCP socket and connect to remote address (address, port) | 190 | * Tries to connect to remote address (address, port) |
| 226 | * Input | 191 | * Input |
| 227 | * client: socket structure to be used | 192 | * ps: pointer to socket |
| 228 | * address: host name or ip address | 193 | * address: host name or ip address |
| 229 | * port: port number to bind to | 194 | * port: port number to bind to |
| 230 | * Returns | 195 | * Returns |
| 231 | * NULL in case of success, error message otherwise | 196 | * NULL in case of success, error message otherwise |
| 232 | \*-------------------------------------------------------------------------*/ | 197 | \*-------------------------------------------------------------------------*/ |
| 233 | cchar *inet_tryconnect(p_inet inet, cchar *address, ushort port) | 198 | const char *inet_tryconnect(p_sock ps, const char *address, ushort port) |
| 234 | { | 199 | { |
| 235 | struct sockaddr_in remote; | 200 | struct sockaddr_in remote; |
| 236 | memset(&remote, 0, sizeof(remote)); | 201 | memset(&remote, 0, sizeof(remote)); |
| 237 | remote.sin_family = AF_INET; | 202 | remote.sin_family = AF_INET; |
| 238 | remote.sin_port = htons(port); | 203 | remote.sin_port = htons(port); |
| 239 | if (!strlen(address) || !inet_aton(address, &remote.sin_addr)) { | 204 | if (strcmp(address, "*")) { |
| 240 | struct hostent *hp = gethostbyname(address); | 205 | if (!strlen(address) || !inet_aton(address, &remote.sin_addr)) { |
| 241 | struct in_addr **addr; | 206 | struct hostent *hp = gethostbyname(address); |
| 242 | if (!hp) return compat_hoststrerror(); | 207 | struct in_addr **addr; |
| 243 | addr = (struct in_addr **) hp->h_addr_list; | 208 | remote.sin_family = AF_INET; |
| 244 | memcpy(&remote.sin_addr, *addr, sizeof(struct in_addr)); | 209 | if (!hp) return sock_hoststrerror(); |
| 245 | } | 210 | addr = (struct in_addr **) hp->h_addr_list; |
| 246 | compat_setblocking(inet->fd); | 211 | memcpy(&remote.sin_addr, *addr, sizeof(struct in_addr)); |
| 247 | if (compat_connect(inet->fd, (SA *) &remote, sizeof(remote)) < 0) { | 212 | } |
| 248 | const char *err = compat_connectstrerror(); | 213 | } else remote.sin_family = AF_UNSPEC; |
| 249 | compat_close(inet->fd); | 214 | sock_setblocking(ps); |
| 250 | inet->fd = COMPAT_INVALIDFD; | 215 | const char *err = sock_connect(ps, (SA *) &remote, sizeof(remote)); |
| 216 | if (err) { | ||
| 217 | sock_destroy(ps); | ||
| 218 | *ps = SOCK_INVALID; | ||
| 251 | return err; | 219 | return err; |
| 252 | } | 220 | } else { |
| 253 | compat_setnonblocking(inet->fd); | 221 | sock_setnonblocking(ps); |
| 254 | return NULL; | 222 | return NULL; |
| 223 | } | ||
| 255 | } | 224 | } |
| 256 | 225 | ||
| 257 | /*-------------------------------------------------------------------------*\ | 226 | /*-------------------------------------------------------------------------*\ |
| 258 | * Tries to create a TCP socket and bind it to (address, port) | 227 | * Tries to bind socket to (address, port) |
| 259 | * Input | 228 | * Input |
| 229 | * sock: pointer to socket | ||
| 260 | * address: host name or ip address | 230 | * address: host name or ip address |
| 261 | * port: port number to bind to | 231 | * port: port number to bind to |
| 262 | * Returns | 232 | * Returns |
| 263 | * NULL in case of success, error message otherwise | 233 | * NULL in case of success, error message otherwise |
| 264 | \*-------------------------------------------------------------------------*/ | 234 | \*-------------------------------------------------------------------------*/ |
| 265 | cchar *inet_trybind(p_inet inet, cchar *address, ushort port) | 235 | const char *inet_trybind(p_sock ps, const char *address, ushort port, |
| 236 | int backlog) | ||
| 266 | { | 237 | { |
| 267 | struct sockaddr_in local; | 238 | struct sockaddr_in local; |
| 268 | memset(&local, 0, sizeof(local)); | 239 | memset(&local, 0, sizeof(local)); |
| @@ -274,34 +245,33 @@ cchar *inet_trybind(p_inet inet, cchar *address, ushort port) | |||
| 274 | (!strlen(address) || !inet_aton(address, &local.sin_addr))) { | 245 | (!strlen(address) || !inet_aton(address, &local.sin_addr))) { |
| 275 | struct hostent *hp = gethostbyname(address); | 246 | struct hostent *hp = gethostbyname(address); |
| 276 | struct in_addr **addr; | 247 | struct in_addr **addr; |
| 277 | if (!hp) return compat_hoststrerror(); | 248 | if (!hp) return sock_hoststrerror(); |
| 278 | addr = (struct in_addr **) hp->h_addr_list; | 249 | addr = (struct in_addr **) hp->h_addr_list; |
| 279 | memcpy(&local.sin_addr, *addr, sizeof(struct in_addr)); | 250 | memcpy(&local.sin_addr, *addr, sizeof(struct in_addr)); |
| 280 | } | 251 | } |
| 281 | compat_setblocking(inet->fd); | 252 | sock_setblocking(ps); |
| 282 | if (compat_bind(inet->fd, (SA *) &local, sizeof(local)) < 0) { | 253 | const char *err = sock_bind(ps, (SA *) &local, sizeof(local)); |
| 283 | const char *err = compat_bindstrerror(); | 254 | if (err) { |
| 284 | compat_close(inet->fd); | 255 | sock_destroy(ps); |
| 285 | inet->fd = COMPAT_INVALIDFD; | 256 | *ps = SOCK_INVALID; |
| 286 | return err; | 257 | return err; |
| 258 | } else { | ||
| 259 | sock_setnonblocking(ps); | ||
| 260 | if (backlog > 0) sock_listen(ps, backlog); | ||
| 261 | return NULL; | ||
| 287 | } | 262 | } |
| 288 | compat_setnonblocking(inet->fd); | ||
| 289 | return NULL; | ||
| 290 | } | 263 | } |
| 291 | 264 | ||
| 292 | /*-------------------------------------------------------------------------*\ | 265 | /*-------------------------------------------------------------------------*\ |
| 293 | * Tries to create a new inet socket | 266 | * Tries to create a new inet socket |
| 294 | * Input | 267 | * Input |
| 295 | * udp: udp structure | 268 | * sock: pointer to socket |
| 296 | * Returns | 269 | * Returns |
| 297 | * NULL if successfull, error message on error | 270 | * NULL if successfull, error message on error |
| 298 | \*-------------------------------------------------------------------------*/ | 271 | \*-------------------------------------------------------------------------*/ |
| 299 | cchar *inet_trysocket(p_inet inet, int type) | 272 | const char *inet_trycreate(p_sock ps, int type) |
| 300 | { | 273 | { |
| 301 | if (inet->fd != COMPAT_INVALIDFD) compat_close(inet->fd); | 274 | return sock_create(ps, AF_INET, type, 0); |
| 302 | inet->fd = compat_socket(AF_INET, type, 0); | ||
| 303 | if (inet->fd == COMPAT_INVALIDFD) return compat_socketstrerror(); | ||
| 304 | else return NULL; | ||
| 305 | } | 275 | } |
| 306 | 276 | ||
| 307 | /*-------------------------------------------------------------------------*\ | 277 | /*-------------------------------------------------------------------------*\ |
| @@ -1,38 +1,26 @@ | |||
| 1 | /*=========================================================================*\ | 1 | /*=========================================================================*\ |
| 2 | * Internet domain class: inherits from the Socket class, and implement | 2 | * Internet domain functions |
| 3 | * a few methods shared by all internet related objects | ||
| 4 | * | 3 | * |
| 5 | * RCS ID: $Id$ | 4 | * RCS ID: $Id$ |
| 6 | \*=========================================================================*/ | 5 | \*=========================================================================*/ |
| 7 | #ifndef INET_H_ | 6 | #ifndef INET_H |
| 8 | #define INET_H_ | 7 | #define INET_H |
| 9 | 8 | ||
| 10 | #include <lua.h> | 9 | #include <lua.h> |
| 11 | #include "lssock.h" | 10 | #include "sock.h" |
| 12 | |||
| 13 | /* class name */ | ||
| 14 | #define INET_CLASS "luasocket(inet)" | ||
| 15 | |||
| 16 | /*-------------------------------------------------------------------------*\ | ||
| 17 | * Socket fields | ||
| 18 | \*-------------------------------------------------------------------------*/ | ||
| 19 | #define INET_FIELDS SOCK_FIELDS | ||
| 20 | |||
| 21 | /*-------------------------------------------------------------------------*\ | ||
| 22 | * Socket structure | ||
| 23 | \*-------------------------------------------------------------------------*/ | ||
| 24 | typedef t_sock t_inet; | ||
| 25 | typedef t_inet *p_inet; | ||
| 26 | 11 | ||
| 27 | /*-------------------------------------------------------------------------*\ | 12 | /*-------------------------------------------------------------------------*\ |
| 28 | * Exported functions | 13 | * Exported functions |
| 29 | \*-------------------------------------------------------------------------*/ | 14 | \*-------------------------------------------------------------------------*/ |
| 30 | void inet_open(lua_State *L); | 15 | void inet_open(lua_State *L); |
| 31 | void inet_construct(lua_State *L, p_inet inet); | ||
| 32 | void inet_inherit(lua_State *L, cchar *lsclass); | ||
| 33 | 16 | ||
| 34 | cchar *inet_tryconnect(p_sock sock, cchar *address, ushort); | 17 | const char *inet_tryconnect(p_sock ps, const char *address, |
| 35 | cchar *inet_trybind(p_sock sock, cchar *address, ushort); | 18 | unsigned short port); |
| 36 | cchar *inet_trysocket(p_inet inet, int type); | 19 | const char *inet_trybind(p_sock ps, const char *address, |
| 20 | unsigned short port, int backlog); | ||
| 21 | const char *inet_trycreate(p_sock ps, int type); | ||
| 22 | |||
| 23 | int inet_meth_getpeername(lua_State *L, p_sock ps); | ||
| 24 | int inet_meth_getsockname(lua_State *L, p_sock ps); | ||
| 37 | 25 | ||
| 38 | #endif /* INET_H_ */ | 26 | #endif /* INET_H_ */ |
diff --git a/src/io.c b/src/io.c new file mode 100644 index 0000000..902124a --- /dev/null +++ b/src/io.c | |||
| @@ -0,0 +1,8 @@ | |||
| 1 | #include "io.h" | ||
| 2 | |||
| 3 | void io_init(p_io io, p_send send, p_recv recv, void *ctx) | ||
| 4 | { | ||
| 5 | io->send = send; | ||
| 6 | io->recv = recv; | ||
| 7 | io->ctx = ctx; | ||
| 8 | } | ||
diff --git a/src/io.h b/src/io.h new file mode 100644 index 0000000..b5b7f1d --- /dev/null +++ b/src/io.h | |||
| @@ -0,0 +1,34 @@ | |||
| 1 | #ifndef IO_H | ||
| 2 | #define IO_H | ||
| 3 | |||
| 4 | #include "error.h" | ||
| 5 | |||
| 6 | /* interface to send function */ | ||
| 7 | typedef int (*p_send) ( | ||
| 8 | void *ctx, /* context needed by send */ | ||
| 9 | const char *data, /* pointer to buffer with data to send */ | ||
| 10 | size_t count, /* number of bytes to send from buffer */ | ||
| 11 | size_t *sent, /* number of bytes sent uppon return */ | ||
| 12 | int timeout /* number of miliseconds left for transmission */ | ||
| 13 | ); | ||
| 14 | |||
| 15 | /* interface to recv function */ | ||
| 16 | typedef int (*p_recv) ( | ||
| 17 | void *ctx, /* context needed by recv */ | ||
| 18 | char *data, /* pointer to buffer where data will be writen */ | ||
| 19 | size_t count, /* number of bytes to receive into buffer */ | ||
| 20 | size_t *got, /* number of bytes received uppon return */ | ||
| 21 | int timeout /* number of miliseconds left for transmission */ | ||
| 22 | ); | ||
| 23 | |||
| 24 | /* IO driver definition */ | ||
| 25 | typedef struct t_io_ { | ||
| 26 | void *ctx; /* context needed by send/recv */ | ||
| 27 | p_send send; /* send function pointer */ | ||
| 28 | p_recv recv; /* receive function pointer */ | ||
| 29 | } t_io; | ||
| 30 | typedef t_io *p_io; | ||
| 31 | |||
| 32 | void io_init(p_io io, p_send send, p_recv recv, void *ctx); | ||
| 33 | |||
| 34 | #endif /* IO_H */ | ||
diff --git a/src/luasocket.c b/src/luasocket.c index bcc705f..53f8c21 100644 --- a/src/luasocket.c +++ b/src/luasocket.c | |||
| @@ -23,18 +23,13 @@ | |||
| 23 | * LuaSocket includes | 23 | * LuaSocket includes |
| 24 | \*=========================================================================*/ | 24 | \*=========================================================================*/ |
| 25 | #include "luasocket.h" | 25 | #include "luasocket.h" |
| 26 | #include "lspriv.h" | 26 | |
| 27 | #include "lsselect.h" | 27 | #include "tm.h" |
| 28 | #include "lscompat.h" | 28 | #include "buf.h" |
| 29 | #include "lsbase.h" | 29 | #include "sock.h" |
| 30 | #include "lstm.h" | 30 | #include "inet.h" |
| 31 | #include "lsbuf.h" | 31 | #include "tcp.h" |
| 32 | #include "lssock.h" | 32 | #include "udp.h" |
| 33 | #include "lsinet.h" | ||
| 34 | #include "lstcpc.h" | ||
| 35 | #include "lstcps.h" | ||
| 36 | #include "lstcps.h" | ||
| 37 | #include "lsudp.h" | ||
| 38 | 33 | ||
| 39 | /*=========================================================================*\ | 34 | /*=========================================================================*\ |
| 40 | * Exported functions | 35 | * Exported functions |
| @@ -42,34 +37,29 @@ | |||
| 42 | /*-------------------------------------------------------------------------*\ | 37 | /*-------------------------------------------------------------------------*\ |
| 43 | * Initializes all library modules. | 38 | * Initializes all library modules. |
| 44 | \*-------------------------------------------------------------------------*/ | 39 | \*-------------------------------------------------------------------------*/ |
| 45 | LUASOCKET_API int lua_socketlibopen(lua_State *L) | 40 | LUASOCKET_API int luaopen_socketlib(lua_State *L) |
| 46 | { | 41 | { |
| 47 | compat_open(L); | 42 | /* create namespace table */ |
| 48 | priv_open(L); | 43 | lua_pushstring(L, LUASOCKET_LIBNAME); |
| 49 | select_open(L); | 44 | lua_newtable(L); |
| 50 | base_open(L); | 45 | #ifdef LUASOCKET_DEBUG |
| 51 | tm_open(L); | 46 | lua_pushstring(L, "debug"); |
| 52 | fd_open(L); | 47 | lua_pushnumber(L, 1); |
| 48 | lua_settable(L, -3); | ||
| 49 | #endif | ||
| 50 | lua_settable(L, LUA_GLOBALSINDEX); | ||
| 51 | /* make sure modules know what is our namespace */ | ||
| 52 | lua_pushstring(L, "LUASOCKET_LIBNAME"); | ||
| 53 | lua_pushstring(L, LUASOCKET_LIBNAME); | ||
| 54 | lua_settable(L, LUA_GLOBALSINDEX); | ||
| 55 | /* initialize all modules */ | ||
| 53 | sock_open(L); | 56 | sock_open(L); |
| 54 | inet_open(L); | 57 | tm_open(L); |
| 55 | tcpc_open(L); | ||
| 56 | buf_open(L); | 58 | buf_open(L); |
| 57 | tcps_open(L); | 59 | inet_open(L); |
| 60 | tcp_open(L); | ||
| 58 | udp_open(L); | 61 | udp_open(L); |
| 59 | #ifdef LUASOCKET_DOFILE | 62 | /* load all Lua code */ |
| 60 | lua_dofile(L, "concat.lua"); | 63 | lua_dofile(L, "luasocket.lua"); |
| 61 | lua_dofile(L, "code.lua"); | ||
| 62 | lua_dofile(L, "url.lua"); | ||
| 63 | lua_dofile(L, "http.lua"); | ||
| 64 | lua_dofile(L, "smtp.lua"); | ||
| 65 | lua_dofile(L, "ftp.lua"); | ||
| 66 | #else | ||
| 67 | #include "concat.loh" | ||
| 68 | #include "code.loh" | ||
| 69 | #include "url.loh" | ||
| 70 | #include "http.loh" | ||
| 71 | #include "smtp.loh" | ||
| 72 | #include "ftp.loh" | ||
| 73 | #endif | ||
| 74 | return 0; | 64 | return 0; |
| 75 | } | 65 | } |
diff --git a/src/luasocket.h b/src/luasocket.h index fd22606..6c25af2 100644 --- a/src/luasocket.h +++ b/src/luasocket.h | |||
| @@ -5,8 +5,8 @@ | |||
| 5 | * | 5 | * |
| 6 | * RCS ID: $Id$ | 6 | * RCS ID: $Id$ |
| 7 | \*=========================================================================*/ | 7 | \*=========================================================================*/ |
| 8 | #ifndef _LUASOCKET_H_ | 8 | #ifndef LUASOCKET_H |
| 9 | #define _LUASOCKET_H_ | 9 | #define LUASOCKET_H |
| 10 | 10 | ||
| 11 | /*-------------------------------------------------------------------------*\ | 11 | /*-------------------------------------------------------------------------*\ |
| 12 | * Current luasocket version | 12 | * Current luasocket version |
| @@ -28,6 +28,6 @@ | |||
| 28 | /*-------------------------------------------------------------------------*\ | 28 | /*-------------------------------------------------------------------------*\ |
| 29 | * Initializes the library. | 29 | * Initializes the library. |
| 30 | \*-------------------------------------------------------------------------*/ | 30 | \*-------------------------------------------------------------------------*/ |
| 31 | LUASOCKET_API int lua_socketlibopen(lua_State *L); | 31 | LUASOCKET_API int luaopen_socketlib(lua_State *L); |
| 32 | 32 | ||
| 33 | #endif /* _LUASOCKET_H_ */ | 33 | #endif /* LUASOCKET_H */ |
diff --git a/src/mbox.lua b/src/mbox.lua index 4a72331..f52719b 100644 --- a/src/mbox.lua +++ b/src/mbox.lua | |||
| @@ -5,10 +5,10 @@ mbox = Public | |||
| 5 | function Public.split_message(message_s) | 5 | function Public.split_message(message_s) |
| 6 | local message = {} | 6 | local message = {} |
| 7 | message_s = string.gsub(message_s, "\r\n", "\n") | 7 | message_s = string.gsub(message_s, "\r\n", "\n") |
| 8 | string.gsub(message_s, "^(.-\n)\n", function (h) %message.headers = h end) | 8 | string.gsub(message_s, "^(.-\n)\n", function (h) message.headers = h end) |
| 9 | string.gsub(message_s, "^.-\n\n(.*)", function (b) %message.body = b end) | 9 | string.gsub(message_s, "^.-\n\n(.*)", function (b) message.body = b end) |
| 10 | if not message.body then | 10 | if not message.body then |
| 11 | string.gsub(message_s, "^\n(.*)", function (b) %message.body = b end) | 11 | string.gsub(message_s, "^\n(.*)", function (b) message.body = b end) |
| 12 | end | 12 | end |
| 13 | if not message.headers and not message.body then | 13 | if not message.headers and not message.body then |
| 14 | message.headers = message_s | 14 | message.headers = message_s |
| @@ -20,7 +20,7 @@ function Public.split_headers(headers_s) | |||
| 20 | local headers = {} | 20 | local headers = {} |
| 21 | headers_s = string.gsub(headers_s, "\r\n", "\n") | 21 | headers_s = string.gsub(headers_s, "\r\n", "\n") |
| 22 | headers_s = string.gsub(headers_s, "\n[ ]+", " ") | 22 | headers_s = string.gsub(headers_s, "\n[ ]+", " ") |
| 23 | string.gsub("\n" .. headers_s, "\n([^\n]+)", function (h) table.insert(%headers, h) end) | 23 | string.gsub("\n" .. headers_s, "\n([^\n]+)", function (h) table.insert(headers, h) end) |
| 24 | return headers | 24 | return headers |
| 25 | end | 25 | end |
| 26 | 26 | ||
| @@ -32,10 +32,10 @@ function Public.parse_header(header_s) | |||
| 32 | end | 32 | end |
| 33 | 33 | ||
| 34 | function Public.parse_headers(headers_s) | 34 | function Public.parse_headers(headers_s) |
| 35 | local headers_t = %Public.split_headers(headers_s) | 35 | local headers_t = Public.split_headers(headers_s) |
| 36 | local headers = {} | 36 | local headers = {} |
| 37 | for i = 1, table.getn(headers_t) do | 37 | for i = 1, table.getn(headers_t) do |
| 38 | local name, value = %Public.parse_header(headers_t[i]) | 38 | local name, value = Public.parse_header(headers_t[i]) |
| 39 | if name then | 39 | if name then |
| 40 | name = string.lower(name) | 40 | name = string.lower(name) |
| 41 | if headers[name] then | 41 | if headers[name] then |
| @@ -73,16 +73,16 @@ function Public.split_mbox(mbox_s) | |||
| 73 | end | 73 | end |
| 74 | 74 | ||
| 75 | function Public.parse(mbox_s) | 75 | function Public.parse(mbox_s) |
| 76 | local mbox = %Public.split_mbox(mbox_s) | 76 | local mbox = Public.split_mbox(mbox_s) |
| 77 | for i = 1, table.getn(mbox) do | 77 | for i = 1, table.getn(mbox) do |
| 78 | mbox[i] = %Public.parse_message(mbox[i]) | 78 | mbox[i] = Public.parse_message(mbox[i]) |
| 79 | end | 79 | end |
| 80 | return mbox | 80 | return mbox |
| 81 | end | 81 | end |
| 82 | 82 | ||
| 83 | function Public.parse_message(message_s) | 83 | function Public.parse_message(message_s) |
| 84 | local message = {} | 84 | local message = {} |
| 85 | message.headers, message.body = %Public.split_message(message_s) | 85 | message.headers, message.body = Public.split_message(message_s) |
| 86 | message.headers = %Public.parse_headers(message.headers) | 86 | message.headers = Public.parse_headers(message.headers) |
| 87 | return message | 87 | return message |
| 88 | end | 88 | end |
diff --git a/src/smtp.lua b/src/smtp.lua index 0ba2b0f..604f79b 100644 --- a/src/smtp.lua +++ b/src/smtp.lua | |||
| @@ -7,7 +7,8 @@ | |||
| 7 | ----------------------------------------------------------------------------- | 7 | ----------------------------------------------------------------------------- |
| 8 | 8 | ||
| 9 | local Public, Private = {}, {} | 9 | local Public, Private = {}, {} |
| 10 | socket.smtp = Public | 10 | local socket = _G[LUASOCKET_LIBNAME] -- get LuaSocket namespace |
| 11 | socket.smtp = Public -- create smtp sub namespace | ||
| 11 | 12 | ||
| 12 | ----------------------------------------------------------------------------- | 13 | ----------------------------------------------------------------------------- |
| 13 | -- Program constants | 14 | -- Program constants |
| @@ -23,32 +24,30 @@ Public.DOMAIN = os.getenv("SERVER_NAME") or "localhost" | |||
| 23 | Public.SERVER = "localhost" | 24 | Public.SERVER = "localhost" |
| 24 | 25 | ||
| 25 | ----------------------------------------------------------------------------- | 26 | ----------------------------------------------------------------------------- |
| 26 | -- Tries to send data through socket. Closes socket on error. | 27 | -- Tries to get a pattern from the server and closes socket on error |
| 27 | -- Input | 28 | -- sock: socket connected to the server |
| 28 | -- sock: server socket | 29 | -- pattern: pattern to receive |
| 29 | -- data: string to be sent | ||
| 30 | -- Returns | 30 | -- Returns |
| 31 | -- err: message in case of error, nil if successfull | 31 | -- received pattern on success |
| 32 | -- nil followed by error message on error | ||
| 32 | ----------------------------------------------------------------------------- | 33 | ----------------------------------------------------------------------------- |
| 33 | function Private.try_send(sock, data) | 34 | function Private.try_receive(sock, pattern) |
| 34 | local err = sock:send(data) | 35 | local data, err = sock:receive(pattern) |
| 35 | if err then sock:close() end | 36 | if not data then sock:close() end |
| 36 | return err | 37 | return data, err |
| 37 | end | 38 | end |
| 38 | 39 | ||
| 39 | ----------------------------------------------------------------------------- | 40 | ----------------------------------------------------------------------------- |
| 40 | -- Tries to get a pattern from the server and closes socket on error | 41 | -- Tries to send data to the server and closes socket on error |
| 41 | -- sock: socket opened to the server | 42 | -- sock: socket connected to the server |
| 42 | -- ...: pattern to receive | 43 | -- data: data to send |
| 43 | -- Returns | 44 | -- Returns |
| 44 | -- ...: received pattern | 45 | -- err: error message if any, nil if successfull |
| 45 | -- err: error message if any | ||
| 46 | ----------------------------------------------------------------------------- | 46 | ----------------------------------------------------------------------------- |
| 47 | function Private.try_receive(...) | 47 | function Private.try_send(sock, data) |
| 48 | local sock = arg[1] | 48 | local sent, err = sock:send(data) |
| 49 | local data, err = sock.receive(unpack(arg)) | 49 | if not sent then sock:close() end |
| 50 | if err then sock:close() end | 50 | return err |
| 51 | return data, err | ||
| 52 | end | 51 | end |
| 53 | 52 | ||
| 54 | ----------------------------------------------------------------------------- | 53 | ----------------------------------------------------------------------------- |
diff --git a/src/tcp.c b/src/tcp.c new file mode 100644 index 0000000..db6a38e --- /dev/null +++ b/src/tcp.c | |||
| @@ -0,0 +1,222 @@ | |||
| 1 | /*=========================================================================*\ | ||
| 2 | * TCP object | ||
| 3 | * | ||
| 4 | * RCS ID: $Id$ | ||
| 5 | \*=========================================================================*/ | ||
| 6 | #include <string.h> | ||
| 7 | |||
| 8 | #include <lua.h> | ||
| 9 | #include <lauxlib.h> | ||
| 10 | |||
| 11 | #include "luasocket.h" | ||
| 12 | |||
| 13 | #include "aux.h" | ||
| 14 | #include "inet.h" | ||
| 15 | #include "tcp.h" | ||
| 16 | |||
| 17 | /*=========================================================================*\ | ||
| 18 | * Internal function prototypes | ||
| 19 | \*=========================================================================*/ | ||
| 20 | static int tcp_global_create(lua_State *L); | ||
| 21 | static int tcp_meth_connect(lua_State *L); | ||
| 22 | static int tcp_meth_bind(lua_State *L); | ||
| 23 | static int tcp_meth_send(lua_State *L); | ||
| 24 | static int tcp_meth_getsockname(lua_State *L); | ||
| 25 | static int tcp_meth_getpeername(lua_State *L); | ||
| 26 | static int tcp_meth_receive(lua_State *L); | ||
| 27 | static int tcp_meth_accept(lua_State *L); | ||
| 28 | static int tcp_meth_close(lua_State *L); | ||
| 29 | static int tcp_meth_timeout(lua_State *L); | ||
| 30 | |||
| 31 | /* tcp object methods */ | ||
| 32 | static luaL_reg tcp[] = { | ||
| 33 | {"connect", tcp_meth_connect}, | ||
| 34 | {"send", tcp_meth_send}, | ||
| 35 | {"receive", tcp_meth_receive}, | ||
| 36 | {"bind", tcp_meth_bind}, | ||
| 37 | {"accept", tcp_meth_accept}, | ||
| 38 | {"setpeername", tcp_meth_connect}, | ||
| 39 | {"setsockname", tcp_meth_bind}, | ||
| 40 | {"getpeername", tcp_meth_getpeername}, | ||
| 41 | {"getsockname", tcp_meth_getsockname}, | ||
| 42 | {"timeout", tcp_meth_timeout}, | ||
| 43 | {"close", tcp_meth_close}, | ||
| 44 | {NULL, NULL} | ||
| 45 | }; | ||
| 46 | |||
| 47 | /* functions in library namespace */ | ||
| 48 | static luaL_reg func[] = { | ||
| 49 | {"tcp", tcp_global_create}, | ||
| 50 | {NULL, NULL} | ||
| 51 | }; | ||
| 52 | |||
| 53 | /*-------------------------------------------------------------------------*\ | ||
| 54 | * Initializes module | ||
| 55 | \*-------------------------------------------------------------------------*/ | ||
| 56 | void tcp_open(lua_State *L) | ||
| 57 | { | ||
| 58 | /* create classes */ | ||
| 59 | aux_newclass(L, "tcp{master}", tcp); | ||
| 60 | aux_newclass(L, "tcp{client}", tcp); | ||
| 61 | aux_newclass(L, "tcp{server}", tcp); | ||
| 62 | /* create class groups */ | ||
| 63 | aux_add2group(L, "tcp{client}", "tcp{client, server}"); | ||
| 64 | aux_add2group(L, "tcp{server}", "tcp{client, server}"); | ||
| 65 | aux_add2group(L, "tcp{master}", "tcp{any}"); | ||
| 66 | aux_add2group(L, "tcp{client}", "tcp{any}"); | ||
| 67 | aux_add2group(L, "tcp{server}", "tcp{any}"); | ||
| 68 | /* define library functions */ | ||
| 69 | luaL_openlib(L, LUASOCKET_LIBNAME, func, 0); | ||
| 70 | lua_pop(L, 1); | ||
| 71 | } | ||
| 72 | |||
| 73 | /*=========================================================================*\ | ||
| 74 | * Lua methods | ||
| 75 | \*=========================================================================*/ | ||
| 76 | /*-------------------------------------------------------------------------*\ | ||
| 77 | * Just call buffered IO methods | ||
| 78 | \*-------------------------------------------------------------------------*/ | ||
| 79 | static int tcp_meth_send(lua_State *L) | ||
| 80 | { | ||
| 81 | p_tcp tcp = (p_tcp) aux_checkclass(L, "tcp{client}", 1); | ||
| 82 | return buf_meth_send(L, &tcp->buf); | ||
| 83 | } | ||
| 84 | |||
| 85 | static int tcp_meth_receive(lua_State *L) | ||
| 86 | { | ||
| 87 | p_tcp tcp = (p_tcp) aux_checkclass(L, "tcp{client}", 1); | ||
| 88 | return buf_meth_receive(L, &tcp->buf); | ||
| 89 | } | ||
| 90 | |||
| 91 | /*-------------------------------------------------------------------------*\ | ||
| 92 | * Just call inet methods | ||
| 93 | \*-------------------------------------------------------------------------*/ | ||
| 94 | static int tcp_meth_getpeername(lua_State *L) | ||
| 95 | { | ||
| 96 | p_tcp tcp = (p_tcp) aux_checkclass(L, "tcp{client}", 1); | ||
| 97 | return inet_meth_getpeername(L, &tcp->sock); | ||
| 98 | } | ||
| 99 | |||
| 100 | static int tcp_meth_getsockname(lua_State *L) | ||
| 101 | { | ||
| 102 | p_tcp tcp = (p_tcp) aux_checkgroup(L, "tcp{client, server}", 1); | ||
| 103 | return inet_meth_getsockname(L, &tcp->sock); | ||
| 104 | } | ||
| 105 | |||
| 106 | /*-------------------------------------------------------------------------*\ | ||
| 107 | * Just call tm methods | ||
| 108 | \*-------------------------------------------------------------------------*/ | ||
| 109 | static int tcp_meth_timeout(lua_State *L) | ||
| 110 | { | ||
| 111 | p_tcp tcp = (p_tcp) aux_checkgroup(L, "tcp{any}", 1); | ||
| 112 | return tm_meth_timeout(L, &tcp->tm); | ||
| 113 | } | ||
| 114 | |||
| 115 | /*-------------------------------------------------------------------------*\ | ||
| 116 | * Closes socket used by object | ||
| 117 | \*-------------------------------------------------------------------------*/ | ||
| 118 | static int tcp_meth_close(lua_State *L) | ||
| 119 | { | ||
| 120 | p_tcp tcp = (p_tcp) aux_checkgroup(L, "tcp{any}", 1); | ||
| 121 | sock_destroy(&tcp->sock); | ||
| 122 | return 0; | ||
| 123 | } | ||
| 124 | |||
| 125 | /*-------------------------------------------------------------------------*\ | ||
| 126 | * Turns a master tcp object into a client object. | ||
| 127 | \*-------------------------------------------------------------------------*/ | ||
| 128 | static int tcp_meth_connect(lua_State *L) | ||
| 129 | { | ||
| 130 | p_tcp tcp = (p_tcp) aux_checkclass(L, "tcp{master}", 1); | ||
| 131 | const char *address = luaL_checkstring(L, 2); | ||
| 132 | unsigned short port = (ushort) luaL_checknumber(L, 3); | ||
| 133 | const char *err = inet_tryconnect(&tcp->sock, address, port); | ||
| 134 | if (err) { | ||
| 135 | lua_pushnil(L); | ||
| 136 | lua_pushstring(L, err); | ||
| 137 | return 2; | ||
| 138 | } | ||
| 139 | /* turn master object into a client object */ | ||
| 140 | aux_setclass(L, "tcp{client}", 1); | ||
| 141 | lua_pushnumber(L, 1); | ||
| 142 | return 1; | ||
| 143 | } | ||
| 144 | |||
| 145 | /*-------------------------------------------------------------------------*\ | ||
| 146 | * Turns a master object into a server object | ||
| 147 | \*-------------------------------------------------------------------------*/ | ||
| 148 | static int tcp_meth_bind(lua_State *L) | ||
| 149 | { | ||
| 150 | p_tcp tcp = (p_tcp) aux_checkclass(L, "tcp{master}", 1); | ||
| 151 | const char *address = luaL_checkstring(L, 2); | ||
| 152 | unsigned short port = (ushort) luaL_checknumber(L, 3); | ||
| 153 | int backlog = (int) luaL_optnumber(L, 4, 1); | ||
| 154 | const char *err = inet_trybind(&tcp->sock, address, port, backlog); | ||
| 155 | if (err) { | ||
| 156 | lua_pushnil(L); | ||
| 157 | lua_pushstring(L, err); | ||
| 158 | return 2; | ||
| 159 | } | ||
| 160 | /* turn master object into a server object */ | ||
| 161 | aux_setclass(L, "tcp{server}", 1); | ||
| 162 | lua_pushnumber(L, 1); | ||
| 163 | return 1; | ||
| 164 | } | ||
| 165 | |||
| 166 | /*-------------------------------------------------------------------------*\ | ||
| 167 | * Waits for and returns a client object attempting connection to the | ||
| 168 | * server object | ||
| 169 | \*-------------------------------------------------------------------------*/ | ||
| 170 | static int tcp_meth_accept(lua_State *L) | ||
| 171 | { | ||
| 172 | struct sockaddr_in addr; | ||
| 173 | size_t addr_len = sizeof(addr); | ||
| 174 | p_tcp server = (p_tcp) aux_checkclass(L, "tcp{server}", 1); | ||
| 175 | p_tm tm = &server->tm; | ||
| 176 | p_tcp client = lua_newuserdata(L, sizeof(t_tcp)); | ||
| 177 | tm_markstart(tm); | ||
| 178 | aux_setclass(L, "tcp{client}", -1); | ||
| 179 | for ( ;; ) { | ||
| 180 | sock_accept(&server->sock, &client->sock, | ||
| 181 | (SA *) &addr, &addr_len, tm_get(tm)); | ||
| 182 | if (client->sock == SOCK_INVALID) { | ||
| 183 | if (tm_get(tm) == 0) { | ||
| 184 | lua_pushnil(L); | ||
| 185 | error_push(L, IO_TIMEOUT); | ||
| 186 | return 2; | ||
| 187 | } | ||
| 188 | } else break; | ||
| 189 | } | ||
| 190 | /* initialize remaining structure fields */ | ||
| 191 | io_init(&client->io, (p_send) sock_send, (p_recv) sock_recv, &client->sock); | ||
| 192 | tm_init(&client->tm, -1, -1); | ||
| 193 | buf_init(&client->buf, &client->io, &client->tm); | ||
| 194 | return 1; | ||
| 195 | } | ||
| 196 | |||
| 197 | /*=========================================================================*\ | ||
| 198 | * Library functions | ||
| 199 | \*=========================================================================*/ | ||
| 200 | /*-------------------------------------------------------------------------*\ | ||
| 201 | * Creates a master tcp object | ||
| 202 | \*-------------------------------------------------------------------------*/ | ||
| 203 | int tcp_global_create(lua_State *L) | ||
| 204 | { | ||
| 205 | /* allocate tcp object */ | ||
| 206 | p_tcp tcp = (p_tcp) lua_newuserdata(L, sizeof(t_tcp)); | ||
| 207 | /* set its type as master object */ | ||
| 208 | aux_setclass(L, "tcp{master}", -1); | ||
| 209 | /* try to allocate a system socket */ | ||
| 210 | const char *err = inet_trycreate(&tcp->sock, SOCK_STREAM); | ||
| 211 | if (err) { /* get rid of object on stack and push error */ | ||
| 212 | lua_pop(L, 1); | ||
| 213 | lua_pushnil(L); | ||
| 214 | lua_pushstring(L, err); | ||
| 215 | return 2; | ||
| 216 | } | ||
| 217 | /* initialize remaining structure fields */ | ||
| 218 | io_init(&tcp->io, (p_send) sock_send, (p_recv) sock_recv, &tcp->sock); | ||
| 219 | tm_init(&tcp->tm, -1, -1); | ||
| 220 | buf_init(&tcp->buf, &tcp->io, &tcp->tm); | ||
| 221 | return 1; | ||
| 222 | } | ||
diff --git a/src/tcp.h b/src/tcp.h new file mode 100644 index 0000000..d4cc65c --- /dev/null +++ b/src/tcp.h | |||
| @@ -0,0 +1,20 @@ | |||
| 1 | #ifndef TCP_H | ||
| 2 | #define TCP_H | ||
| 3 | |||
| 4 | #include <lua.h> | ||
| 5 | |||
| 6 | #include "buf.h" | ||
| 7 | #include "tm.h" | ||
| 8 | #include "sock.h" | ||
| 9 | |||
| 10 | typedef struct t_tcp_ { | ||
| 11 | t_sock sock; | ||
| 12 | t_io io; | ||
| 13 | t_buf buf; | ||
| 14 | t_tm tm; | ||
| 15 | } t_tcp; | ||
| 16 | typedef t_tcp *p_tcp; | ||
| 17 | |||
| 18 | void tcp_open(lua_State *L); | ||
| 19 | |||
| 20 | #endif | ||
diff --git a/src/timeout.c b/src/timeout.c index 5549c89..17878aa 100644 --- a/src/timeout.c +++ b/src/timeout.c | |||
| @@ -1,18 +1,19 @@ | |||
| 1 | /*=========================================================================*\ | 1 | /*=========================================================================*\ |
| 2 | * Timeout management functions | 2 | * Timeout management functions |
| 3 | * Global Lua functions: | 3 | * Global Lua functions: |
| 4 | * _sleep: (debug mode only) | 4 | * _sleep |
| 5 | * _time: (debug mode only) | 5 | * _time |
| 6 | * | 6 | * |
| 7 | * RCS ID: $Id$ | 7 | * RCS ID: $Id$ |
| 8 | \*=========================================================================*/ | 8 | \*=========================================================================*/ |
| 9 | #include <stdio.h> | ||
| 10 | |||
| 9 | #include <lua.h> | 11 | #include <lua.h> |
| 10 | #include <lauxlib.h> | 12 | #include <lauxlib.h> |
| 11 | 13 | ||
| 12 | #include "lspriv.h" | 14 | #include "luasocket.h" |
| 13 | #include "lstm.h" | 15 | #include "aux.h" |
| 14 | 16 | #include "tm.h" | |
| 15 | #include <stdio.h> | ||
| 16 | 17 | ||
| 17 | #ifdef WIN32 | 18 | #ifdef WIN32 |
| 18 | #include <windows.h> | 19 | #include <windows.h> |
| @@ -28,78 +29,69 @@ | |||
| 28 | static int tm_lua_time(lua_State *L); | 29 | static int tm_lua_time(lua_State *L); |
| 29 | static int tm_lua_sleep(lua_State *L); | 30 | static int tm_lua_sleep(lua_State *L); |
| 30 | 31 | ||
| 32 | static luaL_reg func[] = { | ||
| 33 | { "time", tm_lua_time }, | ||
| 34 | { "sleep", tm_lua_sleep }, | ||
| 35 | { NULL, NULL } | ||
| 36 | }; | ||
| 37 | |||
| 31 | /*=========================================================================*\ | 38 | /*=========================================================================*\ |
| 32 | * Exported functions. | 39 | * Exported functions. |
| 33 | \*=========================================================================*/ | 40 | \*=========================================================================*/ |
| 34 | /*-------------------------------------------------------------------------*\ | 41 | /*-------------------------------------------------------------------------*\ |
| 35 | * Sets timeout limits | 42 | * Initialize structure |
| 36 | * Input | ||
| 37 | * tm: timeout control structure | ||
| 38 | * mode: block or return timeout | ||
| 39 | * value: timeout value in miliseconds | ||
| 40 | \*-------------------------------------------------------------------------*/ | 43 | \*-------------------------------------------------------------------------*/ |
| 41 | void tm_set(p_tm tm, int tm_block, int tm_return) | 44 | void tm_init(p_tm tm, int block, int total) |
| 42 | { | 45 | { |
| 43 | tm->tm_block = tm_block; | 46 | tm->block = block; |
| 44 | tm->tm_return = tm_return; | 47 | tm->total = total; |
| 45 | } | 48 | } |
| 46 | 49 | ||
| 47 | /*-------------------------------------------------------------------------*\ | 50 | /*-------------------------------------------------------------------------*\ |
| 48 | * Returns timeout limits | 51 | * Set and get timeout limits |
| 49 | * Input | ||
| 50 | * tm: timeout control structure | ||
| 51 | * mode: block or return timeout | ||
| 52 | * value: timeout value in miliseconds | ||
| 53 | \*-------------------------------------------------------------------------*/ | 52 | \*-------------------------------------------------------------------------*/ |
| 54 | void tm_get(p_tm tm, int *tm_block, int *tm_return) | 53 | void tm_setblock(p_tm tm, int block) |
| 55 | { | 54 | { tm->block = block; } |
| 56 | if (tm_block) *tm_block = tm->tm_block; | 55 | void tm_settotal(p_tm tm, int total) |
| 57 | if (tm_return) *tm_return = tm->tm_return; | 56 | { tm->total = total; } |
| 58 | } | 57 | int tm_getblock(p_tm tm) |
| 58 | { return tm->block; } | ||
| 59 | int tm_gettotal(p_tm tm) | ||
| 60 | { return tm->total; } | ||
| 61 | int tm_getstart(p_tm tm) | ||
| 62 | { return tm->start; } | ||
| 59 | 63 | ||
| 60 | /*-------------------------------------------------------------------------*\ | 64 | /*-------------------------------------------------------------------------*\ |
| 61 | * Determines how much time we have left for the current io operation | 65 | * Determines how much time we have left for the current operation |
| 62 | * an IO write operation. | ||
| 63 | * Input | 66 | * Input |
| 64 | * tm: timeout control structure | 67 | * tm: timeout control structure |
| 65 | * Returns | 68 | * Returns |
| 66 | * the number of ms left or -1 if there is no time limit | 69 | * the number of ms left or -1 if there is no time limit |
| 67 | \*-------------------------------------------------------------------------*/ | 70 | \*-------------------------------------------------------------------------*/ |
| 68 | int tm_getremaining(p_tm tm) | 71 | int tm_get(p_tm tm) |
| 69 | { | 72 | { |
| 70 | /* no timeout */ | 73 | /* no timeout */ |
| 71 | if (tm->tm_block < 0 && tm->tm_return < 0) | 74 | if (tm->block < 0 && tm->total < 0) |
| 72 | return -1; | 75 | return -1; |
| 73 | /* there is no block timeout, we use the return timeout */ | 76 | /* there is no block timeout, we use the return timeout */ |
| 74 | else if (tm->tm_block < 0) | 77 | else if (tm->block < 0) |
| 75 | return MAX(tm->tm_return - tm_gettime() + tm->tm_start, 0); | 78 | return MAX(tm->total - tm_gettime() + tm->start, 0); |
| 76 | /* there is no return timeout, we use the block timeout */ | 79 | /* there is no return timeout, we use the block timeout */ |
| 77 | else if (tm->tm_return < 0) | 80 | else if (tm->total < 0) |
| 78 | return tm->tm_block; | 81 | return tm->block; |
| 79 | /* both timeouts are specified */ | 82 | /* both timeouts are specified */ |
| 80 | else return MIN(tm->tm_block, | 83 | else return MIN(tm->block, |
| 81 | MAX(tm->tm_return - tm_gettime() + tm->tm_start, 0)); | 84 | MAX(tm->total - tm_gettime() + tm->start, 0)); |
| 82 | } | 85 | } |
| 83 | 86 | ||
| 84 | /*-------------------------------------------------------------------------*\ | 87 | /*-------------------------------------------------------------------------*\ |
| 85 | * Marks the operation start time in sock structure | 88 | * Marks the operation start time in structure |
| 86 | * Input | 89 | * Input |
| 87 | * tm: timeout control structure | 90 | * tm: timeout control structure |
| 88 | \*-------------------------------------------------------------------------*/ | 91 | \*-------------------------------------------------------------------------*/ |
| 89 | void tm_markstart(p_tm tm) | 92 | void tm_markstart(p_tm tm) |
| 90 | { | 93 | { |
| 91 | tm->tm_start = tm_gettime(); | 94 | tm->start = tm_gettime(); |
| 92 | tm->tm_end = tm->tm_start; | ||
| 93 | } | ||
| 94 | |||
| 95 | /*-------------------------------------------------------------------------*\ | ||
| 96 | * Returns the length of the operation in ms | ||
| 97 | * Input | ||
| 98 | * tm: timeout control structure | ||
| 99 | \*-------------------------------------------------------------------------*/ | ||
| 100 | int tm_getelapsed(p_tm tm) | ||
| 101 | { | ||
| 102 | return tm->tm_end - tm->tm_start; | ||
| 103 | } | 95 | } |
| 104 | 96 | ||
| 105 | /*-------------------------------------------------------------------------*\ | 97 | /*-------------------------------------------------------------------------*\ |
| @@ -125,11 +117,31 @@ int tm_gettime(void) | |||
| 125 | \*-------------------------------------------------------------------------*/ | 117 | \*-------------------------------------------------------------------------*/ |
| 126 | void tm_open(lua_State *L) | 118 | void tm_open(lua_State *L) |
| 127 | { | 119 | { |
| 128 | (void) L; | 120 | luaL_openlib(L, LUASOCKET_LIBNAME, func, 0); |
| 129 | lua_pushcfunction(L, tm_lua_time); | 121 | } |
| 130 | priv_newglobal(L, "_time"); | 122 | |
| 131 | lua_pushcfunction(L, tm_lua_sleep); | 123 | /*-------------------------------------------------------------------------*\ |
| 132 | priv_newglobal(L, "_sleep"); | 124 | * Sets timeout values for IO operations |
| 125 | * Lua Input: base, time [, mode] | ||
| 126 | * time: time out value in seconds | ||
| 127 | * mode: "b" for block timeout, "t" for total timeout. (default: b) | ||
| 128 | \*-------------------------------------------------------------------------*/ | ||
| 129 | int tm_meth_timeout(lua_State *L, p_tm tm) | ||
| 130 | { | ||
| 131 | int ms = lua_isnil(L, 2) ? -1 : (int) (luaL_checknumber(L, 2)*1000.0); | ||
| 132 | const char *mode = luaL_optstring(L, 3, "b"); | ||
| 133 | switch (*mode) { | ||
| 134 | case 'b': | ||
| 135 | tm_setblock(tm, ms); | ||
| 136 | break; | ||
| 137 | case 'r': case 't': | ||
| 138 | tm_settotal(tm, ms); | ||
| 139 | break; | ||
| 140 | default: | ||
| 141 | luaL_argcheck(L, 0, 3, "invalid timeout mode"); | ||
| 142 | break; | ||
| 143 | } | ||
| 144 | return 0; | ||
| 133 | } | 145 | } |
| 134 | 146 | ||
| 135 | /*=========================================================================*\ | 147 | /*=========================================================================*\ |
diff --git a/src/timeout.h b/src/timeout.h index 1dc0a5a..43476cb 100644 --- a/src/timeout.h +++ b/src/timeout.h | |||
| @@ -3,23 +3,29 @@ | |||
| 3 | * | 3 | * |
| 4 | * RCS ID: $Id$ | 4 | * RCS ID: $Id$ |
| 5 | \*=========================================================================*/ | 5 | \*=========================================================================*/ |
| 6 | #ifndef _TM_H | 6 | #ifndef TM_H |
| 7 | #define _TM_H | 7 | #define TM_H |
| 8 | 8 | ||
| 9 | typedef struct t_tm_tag { | 9 | #include <lua.h> |
| 10 | int tm_return; | 10 | |
| 11 | int tm_block; | 11 | /* timeout control structure */ |
| 12 | int tm_start; | 12 | typedef struct t_tm_ { |
| 13 | int tm_end; | 13 | int total; /* total number of miliseconds for operation */ |
| 14 | int block; /* maximum time for blocking calls */ | ||
| 15 | int start; /* time of start of operation */ | ||
| 14 | } t_tm; | 16 | } t_tm; |
| 15 | typedef t_tm *p_tm; | 17 | typedef t_tm *p_tm; |
| 16 | 18 | ||
| 17 | void tm_set(p_tm tm, int tm_block, int tm_return); | ||
| 18 | int tm_getremaining(p_tm tm); | ||
| 19 | int tm_getelapsed(p_tm tm); | ||
| 20 | int tm_gettime(void); | ||
| 21 | void tm_get(p_tm tm, int *tm_block, int *tm_return); | ||
| 22 | void tm_markstart(p_tm tm); | ||
| 23 | void tm_open(lua_State *L); | 19 | void tm_open(lua_State *L); |
| 20 | void tm_init(p_tm tm, int block, int total); | ||
| 21 | void tm_setblock(p_tm tm, int block); | ||
| 22 | void tm_settotal(p_tm tm, int total); | ||
| 23 | int tm_getblock(p_tm tm); | ||
| 24 | int tm_gettotal(p_tm tm); | ||
| 25 | void tm_markstart(p_tm tm); | ||
| 26 | int tm_getstart(p_tm tm); | ||
| 27 | int tm_get(p_tm tm); | ||
| 28 | int tm_gettime(void); | ||
| 29 | int tm_meth_timeout(lua_State *L, p_tm tm); | ||
| 24 | 30 | ||
| 25 | #endif | 31 | #endif |
| @@ -1,299 +1,263 @@ | |||
| 1 | /*=========================================================================*\ | 1 | /*=========================================================================*\ |
| 2 | * UDP class: inherits from Socked and Internet domain classes and provides | 2 | * UDP object |
| 3 | * all the functionality for UDP objects. | ||
| 4 | * Lua methods: | ||
| 5 | * send: using compat module | ||
| 6 | * sendto: using compat module | ||
| 7 | * receive: using compat module | ||
| 8 | * receivefrom: using compat module | ||
| 9 | * setpeername: using internet module | ||
| 10 | * setsockname: using internet module | ||
| 11 | * Global Lua functions: | ||
| 12 | * udp: creates the udp object | ||
| 13 | * | 3 | * |
| 14 | * RCS ID: $Id$ | 4 | * RCS ID: $Id$ |
| 15 | \*=========================================================================*/ | 5 | \*=========================================================================*/ |
| 16 | #include <string.h> | 6 | #include <string.h> |
| 17 | 7 | ||
| 18 | #include <lua.h> | 8 | #include <lua.h> |
| 19 | #include <lauxlib.h> | 9 | #include <lauxlib.h> |
| 20 | 10 | ||
| 21 | #include "lsinet.h" | 11 | #include "luasocket.h" |
| 22 | #include "lsudp.h" | 12 | |
| 23 | #include "lscompat.h" | 13 | #include "aux.h" |
| 24 | #include "lsselect.h" | 14 | #include "inet.h" |
| 15 | #include "udp.h" | ||
| 25 | 16 | ||
| 26 | /*=========================================================================*\ | 17 | /*=========================================================================*\ |
| 27 | * Internal function prototypes. | 18 | * Internal function prototypes |
| 28 | \*=========================================================================*/ | 19 | \*=========================================================================*/ |
| 29 | static int udp_lua_send(lua_State *L); | 20 | static int udp_global_create(lua_State *L); |
| 30 | static int udp_lua_sendto(lua_State *L); | 21 | static int udp_meth_send(lua_State *L); |
| 31 | static int udp_lua_receive(lua_State *L); | 22 | static int udp_meth_sendto(lua_State *L); |
| 32 | static int udp_lua_receivefrom(lua_State *L); | 23 | static int udp_meth_receive(lua_State *L); |
| 33 | static int udp_lua_setpeername(lua_State *L); | 24 | static int udp_meth_receivefrom(lua_State *L); |
| 34 | static int udp_lua_setsockname(lua_State *L); | 25 | static int udp_meth_getsockname(lua_State *L); |
| 26 | static int udp_meth_getpeername(lua_State *L); | ||
| 27 | static int udp_meth_setsockname(lua_State *L); | ||
| 28 | static int udp_meth_setpeername(lua_State *L); | ||
| 29 | static int udp_meth_close(lua_State *L); | ||
| 30 | static int udp_meth_timeout(lua_State *L); | ||
| 35 | 31 | ||
| 36 | static int udp_global_udp(lua_State *L); | 32 | /* udp object methods */ |
| 33 | static luaL_reg udp[] = { | ||
| 34 | {"setpeername", udp_meth_setpeername}, | ||
| 35 | {"setsockname", udp_meth_setsockname}, | ||
| 36 | {"getsockname", udp_meth_getsockname}, | ||
| 37 | {"getpeername", udp_meth_getpeername}, | ||
| 38 | {"send", udp_meth_send}, | ||
| 39 | {"sendto", udp_meth_sendto}, | ||
| 40 | {"receive", udp_meth_receive}, | ||
| 41 | {"receivefrom", udp_meth_receivefrom}, | ||
| 42 | {"timeout", udp_meth_timeout}, | ||
| 43 | {"close", udp_meth_close}, | ||
| 44 | {NULL, NULL} | ||
| 45 | }; | ||
| 37 | 46 | ||
| 38 | static struct luaL_reg funcs[] = { | 47 | /* functions in library namespace */ |
| 39 | {"send", udp_lua_send}, | 48 | static luaL_reg func[] = { |
| 40 | {"sendto", udp_lua_sendto}, | 49 | {"udp", udp_global_create}, |
| 41 | {"receive", udp_lua_receive}, | 50 | {NULL, NULL} |
| 42 | {"receivefrom", udp_lua_receivefrom}, | ||
| 43 | {"setpeername", udp_lua_setpeername}, | ||
| 44 | {"setsockname", udp_lua_setsockname}, | ||
| 45 | }; | 51 | }; |
| 46 | 52 | ||
| 47 | /*=========================================================================*\ | ||
| 48 | * Exported functions | ||
| 49 | \*=========================================================================*/ | ||
| 50 | /*-------------------------------------------------------------------------*\ | 53 | /*-------------------------------------------------------------------------*\ |
| 51 | * Initializes module | 54 | * Initializes module |
| 52 | \*-------------------------------------------------------------------------*/ | 55 | \*-------------------------------------------------------------------------*/ |
| 53 | void udp_open(lua_State *L) | 56 | void udp_open(lua_State *L) |
| 54 | { | 57 | { |
| 55 | unsigned int i; | 58 | /* create classes */ |
| 56 | priv_newclass(L, UDP_CLASS); | 59 | aux_newclass(L, "udp{connected}", udp); |
| 57 | udp_inherit(L, UDP_CLASS); | 60 | aux_newclass(L, "udp{unconnected}", udp); |
| 58 | /* declare global functions */ | 61 | /* create class groups */ |
| 59 | lua_pushcfunction(L, udp_global_udp); | 62 | aux_add2group(L, "udp{connected}", "udp{any}"); |
| 60 | priv_newglobal(L, "udp"); | 63 | aux_add2group(L, "udp{unconnected}", "udp{any}"); |
| 61 | for (i = 0; i < sizeof(funcs)/sizeof(funcs[0]); i++) | 64 | /* define library functions */ |
| 62 | priv_newglobalmethod(L, funcs[i].name); | 65 | luaL_openlib(L, LUASOCKET_LIBNAME, func, 0); |
| 63 | /* make class selectable */ | 66 | lua_pop(L, 1); |
| 64 | select_addclass(L, UDP_CLASS); | ||
| 65 | } | ||
| 66 | |||
| 67 | /*-------------------------------------------------------------------------*\ | ||
| 68 | * Hook object methods to methods table. | ||
| 69 | \*-------------------------------------------------------------------------*/ | ||
| 70 | void udp_inherit(lua_State *L, cchar *lsclass) | ||
| 71 | { | ||
| 72 | unsigned int i; | ||
| 73 | inet_inherit(L, lsclass); | ||
| 74 | for (i = 0; i < sizeof(funcs)/sizeof(funcs[0]); i++) { | ||
| 75 | lua_pushcfunction(L, funcs[i].func); | ||
| 76 | priv_setmethod(L, lsclass, funcs[i].name); | ||
| 77 | } | ||
| 78 | } | 67 | } |
| 79 | 68 | ||
| 69 | /*=========================================================================*\ | ||
| 70 | * Lua methods | ||
| 71 | \*=========================================================================*/ | ||
| 80 | /*-------------------------------------------------------------------------*\ | 72 | /*-------------------------------------------------------------------------*\ |
| 81 | * Initializes socket structure | 73 | * Send data through connected udp socket |
| 82 | \*-------------------------------------------------------------------------*/ | 74 | \*-------------------------------------------------------------------------*/ |
| 83 | void udp_construct(lua_State *L, p_udp udp) | 75 | static int udp_meth_send(lua_State *L) |
| 84 | { | 76 | { |
| 85 | inet_construct(L, (p_inet) udp); | 77 | p_udp udp = (p_udp) aux_checkclass(L, "udp{connected}", 1); |
| 86 | udp->udp_connected = 0; | 78 | p_tm tm = &udp->tm; |
| 79 | size_t count, sent = 0; | ||
| 80 | int err; | ||
| 81 | const char *data = luaL_checklstring(L, 2, &count); | ||
| 82 | tm_markstart(tm); | ||
| 83 | err = sock_send(&udp->sock, data, count, &sent, tm_get(tm)); | ||
| 84 | if (err == IO_DONE) lua_pushnumber(L, sent); | ||
| 85 | else lua_pushnil(L); | ||
| 86 | error_push(L, err); | ||
| 87 | return 2; | ||
| 87 | } | 88 | } |
| 88 | 89 | ||
| 89 | /*-------------------------------------------------------------------------*\ | 90 | /*-------------------------------------------------------------------------*\ |
| 90 | * Creates a socket structure and initializes it. A socket object is | 91 | * Send data through unconnected udp socket |
| 91 | * left in the Lua stack. | ||
| 92 | * Returns | ||
| 93 | * pointer to allocated structure | ||
| 94 | \*-------------------------------------------------------------------------*/ | 92 | \*-------------------------------------------------------------------------*/ |
| 95 | p_udp udp_push(lua_State *L) | 93 | static int udp_meth_sendto(lua_State *L) |
| 96 | { | 94 | { |
| 97 | p_udp udp = (p_udp) lua_newuserdata(L, sizeof(t_udp)); | 95 | p_udp udp = (p_udp) aux_checkclass(L, "udp{unconnected}", 1); |
| 98 | priv_setclass(L, UDP_CLASS); | 96 | size_t count, sent = 0; |
| 99 | udp_construct(L, udp); | 97 | const char *data = luaL_checklstring(L, 2, &count); |
| 100 | return udp; | 98 | const char *ip = luaL_checkstring(L, 3); |
| 99 | ushort port = (ushort) luaL_checknumber(L, 4); | ||
| 100 | p_tm tm = &udp->tm; | ||
| 101 | struct sockaddr_in addr; | ||
| 102 | int err; | ||
| 103 | memset(&addr, 0, sizeof(addr)); | ||
| 104 | if (!inet_aton(ip, &addr.sin_addr)) | ||
| 105 | luaL_argerror(L, 3, "invalid ip address"); | ||
| 106 | addr.sin_family = AF_INET; | ||
| 107 | addr.sin_port = htons(port); | ||
| 108 | tm_markstart(tm); | ||
| 109 | err = sock_sendto(&udp->sock, data, count, &sent, | ||
| 110 | (SA *) &addr, sizeof(addr), tm_get(tm)); | ||
| 111 | if (err == IO_DONE) lua_pushnumber(L, sent); | ||
| 112 | else lua_pushnil(L); | ||
| 113 | error_push(L, err == IO_CLOSED ? IO_REFUSED : err); | ||
| 114 | return 2; | ||
| 101 | } | 115 | } |
| 102 | 116 | ||
| 103 | /*=========================================================================*\ | ||
| 104 | * Socket table constructors | ||
| 105 | \*=========================================================================*/ | ||
| 106 | /*-------------------------------------------------------------------------*\ | ||
| 107 | * Creates a udp socket object and returns it to the Lua script. | ||
| 108 | * Lua Input: [options] | ||
| 109 | * options: socket options table | ||
| 110 | * Lua Returns | ||
| 111 | * On success: udp socket | ||
| 112 | * On error: nil, followed by an error message | ||
| 113 | \*-------------------------------------------------------------------------*/ | ||
| 114 | static int udp_global_udp(lua_State *L) | ||
| 115 | { | ||
| 116 | int oldtop = lua_gettop(L); | ||
| 117 | p_udp udp = udp_push(L); | ||
| 118 | cchar *err = inet_trysocket((p_inet) udp, SOCK_DGRAM); | ||
| 119 | if (err) { | ||
| 120 | lua_pushnil(L); | ||
| 121 | lua_pushstring(L, err); | ||
| 122 | return 2; | ||
| 123 | } | ||
| 124 | if (oldtop < 1) return 1; | ||
| 125 | err = compat_trysetoptions(L, udp->fd); | ||
| 126 | if (err) { | ||
| 127 | lua_pushnil(L); | ||
| 128 | lua_pushstring(L, err); | ||
| 129 | return 2; | ||
| 130 | } | ||
| 131 | return 1; | ||
| 132 | } | ||
| 133 | |||
| 134 | /*=========================================================================*\ | ||
| 135 | * Socket table methods | ||
| 136 | \*=========================================================================*/ | ||
| 137 | /*-------------------------------------------------------------------------*\ | 117 | /*-------------------------------------------------------------------------*\ |
| 138 | * Receives data from a UDP socket | 118 | * Receives data from a UDP socket |
| 139 | * Lua Input: sock [, wanted] | ||
| 140 | * sock: client socket created by the connect function | ||
| 141 | * wanted: the number of bytes expected (default: LUASOCKET_UDPBUFFERSIZE) | ||
| 142 | * Lua Returns | ||
| 143 | * On success: datagram received | ||
| 144 | * On error: nil, followed by an error message | ||
| 145 | \*-------------------------------------------------------------------------*/ | 119 | \*-------------------------------------------------------------------------*/ |
| 146 | static int udp_lua_receive(lua_State *L) | 120 | static int udp_meth_receive(lua_State *L) |
| 147 | { | 121 | { |
| 148 | p_udp udp = (p_udp) lua_touserdata(L, 1); | 122 | p_udp udp = (p_udp) aux_checkgroup(L, "udp{any}", 1); |
| 149 | char buffer[UDP_DATAGRAMSIZE]; | 123 | char buffer[UDP_DATAGRAMSIZE]; |
| 150 | size_t got, wanted = (size_t) luaL_optnumber(L, 2, sizeof(buffer)); | 124 | size_t got, count = (size_t) luaL_optnumber(L, 2, sizeof(buffer)); |
| 151 | int err; | 125 | int err; |
| 152 | p_tm tm = &udp->base_tm; | 126 | p_tm tm = &udp->tm; |
| 153 | wanted = MIN(wanted, sizeof(buffer)); | 127 | count = MIN(count, sizeof(buffer)); |
| 154 | tm_markstart(tm); | 128 | tm_markstart(tm); |
| 155 | err = compat_recv(udp->fd, buffer, wanted, &got, tm_getremaining(tm)); | 129 | err = sock_recv(&udp->sock, buffer, count, &got, tm_get(tm)); |
| 156 | if (err == PRIV_CLOSED) err = PRIV_REFUSED; | 130 | if (err == IO_DONE) lua_pushlstring(L, buffer, got); |
| 157 | if (err != PRIV_DONE) lua_pushnil(L); | 131 | else lua_pushnil(L); |
| 158 | else lua_pushlstring(L, buffer, got); | 132 | error_push(L, err); |
| 159 | priv_pusherror(L, err); | ||
| 160 | return 2; | 133 | return 2; |
| 161 | } | 134 | } |
| 162 | 135 | ||
| 163 | /*-------------------------------------------------------------------------*\ | 136 | /*-------------------------------------------------------------------------*\ |
| 164 | * Receives a datagram from a UDP socket | 137 | * Receives data and sender from a UDP socket |
| 165 | * Lua Input: sock [, wanted] | ||
| 166 | * sock: client socket created by the connect function | ||
| 167 | * wanted: the number of bytes expected (default: LUASOCKET_UDPBUFFERSIZE) | ||
| 168 | * Lua Returns | ||
| 169 | * On success: datagram received, ip and port of sender | ||
| 170 | * On error: nil, followed by an error message | ||
| 171 | \*-------------------------------------------------------------------------*/ | 138 | \*-------------------------------------------------------------------------*/ |
| 172 | static int udp_lua_receivefrom(lua_State *L) | 139 | static int udp_meth_receivefrom(lua_State *L) |
| 173 | { | 140 | { |
| 174 | p_udp udp = (p_udp) lua_touserdata(L, 1); | 141 | p_udp udp = (p_udp) aux_checkclass(L, "udp{unconnected}", 1); |
| 175 | p_tm tm = &udp->base_tm; | 142 | struct sockaddr_in addr; |
| 176 | struct sockaddr_in peer; | 143 | size_t addr_len = sizeof(addr); |
| 177 | size_t peer_len = sizeof(peer); | ||
| 178 | char buffer[UDP_DATAGRAMSIZE]; | 144 | char buffer[UDP_DATAGRAMSIZE]; |
| 179 | size_t wanted = (size_t) luaL_optnumber(L, 2, sizeof(buffer)); | 145 | size_t got, count = (size_t) luaL_optnumber(L, 2, sizeof(buffer)); |
| 180 | size_t got; | ||
| 181 | int err; | 146 | int err; |
| 182 | if (udp->udp_connected) luaL_error(L, "receivefrom on connected socket"); | 147 | p_tm tm = &udp->tm; |
| 183 | tm_markstart(tm); | 148 | tm_markstart(tm); |
| 184 | wanted = MIN(wanted, sizeof(buffer)); | 149 | count = MIN(count, sizeof(buffer)); |
| 185 | err = compat_recvfrom(udp->fd, buffer, wanted, &got, tm_getremaining(tm), | 150 | err = sock_recvfrom(&udp->sock, buffer, count, &got, |
| 186 | (SA *) &peer, &peer_len); | 151 | (SA *) &addr, &addr_len, tm_get(tm)); |
| 187 | if (err == PRIV_CLOSED) err = PRIV_REFUSED; | 152 | if (err == IO_DONE) { |
| 188 | if (err == PRIV_DONE) { | ||
| 189 | lua_pushlstring(L, buffer, got); | 153 | lua_pushlstring(L, buffer, got); |
| 190 | lua_pushstring(L, inet_ntoa(peer.sin_addr)); | 154 | lua_pushstring(L, inet_ntoa(addr.sin_addr)); |
| 191 | lua_pushnumber(L, ntohs(peer.sin_port)); | 155 | lua_pushnumber(L, ntohs(addr.sin_port)); |
| 192 | return 3; | 156 | return 3; |
| 193 | } else { | 157 | } else { |
| 194 | lua_pushnil(L); | 158 | lua_pushnil(L); |
| 195 | priv_pusherror(L, err); | 159 | error_push(L, err); |
| 196 | return 2; | 160 | return 2; |
| 197 | } | 161 | } |
| 198 | } | 162 | } |
| 199 | 163 | ||
| 200 | /*-------------------------------------------------------------------------*\ | 164 | /*-------------------------------------------------------------------------*\ |
| 201 | * Send data through a connected UDP socket | 165 | * Just call inet methods |
| 202 | * Lua Input: sock, data | ||
| 203 | * sock: udp socket | ||
| 204 | * data: data to be sent | ||
| 205 | * Lua Returns | ||
| 206 | * On success: nil, followed by the total number of bytes sent | ||
| 207 | * On error: error message | ||
| 208 | \*-------------------------------------------------------------------------*/ | 166 | \*-------------------------------------------------------------------------*/ |
| 209 | static int udp_lua_send(lua_State *L) | 167 | static int udp_meth_getpeername(lua_State *L) |
| 210 | { | 168 | { |
| 211 | p_udp udp = (p_udp) lua_touserdata(L, 1); | 169 | p_udp udp = (p_udp) aux_checkclass(L, "udp{connected}", 1); |
| 212 | p_tm tm = &udp->base_tm; | 170 | return inet_meth_getpeername(L, &udp->sock); |
| 213 | size_t wanted, sent = 0; | 171 | } |
| 214 | int err; | 172 | |
| 215 | cchar *data = luaL_checklstring(L, 2, &wanted); | 173 | static int udp_meth_getsockname(lua_State *L) |
| 216 | if (!udp->udp_connected) luaL_error(L, "send on unconnected socket"); | 174 | { |
| 217 | tm_markstart(tm); | 175 | p_udp udp = (p_udp) aux_checkgroup(L, "udp{any}", 1); |
| 218 | err = compat_send(udp->fd, data, wanted, &sent, tm_getremaining(tm)); | 176 | return inet_meth_getsockname(L, &udp->sock); |
| 219 | priv_pusherror(L, err == PRIV_CLOSED ? PRIV_REFUSED : err); | ||
| 220 | lua_pushnumber(L, sent); | ||
| 221 | return 2; | ||
| 222 | } | 177 | } |
| 223 | 178 | ||
| 224 | /*-------------------------------------------------------------------------*\ | 179 | /*-------------------------------------------------------------------------*\ |
| 225 | * Send data through a unconnected UDP socket | 180 | * Just call tm methods |
| 226 | * Lua Input: sock, data, ip, port | ||
| 227 | * sock: udp socket | ||
| 228 | * data: data to be sent | ||
| 229 | * ip: ip address of target | ||
| 230 | * port: port in target | ||
| 231 | * Lua Returns | ||
| 232 | * On success: nil, followed by the total number of bytes sent | ||
| 233 | * On error: error message | ||
| 234 | \*-------------------------------------------------------------------------*/ | 181 | \*-------------------------------------------------------------------------*/ |
| 235 | static int udp_lua_sendto(lua_State *L) | 182 | static int udp_meth_timeout(lua_State *L) |
| 236 | { | 183 | { |
| 237 | p_udp udp = (p_udp) lua_touserdata(L, 1); | 184 | p_udp udp = (p_udp) aux_checkgroup(L, "udp{any}", 1); |
| 238 | size_t wanted, sent = 0; | 185 | return tm_meth_timeout(L, &udp->tm); |
| 239 | cchar *data = luaL_checklstring(L, 2, &wanted); | ||
| 240 | cchar *ip = luaL_checkstring(L, 3); | ||
| 241 | ushort port = (ushort) luaL_checknumber(L, 4); | ||
| 242 | p_tm tm = &udp->base_tm; | ||
| 243 | struct sockaddr_in peer; | ||
| 244 | int err; | ||
| 245 | if (udp->udp_connected) luaL_error(L, "sendto on connected socket"); | ||
| 246 | memset(&peer, 0, sizeof(peer)); | ||
| 247 | if (!inet_aton(ip, &peer.sin_addr)) luaL_error(L, "invalid ip address"); | ||
| 248 | peer.sin_family = AF_INET; | ||
| 249 | peer.sin_port = htons(port); | ||
| 250 | tm_markstart(tm); | ||
| 251 | err = compat_sendto(udp->fd, data, wanted, &sent, tm_getremaining(tm), | ||
| 252 | (SA *) &peer, sizeof(peer)); | ||
| 253 | priv_pusherror(L, err == PRIV_CLOSED ? PRIV_REFUSED : err); | ||
| 254 | lua_pushnumber(L, sent); | ||
| 255 | return 2; | ||
| 256 | } | 186 | } |
| 257 | 187 | ||
| 258 | /*-------------------------------------------------------------------------*\ | 188 | /*-------------------------------------------------------------------------*\ |
| 259 | * Associates a local address to an UDP socket | 189 | * Turns a master udp object into a client object. |
| 260 | * Lua Input: address, port | ||
| 261 | * address: host name or ip address to bind to | ||
| 262 | * port: port to bind to | ||
| 263 | * Lua Returns | ||
| 264 | * On success: nil | ||
| 265 | * On error: error message | ||
| 266 | \*-------------------------------------------------------------------------*/ | 190 | \*-------------------------------------------------------------------------*/ |
| 267 | static int udp_lua_setsockname(lua_State * L) | 191 | static int udp_meth_setpeername(lua_State *L) |
| 268 | { | 192 | { |
| 269 | p_udp udp = (p_udp) lua_touserdata(L, 1); | 193 | p_udp udp = (p_udp) aux_checkclass(L, "udp{unconnected}", 1); |
| 270 | cchar *address = luaL_checkstring(L, 2); | 194 | const char *address = luaL_checkstring(L, 2); |
| 271 | ushort port = (ushort) luaL_checknumber(L, 3); | 195 | int connecting = strcmp(address, "*"); |
| 272 | cchar *err = inet_trybind((p_inet) udp, address, port); | 196 | unsigned short port = connecting ? |
| 273 | if (err) lua_pushstring(L, err); | 197 | (ushort) luaL_checknumber(L, 3) : (ushort) luaL_optnumber(L, 3, 0); |
| 274 | else lua_pushnil(L); | 198 | const char *err = inet_tryconnect(&udp->sock, address, port); |
| 199 | if (err) { | ||
| 200 | lua_pushnil(L); | ||
| 201 | lua_pushstring(L, err); | ||
| 202 | return 2; | ||
| 203 | } | ||
| 204 | /* change class to connected or unconnected depending on address */ | ||
| 205 | if (connecting) aux_setclass(L, "udp{connected}", 1); | ||
| 206 | else aux_setclass(L, "udp{unconnected}", 1); | ||
| 207 | lua_pushnumber(L, 1); | ||
| 275 | return 1; | 208 | return 1; |
| 276 | } | 209 | } |
| 277 | 210 | ||
| 278 | /*-------------------------------------------------------------------------*\ | 211 | /*-------------------------------------------------------------------------*\ |
| 279 | * Sets a peer for a UDP socket | 212 | * Closes socket used by object |
| 280 | * Lua Input: address, port | 213 | \*-------------------------------------------------------------------------*/ |
| 281 | * address: remote host name | 214 | static int udp_meth_close(lua_State *L) |
| 282 | * port: remote host port | 215 | { |
| 283 | * Lua Returns | 216 | p_udp udp = (p_udp) aux_checkgroup(L, "udp{any}", 1); |
| 284 | * On success: nil | 217 | sock_destroy(&udp->sock); |
| 285 | * On error: error message | 218 | return 0; |
| 219 | } | ||
| 220 | |||
| 221 | /*-------------------------------------------------------------------------*\ | ||
| 222 | * Turns a master object into a server object | ||
| 286 | \*-------------------------------------------------------------------------*/ | 223 | \*-------------------------------------------------------------------------*/ |
| 287 | static int udp_lua_setpeername(lua_State *L) | 224 | static int udp_meth_setsockname(lua_State *L) |
| 288 | { | 225 | { |
| 289 | p_udp udp = (p_udp) lua_touserdata(L, 1); | 226 | p_udp udp = (p_udp) aux_checkclass(L, "udp{master}", 1); |
| 290 | cchar *address = luaL_checkstring(L, 2); | 227 | const char *address = luaL_checkstring(L, 2); |
| 291 | ushort port = (ushort) luaL_checknumber(L, 3); | 228 | unsigned short port = (ushort) luaL_checknumber(L, 3); |
| 292 | cchar *err = inet_tryconnect((p_inet) udp, address, port); | 229 | const char *err = inet_trybind(&udp->sock, address, port, -1); |
| 293 | if (!err) { | 230 | if (err) { |
| 294 | udp->udp_connected = 1; | ||
| 295 | lua_pushnil(L); | 231 | lua_pushnil(L); |
| 296 | } else lua_pushstring(L, err); | 232 | lua_pushstring(L, err); |
| 233 | return 2; | ||
| 234 | } | ||
| 235 | lua_pushnumber(L, 1); | ||
| 297 | return 1; | 236 | return 1; |
| 298 | } | 237 | } |
| 299 | 238 | ||
| 239 | /*=========================================================================*\ | ||
| 240 | * Library functions | ||
| 241 | \*=========================================================================*/ | ||
| 242 | /*-------------------------------------------------------------------------*\ | ||
| 243 | * Creates a master udp object | ||
| 244 | \*-------------------------------------------------------------------------*/ | ||
| 245 | int udp_global_create(lua_State *L) | ||
| 246 | { | ||
| 247 | /* allocate udp object */ | ||
| 248 | p_udp udp = (p_udp) lua_newuserdata(L, sizeof(t_udp)); | ||
| 249 | /* set its type as master object */ | ||
| 250 | aux_setclass(L, "udp{unconnected}", -1); | ||
| 251 | /* try to allocate a system socket */ | ||
| 252 | const char *err = inet_trycreate(&udp->sock, SOCK_DGRAM); | ||
| 253 | if (err) { | ||
| 254 | /* get rid of object on stack and push error */ | ||
| 255 | lua_pop(L, 1); | ||
| 256 | lua_pushnil(L); | ||
| 257 | lua_pushstring(L, err); | ||
| 258 | return 2; | ||
| 259 | } | ||
| 260 | /* initialize timeout management */ | ||
| 261 | tm_init(&udp->tm, -1, -1); | ||
| 262 | return 1; | ||
| 263 | } | ||
| @@ -1,30 +1,19 @@ | |||
| 1 | /*=========================================================================*\ | 1 | #ifndef UDP_H |
| 2 | * UDP class: inherits from Socked and Internet domain classes and provides | 2 | #define UDP_H |
| 3 | * all the functionality for UDP objects. | ||
| 4 | * | ||
| 5 | * RCS ID: $Id$ | ||
| 6 | \*=========================================================================*/ | ||
| 7 | #ifndef UDP_H_ | ||
| 8 | #define UDP_H_ | ||
| 9 | 3 | ||
| 10 | #include "lsinet.h" | 4 | #include <lua.h> |
| 11 | 5 | ||
| 12 | #define UDP_CLASS "luasocket(UDP socket)" | 6 | #include "tm.h" |
| 7 | #include "sock.h" | ||
| 13 | 8 | ||
| 14 | #define UDP_DATAGRAMSIZE 576 | 9 | #define UDP_DATAGRAMSIZE 576 |
| 15 | 10 | ||
| 16 | #define UDP_FIELDS \ | 11 | typedef struct t_udp_ { |
| 17 | INET_FIELDS; \ | 12 | t_sock sock; |
| 18 | int udp_connected | 13 | t_tm tm; |
| 19 | |||
| 20 | typedef struct t_udp_tag { | ||
| 21 | UDP_FIELDS; | ||
| 22 | } t_udp; | 14 | } t_udp; |
| 23 | typedef t_udp *p_udp; | 15 | typedef t_udp *p_udp; |
| 24 | 16 | ||
| 25 | void udp_inherit(lua_State *L, cchar *lsclass); | ||
| 26 | void udp_construct(lua_State *L, p_udp udp); | ||
| 27 | void udp_open(lua_State *L); | 17 | void udp_open(lua_State *L); |
| 28 | p_udp udp_push(lua_State *L); | ||
| 29 | 18 | ||
| 30 | #endif | 19 | #endif |
diff --git a/src/unix.c b/src/usocket.c index 23984b0..b4b8d5a 100644 --- a/src/unix.c +++ b/src/usocket.c | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | /*=========================================================================*\ | 1 | /*=========================================================================*\ |
| 2 | * Network compatibilization module: Unix version | 2 | * Socket compatibilization module for Unix |
| 3 | * | 3 | * |
| 4 | * RCS ID: $Id$ | 4 | * RCS ID: $Id$ |
| 5 | \*=========================================================================*/ | 5 | \*=========================================================================*/ |
| @@ -7,20 +7,20 @@ | |||
| 7 | #include <lauxlib.h> | 7 | #include <lauxlib.h> |
| 8 | #include <string.h> | 8 | #include <string.h> |
| 9 | 9 | ||
| 10 | #include "lscompat.h" | 10 | #include "sock.h" |
| 11 | 11 | ||
| 12 | /*=========================================================================*\ | 12 | /*=========================================================================*\ |
| 13 | * Internal function prototypes | 13 | * Internal function prototypes |
| 14 | \*=========================================================================*/ | 14 | \*=========================================================================*/ |
| 15 | static cchar *try_setoption(lua_State *L, COMPAT_FD sock); | 15 | static const char *try_setoption(lua_State *L, p_sock ps); |
| 16 | static cchar *try_setbooloption(lua_State *L, COMPAT_FD sock, int name); | 16 | static const char *try_setbooloption(lua_State *L, p_sock ps, int name); |
| 17 | 17 | ||
| 18 | /*=========================================================================*\ | 18 | /*=========================================================================*\ |
| 19 | * Exported functions. | 19 | * Exported functions. |
| 20 | \*=========================================================================*/ | 20 | \*=========================================================================*/ |
| 21 | int compat_open(lua_State *L) | 21 | int sock_open(lua_State *L) |
| 22 | { | 22 | { |
| 23 | /* Instals a handler to ignore sigpipe. */ | 23 | /* instals a handler to ignore sigpipe. */ |
| 24 | struct sigaction new; | 24 | struct sigaction new; |
| 25 | memset(&new, 0, sizeof(new)); | 25 | memset(&new, 0, sizeof(new)); |
| 26 | new.sa_handler = SIG_IGN; | 26 | new.sa_handler = SIG_IGN; |
| @@ -28,143 +28,178 @@ int compat_open(lua_State *L) | |||
| 28 | return 1; | 28 | return 1; |
| 29 | } | 29 | } |
| 30 | 30 | ||
| 31 | COMPAT_FD compat_accept(COMPAT_FD s, struct sockaddr *addr, | 31 | void sock_destroy(p_sock ps) |
| 32 | size_t *len, int deadline) | ||
| 33 | { | 32 | { |
| 33 | close(*ps); | ||
| 34 | } | ||
| 35 | |||
| 36 | const char *sock_create(p_sock ps, int domain, int type, int protocol) | ||
| 37 | { | ||
| 38 | t_sock sock = socket(domain, type, protocol); | ||
| 39 | if (sock == SOCK_INVALID) return sock_createstrerror(); | ||
| 40 | *ps = sock; | ||
| 41 | sock_setnonblocking(ps); | ||
| 42 | sock_setreuseaddr(ps); | ||
| 43 | return NULL; | ||
| 44 | } | ||
| 45 | |||
| 46 | const char *sock_connect(p_sock ps, SA *addr, size_t addr_len) | ||
| 47 | { | ||
| 48 | if (connect(*ps, addr, addr_len) < 0) return sock_connectstrerror(); | ||
| 49 | else return NULL; | ||
| 50 | } | ||
| 51 | |||
| 52 | const char *sock_bind(p_sock ps, SA *addr, size_t addr_len) | ||
| 53 | { | ||
| 54 | if (bind(*ps, addr, addr_len) < 0) return sock_bindstrerror(); | ||
| 55 | else return NULL; | ||
| 56 | } | ||
| 57 | |||
| 58 | void sock_listen(p_sock ps, int backlog) | ||
| 59 | { | ||
| 60 | listen(*ps, backlog); | ||
| 61 | } | ||
| 62 | |||
| 63 | void sock_accept(p_sock ps, p_sock pa, SA *addr, size_t *addr_len, int timeout) | ||
| 64 | { | ||
| 65 | t_sock sock = *ps; | ||
| 34 | struct timeval tv; | 66 | struct timeval tv; |
| 35 | fd_set fds; | 67 | fd_set fds; |
| 36 | tv.tv_sec = deadline / 1000; | 68 | tv.tv_sec = timeout / 1000; |
| 37 | tv.tv_usec = (deadline % 1000) * 1000; | 69 | tv.tv_usec = (timeout % 1000) * 1000; |
| 38 | FD_ZERO(&fds); | 70 | FD_ZERO(&fds); |
| 39 | FD_SET(s, &fds); | 71 | FD_SET(sock, &fds); |
| 40 | select(s+1, &fds, NULL, NULL, deadline >= 0 ? &tv : NULL); | 72 | select(sock+1, &fds, NULL, NULL, timeout >= 0 ? &tv : NULL); |
| 41 | return accept(s, addr, len); | 73 | *pa = accept(sock, addr, addr_len); |
| 42 | } | 74 | } |
| 43 | 75 | ||
| 44 | int compat_send(COMPAT_FD c, cchar *data, size_t count, size_t *sent, | 76 | int sock_send(p_sock ps, const char *data, size_t count, size_t *sent, |
| 45 | int deadline) | 77 | int timeout) |
| 46 | { | 78 | { |
| 79 | t_sock sock = *ps; | ||
| 47 | struct timeval tv; | 80 | struct timeval tv; |
| 48 | fd_set fds; | 81 | fd_set fds; |
| 49 | ssize_t put = 0; | 82 | ssize_t put = 0; |
| 50 | int err; | 83 | int err; |
| 51 | int ret; | 84 | int ret; |
| 52 | tv.tv_sec = deadline / 1000; | 85 | tv.tv_sec = timeout / 1000; |
| 53 | tv.tv_usec = (deadline % 1000) * 1000; | 86 | tv.tv_usec = (timeout % 1000) * 1000; |
| 54 | FD_ZERO(&fds); | 87 | FD_ZERO(&fds); |
| 55 | FD_SET(c, &fds); | 88 | FD_SET(sock, &fds); |
| 56 | ret = select(c+1, NULL, &fds, NULL, deadline >= 0 ? &tv : NULL); | 89 | ret = select(sock+1, NULL, &fds, NULL, timeout >= 0 ? &tv : NULL); |
| 57 | if (ret > 0) { | 90 | if (ret > 0) { |
| 58 | put = write(c, data, count); | 91 | put = write(sock, data, count); |
| 59 | if (put <= 0) { | 92 | if (put <= 0) { |
| 60 | err = PRIV_CLOSED; | 93 | err = IO_CLOSED; |
| 61 | #ifdef __CYGWIN__ | 94 | #ifdef __CYGWIN__ |
| 62 | /* this is for CYGWIN, which is like Unix but has Win32 bugs */ | 95 | /* this is for CYGWIN, which is like Unix but has Win32 bugs */ |
| 63 | if (errno == EWOULDBLOCK) err = PRIV_DONE; | 96 | if (errno == EWOULDBLOCK) err = IO_DONE; |
| 64 | #endif | 97 | #endif |
| 65 | *sent = 0; | 98 | *sent = 0; |
| 66 | } else { | 99 | } else { |
| 67 | *sent = put; | 100 | *sent = put; |
| 68 | err = PRIV_DONE; | 101 | err = IO_DONE; |
| 69 | } | 102 | } |
| 70 | return err; | 103 | return err; |
| 71 | } else { | 104 | } else { |
| 72 | *sent = 0; | 105 | *sent = 0; |
| 73 | return PRIV_TIMEOUT; | 106 | return IO_TIMEOUT; |
| 74 | } | 107 | } |
| 75 | } | 108 | } |
| 76 | 109 | ||
| 77 | int compat_sendto(COMPAT_FD c, cchar *data, size_t count, size_t *sent, | 110 | int sock_sendto(p_sock ps, const char *data, size_t count, size_t *sent, |
| 78 | int deadline, SA *addr, size_t len) | 111 | SA *addr, size_t addr_len, int timeout) |
| 79 | { | 112 | { |
| 113 | t_sock sock = *ps; | ||
| 80 | struct timeval tv; | 114 | struct timeval tv; |
| 81 | fd_set fds; | 115 | fd_set fds; |
| 82 | ssize_t put = 0; | 116 | ssize_t put = 0; |
| 83 | int err; | 117 | int err; |
| 84 | int ret; | 118 | int ret; |
| 85 | tv.tv_sec = deadline / 1000; | 119 | tv.tv_sec = timeout / 1000; |
| 86 | tv.tv_usec = (deadline % 1000) * 1000; | 120 | tv.tv_usec = (timeout % 1000) * 1000; |
| 87 | FD_ZERO(&fds); | 121 | FD_ZERO(&fds); |
| 88 | FD_SET(c, &fds); | 122 | FD_SET(sock, &fds); |
| 89 | ret = select(c+1, NULL, &fds, NULL, deadline >= 0 ? &tv : NULL); | 123 | ret = select(sock+1, NULL, &fds, NULL, timeout >= 0 ? &tv : NULL); |
| 90 | if (ret > 0) { | 124 | if (ret > 0) { |
| 91 | put = sendto(c, data, count, 0, addr, len); | 125 | put = sendto(sock, data, count, 0, addr, addr_len); |
| 92 | if (put <= 0) { | 126 | if (put <= 0) { |
| 93 | err = PRIV_CLOSED; | 127 | err = IO_CLOSED; |
| 94 | #ifdef __CYGWIN__ | 128 | #ifdef __CYGWIN__ |
| 95 | /* this is for CYGWIN, which is like Unix but has Win32 bugs */ | 129 | /* this is for CYGWIN, which is like Unix but has Win32 bugs */ |
| 96 | if (sent < 0 && errno == EWOULDBLOCK) err = PRIV_DONE; | 130 | if (sent < 0 && errno == EWOULDBLOCK) err = IO_DONE; |
| 97 | #endif | 131 | #endif |
| 98 | *sent = 0; | 132 | *sent = 0; |
| 99 | } else { | 133 | } else { |
| 100 | *sent = put; | 134 | *sent = put; |
| 101 | err = PRIV_DONE; | 135 | err = IO_DONE; |
| 102 | } | 136 | } |
| 103 | return err; | 137 | return err; |
| 104 | } else { | 138 | } else { |
| 105 | *sent = 0; | 139 | *sent = 0; |
| 106 | return PRIV_TIMEOUT; | 140 | return IO_TIMEOUT; |
| 107 | } | 141 | } |
| 108 | } | 142 | } |
| 109 | 143 | ||
| 110 | int compat_recv(COMPAT_FD c, char *data, size_t count, size_t *got, | 144 | int sock_recv(p_sock ps, char *data, size_t count, size_t *got, int timeout) |
| 111 | int deadline) | ||
| 112 | { | 145 | { |
| 146 | t_sock sock = *ps; | ||
| 113 | struct timeval tv; | 147 | struct timeval tv; |
| 114 | fd_set fds; | 148 | fd_set fds; |
| 115 | int ret; | 149 | int ret; |
| 116 | ssize_t taken = 0; | 150 | ssize_t taken = 0; |
| 117 | tv.tv_sec = deadline / 1000; | 151 | tv.tv_sec = timeout / 1000; |
| 118 | tv.tv_usec = (deadline % 1000) * 1000; | 152 | tv.tv_usec = (timeout % 1000) * 1000; |
| 119 | FD_ZERO(&fds); | 153 | FD_ZERO(&fds); |
| 120 | FD_SET(c, &fds); | 154 | FD_SET(sock, &fds); |
| 121 | ret = select(c+1, &fds, NULL, NULL, deadline >= 0 ? &tv : NULL); | 155 | ret = select(sock+1, &fds, NULL, NULL, timeout >= 0 ? &tv : NULL); |
| 122 | if (ret > 0) { | 156 | if (ret > 0) { |
| 123 | taken = read(c, data, count); | 157 | taken = read(sock, data, count); |
| 124 | if (taken <= 0) { | 158 | if (taken <= 0) { |
| 125 | *got = 0; | 159 | *got = 0; |
| 126 | return PRIV_CLOSED; | 160 | return IO_CLOSED; |
| 127 | } else { | 161 | } else { |
| 128 | *got = taken; | 162 | *got = taken; |
| 129 | return PRIV_DONE; | 163 | return IO_DONE; |
| 130 | } | 164 | } |
| 131 | } else { | 165 | } else { |
| 132 | *got = 0; | 166 | *got = 0; |
| 133 | return PRIV_TIMEOUT; | 167 | return IO_TIMEOUT; |
| 134 | } | 168 | } |
| 135 | } | 169 | } |
| 136 | 170 | ||
| 137 | int compat_recvfrom(COMPAT_FD c, char *data, size_t count, size_t *got, | 171 | int sock_recvfrom(p_sock ps, char *data, size_t count, size_t *got, |
| 138 | int deadline, SA *addr, size_t *len) | 172 | SA *addr, size_t *addr_len, int timeout) |
| 139 | { | 173 | { |
| 174 | t_sock sock = *ps; | ||
| 140 | struct timeval tv; | 175 | struct timeval tv; |
| 141 | fd_set fds; | 176 | fd_set fds; |
| 142 | int ret; | 177 | int ret; |
| 143 | ssize_t taken = 0; | 178 | ssize_t taken = 0; |
| 144 | tv.tv_sec = deadline / 1000; | 179 | tv.tv_sec = timeout / 1000; |
| 145 | tv.tv_usec = (deadline % 1000) * 1000; | 180 | tv.tv_usec = (timeout % 1000) * 1000; |
| 146 | FD_ZERO(&fds); | 181 | FD_ZERO(&fds); |
| 147 | FD_SET(c, &fds); | 182 | FD_SET(sock, &fds); |
| 148 | ret = select(c+1, &fds, NULL, NULL, deadline >= 0 ? &tv : NULL); | 183 | ret = select(sock+1, &fds, NULL, NULL, timeout >= 0 ? &tv : NULL); |
| 149 | if (ret > 0) { | 184 | if (ret > 0) { |
| 150 | taken = recvfrom(c, data, count, 0, addr, len); | 185 | taken = recvfrom(sock, data, count, 0, addr, addr_len); |
| 151 | if (taken <= 0) { | 186 | if (taken <= 0) { |
| 152 | *got = 0; | 187 | *got = 0; |
| 153 | return PRIV_CLOSED; | 188 | return IO_CLOSED; |
| 154 | } else { | 189 | } else { |
| 155 | *got = taken; | 190 | *got = taken; |
| 156 | return PRIV_DONE; | 191 | return IO_DONE; |
| 157 | } | 192 | } |
| 158 | } else { | 193 | } else { |
| 159 | *got = 0; | 194 | *got = 0; |
| 160 | return PRIV_TIMEOUT; | 195 | return IO_TIMEOUT; |
| 161 | } | 196 | } |
| 162 | } | 197 | } |
| 163 | 198 | ||
| 164 | /*-------------------------------------------------------------------------*\ | 199 | /*-------------------------------------------------------------------------*\ |
| 165 | * Returns a string describing the last host manipulation error. | 200 | * Returns a string describing the last host manipulation error. |
| 166 | \*-------------------------------------------------------------------------*/ | 201 | \*-------------------------------------------------------------------------*/ |
| 167 | const char *compat_hoststrerror(void) | 202 | const char *sock_hoststrerror(void) |
| 168 | { | 203 | { |
| 169 | switch (h_errno) { | 204 | switch (h_errno) { |
| 170 | case HOST_NOT_FOUND: return "host not found"; | 205 | case HOST_NOT_FOUND: return "host not found"; |
| @@ -178,7 +213,7 @@ const char *compat_hoststrerror(void) | |||
| 178 | /*-------------------------------------------------------------------------*\ | 213 | /*-------------------------------------------------------------------------*\ |
| 179 | * Returns a string describing the last socket manipulation error. | 214 | * Returns a string describing the last socket manipulation error. |
| 180 | \*-------------------------------------------------------------------------*/ | 215 | \*-------------------------------------------------------------------------*/ |
| 181 | const char *compat_socketstrerror(void) | 216 | const char *sock_createstrerror(void) |
| 182 | { | 217 | { |
| 183 | switch (errno) { | 218 | switch (errno) { |
| 184 | case EACCES: return "access denied"; | 219 | case EACCES: return "access denied"; |
| @@ -192,7 +227,7 @@ const char *compat_socketstrerror(void) | |||
| 192 | /*-------------------------------------------------------------------------*\ | 227 | /*-------------------------------------------------------------------------*\ |
| 193 | * Returns a string describing the last bind command error. | 228 | * Returns a string describing the last bind command error. |
| 194 | \*-------------------------------------------------------------------------*/ | 229 | \*-------------------------------------------------------------------------*/ |
| 195 | const char *compat_bindstrerror(void) | 230 | const char *sock_bindstrerror(void) |
| 196 | { | 231 | { |
| 197 | switch (errno) { | 232 | switch (errno) { |
| 198 | case EBADF: return "invalid descriptor"; | 233 | case EBADF: return "invalid descriptor"; |
| @@ -209,7 +244,7 @@ const char *compat_bindstrerror(void) | |||
| 209 | /*-------------------------------------------------------------------------*\ | 244 | /*-------------------------------------------------------------------------*\ |
| 210 | * Returns a string describing the last connect error. | 245 | * Returns a string describing the last connect error. |
| 211 | \*-------------------------------------------------------------------------*/ | 246 | \*-------------------------------------------------------------------------*/ |
| 212 | const char *compat_connectstrerror(void) | 247 | const char *sock_connectstrerror(void) |
| 213 | { | 248 | { |
| 214 | switch (errno) { | 249 | switch (errno) { |
| 215 | case EBADF: return "invalid descriptor"; | 250 | case EBADF: return "invalid descriptor"; |
| @@ -229,40 +264,30 @@ const char *compat_connectstrerror(void) | |||
| 229 | * Input | 264 | * Input |
| 230 | * sock: socket descriptor | 265 | * sock: socket descriptor |
| 231 | \*-------------------------------------------------------------------------*/ | 266 | \*-------------------------------------------------------------------------*/ |
| 232 | void compat_setreuseaddr(COMPAT_FD sock) | 267 | void sock_setreuseaddr(p_sock ps) |
| 233 | { | 268 | { |
| 234 | int val = 1; | 269 | int val = 1; |
| 235 | setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *)&val, sizeof(val)); | 270 | setsockopt(*ps, SOL_SOCKET, SO_REUSEADDR, (char *)&val, sizeof(val)); |
| 236 | } | ||
| 237 | |||
| 238 | COMPAT_FD compat_socket(int domain, int type, int protocol) | ||
| 239 | { | ||
| 240 | COMPAT_FD sock = socket(domain, type, protocol); | ||
| 241 | if (sock != COMPAT_INVALIDFD) { | ||
| 242 | compat_setnonblocking(sock); | ||
| 243 | compat_setreuseaddr(sock); | ||
| 244 | } | ||
| 245 | return sock; | ||
| 246 | } | 271 | } |
| 247 | 272 | ||
| 248 | /*-------------------------------------------------------------------------*\ | 273 | /*-------------------------------------------------------------------------*\ |
| 249 | * Put socket into blocking mode. | 274 | * Put socket into blocking mode. |
| 250 | \*-------------------------------------------------------------------------*/ | 275 | \*-------------------------------------------------------------------------*/ |
| 251 | void compat_setblocking(COMPAT_FD sock) | 276 | void sock_setblocking(p_sock ps) |
| 252 | { | 277 | { |
| 253 | int flags = fcntl(sock, F_GETFL, 0); | 278 | int flags = fcntl(*ps, F_GETFL, 0); |
| 254 | flags &= (~(O_NONBLOCK)); | 279 | flags &= (~(O_NONBLOCK)); |
| 255 | fcntl(sock, F_SETFL, flags); | 280 | fcntl(*ps, F_SETFL, flags); |
| 256 | } | 281 | } |
| 257 | 282 | ||
| 258 | /*-------------------------------------------------------------------------*\ | 283 | /*-------------------------------------------------------------------------*\ |
| 259 | * Put socket into non-blocking mode. | 284 | * Put socket into non-blocking mode. |
| 260 | \*-------------------------------------------------------------------------*/ | 285 | \*-------------------------------------------------------------------------*/ |
| 261 | void compat_setnonblocking(COMPAT_FD sock) | 286 | void sock_setnonblocking(p_sock ps) |
| 262 | { | 287 | { |
| 263 | int flags = fcntl(sock, F_GETFL, 0); | 288 | int flags = fcntl(*ps, F_GETFL, 0); |
| 264 | flags |= O_NONBLOCK; | 289 | flags |= O_NONBLOCK; |
| 265 | fcntl(sock, F_SETFL, flags); | 290 | fcntl(*ps, F_SETFL, flags); |
| 266 | } | 291 | } |
| 267 | 292 | ||
| 268 | /*-------------------------------------------------------------------------*\ | 293 | /*-------------------------------------------------------------------------*\ |
| @@ -273,54 +298,50 @@ void compat_setnonblocking(COMPAT_FD sock) | |||
| 273 | * Returns | 298 | * Returns |
| 274 | * NULL if successfull, error message on error | 299 | * NULL if successfull, error message on error |
| 275 | \*-------------------------------------------------------------------------*/ | 300 | \*-------------------------------------------------------------------------*/ |
| 276 | cchar *compat_trysetoptions(lua_State *L, COMPAT_FD sock) | 301 | const char *sock_trysetoptions(lua_State *L, p_sock ps) |
| 277 | { | 302 | { |
| 278 | if (!lua_istable(L, 1)) luaL_argerror(L, 1, "invalid options table"); | 303 | if (!lua_istable(L, 1)) luaL_argerror(L, 1, "invalid options table"); |
| 279 | lua_pushnil(L); | 304 | lua_pushnil(L); |
| 280 | while (lua_next(L, 1)) { | 305 | while (lua_next(L, 1)) { |
| 281 | cchar *err = try_setoption(L, sock); | 306 | const char *err = try_setoption(L, ps); |
| 282 | lua_pop(L, 1); | 307 | lua_pop(L, 1); |
| 283 | if (err) return err; | 308 | if (err) return err; |
| 284 | } | 309 | } |
| 285 | return NULL; | 310 | return NULL; |
| 286 | } | 311 | } |
| 287 | 312 | ||
| 288 | /*=========================================================================*\ | ||
| 289 | * Internal functions. | ||
| 290 | \*=========================================================================*/ | ||
| 291 | static cchar *try_setbooloption(lua_State *L, COMPAT_FD sock, int name) | ||
| 292 | { | ||
| 293 | int bool, res; | ||
| 294 | if (!lua_isnumber(L, -1)) luaL_error(L, "invalid option value"); | ||
| 295 | bool = (int) lua_tonumber(L, -1); | ||
| 296 | res = setsockopt(sock, SOL_SOCKET, name, (char *) &bool, sizeof(bool)); | ||
| 297 | if (res < 0) return "error setting option"; | ||
| 298 | else return NULL; | ||
| 299 | } | ||
| 300 | |||
| 301 | |||
| 302 | /*-------------------------------------------------------------------------*\ | 313 | /*-------------------------------------------------------------------------*\ |
| 303 | * Set socket options from a table on top of Lua stack. | 314 | * Set socket options from a table on top of Lua stack. |
| 304 | * Supports SO_KEEPALIVE, SO_DONTROUTE, SO_BROADCAST, and SO_LINGER options. | 315 | * Supports SO_KEEPALIVE, SO_DONTROUTE, and SO_BROADCAST options. |
| 305 | * Input | 316 | * Input |
| 306 | * L: Lua state to use | 317 | * sock: socket |
| 307 | * sock: socket descriptor | ||
| 308 | * Returns | 318 | * Returns |
| 309 | * 1 if successful, 0 otherwise | 319 | * 1 if successful, 0 otherwise |
| 310 | \*-------------------------------------------------------------------------*/ | 320 | \*-------------------------------------------------------------------------*/ |
| 311 | static cchar *try_setoption(lua_State *L, COMPAT_FD sock) | 321 | static const char *try_setoption(lua_State *L, p_sock ps) |
| 312 | { | 322 | { |
| 313 | static cchar *options[] = { | 323 | static const char *options[] = { |
| 314 | "SO_KEEPALIVE", "SO_DONTROUTE", "SO_BROADCAST", "SO_LINGER", NULL | 324 | "SO_KEEPALIVE", "SO_DONTROUTE", "SO_BROADCAST", NULL |
| 315 | }; | 325 | }; |
| 316 | cchar *option = lua_tostring(L, -2); | 326 | const char *option = lua_tostring(L, -2); |
| 317 | if (!lua_isstring(L, -2)) return "invalid option"; | 327 | if (!lua_isstring(L, -2)) return "invalid option"; |
| 318 | switch (luaL_findstring(option, options)) { | 328 | switch (luaL_findstring(option, options)) { |
| 319 | case 0: return try_setbooloption(L, sock, SO_KEEPALIVE); | 329 | case 0: return try_setbooloption(L, ps, SO_KEEPALIVE); |
| 320 | case 1: return try_setbooloption(L, sock, SO_DONTROUTE); | 330 | case 1: return try_setbooloption(L, ps, SO_DONTROUTE); |
| 321 | case 2: return try_setbooloption(L, sock, SO_BROADCAST); | 331 | case 2: return try_setbooloption(L, ps, SO_BROADCAST); |
| 322 | case 3: return "SO_LINGER is deprecated"; | ||
| 323 | default: return "unsupported option"; | 332 | default: return "unsupported option"; |
| 324 | } | 333 | } |
| 325 | } | 334 | } |
| 326 | 335 | ||
| 336 | /*=========================================================================*\ | ||
| 337 | * Internal functions. | ||
| 338 | \*=========================================================================*/ | ||
| 339 | static const char *try_setbooloption(lua_State *L, p_sock ps, int name) | ||
| 340 | { | ||
| 341 | int bool, res; | ||
| 342 | if (!lua_isnumber(L, -1)) luaL_error(L, "invalid option value"); | ||
| 343 | bool = (int) lua_tonumber(L, -1); | ||
| 344 | res = setsockopt(*ps, SOL_SOCKET, name, (char *) &bool, sizeof(bool)); | ||
| 345 | if (res < 0) return "error setting option"; | ||
| 346 | else return NULL; | ||
| 347 | } | ||
diff --git a/src/unix.h b/src/usocket.h index 863e478..f124bce 100644 --- a/src/unix.h +++ b/src/usocket.h | |||
| @@ -1,10 +1,10 @@ | |||
| 1 | /*=========================================================================*\ | 1 | /*=========================================================================*\ |
| 2 | * Network compatibilization module: Unix version | 2 | * Socket compatibilization module for Unix |
| 3 | * | 3 | * |
| 4 | * RCS ID: $Id$ | 4 | * RCS ID: $Id$ |
| 5 | \*=========================================================================*/ | 5 | \*=========================================================================*/ |
| 6 | #ifndef UNIX_H_ | 6 | #ifndef UNIX_H |
| 7 | #define UNIX_H_ | 7 | #define UNIX_H |
| 8 | 8 | ||
| 9 | /*=========================================================================*\ | 9 | /*=========================================================================*\ |
| 10 | * BSD include files | 10 | * BSD include files |
| @@ -31,13 +31,9 @@ | |||
| 31 | #include <netinet/in.h> | 31 | #include <netinet/in.h> |
| 32 | #include <arpa/inet.h> | 32 | #include <arpa/inet.h> |
| 33 | 33 | ||
| 34 | #define COMPAT_FD int | 34 | typedef int t_sock; |
| 35 | #define COMPAT_INVALIDFD (-1) | 35 | typedef t_sock *p_sock; |
| 36 | 36 | ||
| 37 | #define compat_bind bind | 37 | #define SOCK_INVALID (-1) |
| 38 | #define compat_connect connect | ||
| 39 | #define compat_listen listen | ||
| 40 | #define compat_close close | ||
| 41 | #define compat_select select | ||
| 42 | 38 | ||
| 43 | #endif /* UNIX_H_ */ | 39 | #endif /* UNIX_H */ |
