aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorDiego Nehab <diego@tecgraf.puc-rio.br>2003-05-25 01:54:13 +0000
committerDiego Nehab <diego@tecgraf.puc-rio.br>2003-05-25 01:54:13 +0000
commit0f6c8d50a99997ac7829864b1c93362b50f1bbf3 (patch)
treed0cefe3a05484e65b7b7e79d8cae4a1d2e6d19fb /src
parentc1ef3e7103cc652d2004ef1ddc9409b946207f33 (diff)
downloadluasocket-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.c113
-rw-r--r--src/auxiliar.h26
-rw-r--r--src/buffer.c275
-rw-r--r--src/buffer.h26
-rw-r--r--src/ftp.lua57
-rw-r--r--src/http.lua35
-rw-r--r--src/inet.c170
-rw-r--r--src/inet.h36
-rw-r--r--src/io.c8
-rw-r--r--src/io.h34
-rw-r--r--src/luasocket.c64
-rw-r--r--src/luasocket.h8
-rw-r--r--src/mbox.lua20
-rw-r--r--src/smtp.lua39
-rw-r--r--src/tcp.c222
-rw-r--r--src/tcp.h20
-rw-r--r--src/timeout.c116
-rw-r--r--src/timeout.h32
-rw-r--r--src/udp.c404
-rw-r--r--src/udp.h27
-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\*=========================================================================*/
11static 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\*-------------------------------------------------------------------------*/
21void 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\*-------------------------------------------------------------------------*/
40void 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\*-------------------------------------------------------------------------*/
54void *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\*-------------------------------------------------------------------------*/
68void *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\*-------------------------------------------------------------------------*/
82void 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\*-------------------------------------------------------------------------*/
95static 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
12void aux_newclass(lua_State *L, const char *name, luaL_reg *func);
13void aux_add2group(lua_State *L, const char *name, const char *group);
14void *aux_checkclass(lua_State *L, const char *name, int objidx);
15void *aux_checkgroup(lua_State *L, const char *group, int objidx);
16void 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\*=========================================================================*/
17static int sendraw(lua_State *L, p_buf buf, cchar *data, size_t len,
18 size_t *done);
19static int recvraw(lua_State *L, p_buf buf, size_t wanted); 16static int recvraw(lua_State *L, p_buf buf, size_t wanted);
20static int recvdosline(lua_State *L, p_buf buf); 17static int recvline(lua_State *L, p_buf buf);
21static int recvunixline(lua_State *L, p_buf buf);
22static int recvall(lua_State *L, p_buf buf); 18static int recvall(lua_State *L, p_buf buf);
23 19static int buf_get(p_buf buf, const char **data, size_t *count);
24static int buf_contents(lua_State *L, p_buf buf, cchar **data, size_t *len); 20static void buf_skip(p_buf buf, size_t count);
25static void buf_skip(lua_State *L, p_buf buf, size_t len); 21static 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\*-------------------------------------------------------------------------*/
44void buf_init(lua_State *L, p_buf buf, p_base base) 37void 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\*-------------------------------------------------------------------------*/
62int buf_send(lua_State *L, p_buf buf) 47int 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\*-------------------------------------------------------------------------*/
104int buf_receive(lua_State *L, p_buf buf) 73int 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\*-------------------------------------------------------------------------*/
158int buf_isempty(lua_State *L, p_buf buf) 121int 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\*-------------------------------------------------------------------------*/
178static int sendraw(lua_State *L, p_buf buf, cchar *data, size_t len, 132static 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\*-------------------------------------------------------------------------*/
201static int recvraw(lua_State *L, p_buf buf, size_t wanted) 150static
151int 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\*-------------------------------------------------------------------------*/
226static int recvall(lua_State *L, p_buf buf) 172static
173int 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\*-------------------------------------------------------------------------*/
249static int recvdosline(lua_State *L, p_buf buf) 192static
193int 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\*-------------------------------------------------------------------------*/
281static 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\*-------------------------------------------------------------------------*/
310static void buf_skip(lua_State *L, p_buf buf, size_t len) 220static
221void 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\*-------------------------------------------------------------------------*/
327static int buf_contents(lua_State *L, p_buf buf, cchar **data, size_t *len) 232static
233int 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\*-------------------------------------------------------------------------*/
18typedef struct t_buf_tag { 19typedef 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;
23typedef t_buf *p_buf; 25typedef t_buf *p_buf;
24 26
@@ -26,9 +28,9 @@ typedef t_buf *p_buf;
26* Exported functions 28* Exported functions
27\*-------------------------------------------------------------------------*/ 29\*-------------------------------------------------------------------------*/
28void buf_open(lua_State *L); 30void buf_open(lua_State *L);
29void buf_init(lua_State *L, p_buf buf, p_base base); 31void buf_init(p_buf buf, p_io io, p_tm tm);
30int buf_send(lua_State *L, p_buf buf); 32int buf_meth_send(lua_State *L, p_buf buf);
31int buf_receive(lua_State *L, p_buf buf); 33int buf_meth_receive(lua_State *L, p_buf buf);
32int buf_isempty(lua_State *L, p_buf buf); 34int 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
9local Public, Private = {}, {} 9local Public, Private = {}, {}
10socket.ftp = Public 10local socket = _G[LUASOCKET_LIBNAME] -- get LuaSocket namespace
11socket.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"
23Public.BLOCKSIZE = 8192 24Public.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-----------------------------------------------------------------------------
33function Private.try_sendline(sock, line) 34function 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
37end 38end
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-----------------------------------------------------------------------------
47function Private.try_receive(...) 47function 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 51end
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-----------------------------------------------------------------------------
61function Private.try_sendline(sock, line)
62 return Private.try_send(sock, line .. "\r\n")
52end 63end
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-----------------------------------------------------------------------------
309function Private.send_indirect(data, send_cb, chunk, size) 320function 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
9local Public, Private = {}, {} 9local Public, Private = {}, {}
10socket.http = Public 10local socket = _G[LUASOCKET_LIBNAME] -- get LuaSocket namespace
11socket.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-----------------------------------------------------------------------------
32function Private.try_receive(...) 33function 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
40end 37end
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-----------------------------------------------------------------------------
49function Private.try_send(sock, data) 46function 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
53end 50end
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-----------------------------------------------------------------------------
287function Private.send_indirect(data, send_cb, chunk, size) 284function 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
305end 302end
diff --git a/src/inet.c b/src/inet.c
index 341c60e..f20762f 100644
--- a/src/inet.c
+++ b/src/inet.c
@@ -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\*=========================================================================*/
25static int inet_lua_toip(lua_State *L); 17static int inet_global_toip(lua_State *L);
26static int inet_lua_tohostname(lua_State *L); 18static int inet_global_tohostname(lua_State *L);
27static int inet_lua_getpeername(lua_State *L); 19
28static int inet_lua_getsockname(lua_State *L);
29static void inet_pushresolved(lua_State *L, struct hostent *hp); 20static void inet_pushresolved(lua_State *L, struct hostent *hp);
30 21
31#ifdef COMPAT_INETATON 22#ifdef INET_ATON
32static int inet_aton(cchar *cp, struct in_addr *inp); 23static int inet_aton(const char *cp, struct in_addr *inp);
33#endif 24#endif
34 25
26static 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\*-------------------------------------------------------------------------*/
41void inet_open(lua_State *L) 38void 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\*-------------------------------------------------------------------------*/
56void 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\*-------------------------------------------------------------------------*/
73void 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\*-------------------------------------------------------------------------*/
90static int inet_lua_toip(lua_State *L) 55static 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\*-------------------------------------------------------------------------*/
118static int inet_lua_tohostname(lua_State *L) 84static 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\*-------------------------------------------------------------------------*/
147static int inet_lua_getpeername(lua_State *L) 114int 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\*-------------------------------------------------------------------------*/
169static int inet_lua_getsockname(lua_State *L) 135int 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\*-------------------------------------------------------------------------*/
233cchar *inet_tryconnect(p_inet inet, cchar *address, ushort port) 198const 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\*-------------------------------------------------------------------------*/
265cchar *inet_trybind(p_inet inet, cchar *address, ushort port) 235const 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\*-------------------------------------------------------------------------*/
299cchar *inet_trysocket(p_inet inet, int type) 272const 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/*-------------------------------------------------------------------------*\
diff --git a/src/inet.h b/src/inet.h
index 93fcedf..bcefc5b 100644
--- a/src/inet.h
+++ b/src/inet.h
@@ -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\*-------------------------------------------------------------------------*/
24typedef t_sock t_inet;
25typedef t_inet *p_inet;
26 11
27/*-------------------------------------------------------------------------*\ 12/*-------------------------------------------------------------------------*\
28* Exported functions 13* Exported functions
29\*-------------------------------------------------------------------------*/ 14\*-------------------------------------------------------------------------*/
30void inet_open(lua_State *L); 15void inet_open(lua_State *L);
31void inet_construct(lua_State *L, p_inet inet);
32void inet_inherit(lua_State *L, cchar *lsclass);
33 16
34cchar *inet_tryconnect(p_sock sock, cchar *address, ushort); 17const char *inet_tryconnect(p_sock ps, const char *address,
35cchar *inet_trybind(p_sock sock, cchar *address, ushort); 18 unsigned short port);
36cchar *inet_trysocket(p_inet inet, int type); 19const char *inet_trybind(p_sock ps, const char *address,
20 unsigned short port, int backlog);
21const char *inet_trycreate(p_sock ps, int type);
22
23int inet_meth_getpeername(lua_State *L, p_sock ps);
24int 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
3void 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 */
7typedef 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 */
16typedef 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 */
25typedef 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;
30typedef t_io *p_io;
31
32void 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\*-------------------------------------------------------------------------*/
45LUASOCKET_API int lua_socketlibopen(lua_State *L) 40LUASOCKET_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\*-------------------------------------------------------------------------*/
31LUASOCKET_API int lua_socketlibopen(lua_State *L); 31LUASOCKET_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
5function Public.split_message(message_s) 5function 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
25end 25end
26 26
@@ -32,10 +32,10 @@ function Public.parse_header(header_s)
32end 32end
33 33
34function Public.parse_headers(headers_s) 34function 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)
73end 73end
74 74
75function Public.parse(mbox_s) 75function 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
81end 81end
82 82
83function Public.parse_message(message_s) 83function 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
88end 88end
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
9local Public, Private = {}, {} 9local Public, Private = {}, {}
10socket.smtp = Public 10local socket = _G[LUASOCKET_LIBNAME] -- get LuaSocket namespace
11socket.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"
23Public.SERVER = "localhost" 24Public.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-----------------------------------------------------------------------------
33function Private.try_send(sock, data) 34function 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
37end 38end
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-----------------------------------------------------------------------------
47function Private.try_receive(...) 47function 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
52end 51end
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\*=========================================================================*/
20static int tcp_global_create(lua_State *L);
21static int tcp_meth_connect(lua_State *L);
22static int tcp_meth_bind(lua_State *L);
23static int tcp_meth_send(lua_State *L);
24static int tcp_meth_getsockname(lua_State *L);
25static int tcp_meth_getpeername(lua_State *L);
26static int tcp_meth_receive(lua_State *L);
27static int tcp_meth_accept(lua_State *L);
28static int tcp_meth_close(lua_State *L);
29static int tcp_meth_timeout(lua_State *L);
30
31/* tcp object methods */
32static 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 */
48static luaL_reg func[] = {
49 {"tcp", tcp_global_create},
50 {NULL, NULL}
51};
52
53/*-------------------------------------------------------------------------*\
54* Initializes module
55\*-------------------------------------------------------------------------*/
56void 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\*-------------------------------------------------------------------------*/
79static 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
85static 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\*-------------------------------------------------------------------------*/
94static 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
100static 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\*-------------------------------------------------------------------------*/
109static 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\*-------------------------------------------------------------------------*/
118static 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\*-------------------------------------------------------------------------*/
128static 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\*-------------------------------------------------------------------------*/
148static 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\*-------------------------------------------------------------------------*/
170static 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\*-------------------------------------------------------------------------*/
203int 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
10typedef struct t_tcp_ {
11 t_sock sock;
12 t_io io;
13 t_buf buf;
14 t_tm tm;
15} t_tcp;
16typedef t_tcp *p_tcp;
17
18void 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 @@
28static int tm_lua_time(lua_State *L); 29static int tm_lua_time(lua_State *L);
29static int tm_lua_sleep(lua_State *L); 30static int tm_lua_sleep(lua_State *L);
30 31
32static 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\*-------------------------------------------------------------------------*/
41void tm_set(p_tm tm, int tm_block, int tm_return) 44void 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\*-------------------------------------------------------------------------*/
54void tm_get(p_tm tm, int *tm_block, int *tm_return) 53void tm_setblock(p_tm tm, int block)
55{ 54{ tm->block = block; }
56 if (tm_block) *tm_block = tm->tm_block; 55void tm_settotal(p_tm tm, int total)
57 if (tm_return) *tm_return = tm->tm_return; 56{ tm->total = total; }
58} 57int tm_getblock(p_tm tm)
58{ return tm->block; }
59int tm_gettotal(p_tm tm)
60{ return tm->total; }
61int 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\*-------------------------------------------------------------------------*/
68int tm_getremaining(p_tm tm) 71int 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\*-------------------------------------------------------------------------*/
89void tm_markstart(p_tm tm) 92void 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\*-------------------------------------------------------------------------*/
100int 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\*-------------------------------------------------------------------------*/
126void tm_open(lua_State *L) 118void 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\*-------------------------------------------------------------------------*/
129int 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
9typedef 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; 12typedef 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;
15typedef t_tm *p_tm; 17typedef t_tm *p_tm;
16 18
17void tm_set(p_tm tm, int tm_block, int tm_return);
18int tm_getremaining(p_tm tm);
19int tm_getelapsed(p_tm tm);
20int tm_gettime(void);
21void tm_get(p_tm tm, int *tm_block, int *tm_return);
22void tm_markstart(p_tm tm);
23void tm_open(lua_State *L); 19void tm_open(lua_State *L);
20void tm_init(p_tm tm, int block, int total);
21void tm_setblock(p_tm tm, int block);
22void tm_settotal(p_tm tm, int total);
23int tm_getblock(p_tm tm);
24int tm_gettotal(p_tm tm);
25void tm_markstart(p_tm tm);
26int tm_getstart(p_tm tm);
27int tm_get(p_tm tm);
28int tm_gettime(void);
29int tm_meth_timeout(lua_State *L, p_tm tm);
24 30
25#endif 31#endif
diff --git a/src/udp.c b/src/udp.c
index 361816c..1701d1b 100644
--- a/src/udp.c
+++ b/src/udp.c
@@ -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\*=========================================================================*/
29static int udp_lua_send(lua_State *L); 20static int udp_global_create(lua_State *L);
30static int udp_lua_sendto(lua_State *L); 21static int udp_meth_send(lua_State *L);
31static int udp_lua_receive(lua_State *L); 22static int udp_meth_sendto(lua_State *L);
32static int udp_lua_receivefrom(lua_State *L); 23static int udp_meth_receive(lua_State *L);
33static int udp_lua_setpeername(lua_State *L); 24static int udp_meth_receivefrom(lua_State *L);
34static int udp_lua_setsockname(lua_State *L); 25static int udp_meth_getsockname(lua_State *L);
26static int udp_meth_getpeername(lua_State *L);
27static int udp_meth_setsockname(lua_State *L);
28static int udp_meth_setpeername(lua_State *L);
29static int udp_meth_close(lua_State *L);
30static int udp_meth_timeout(lua_State *L);
35 31
36static int udp_global_udp(lua_State *L); 32/* udp object methods */
33static 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
38static struct luaL_reg funcs[] = { 47/* functions in library namespace */
39 {"send", udp_lua_send}, 48static 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\*-------------------------------------------------------------------------*/
53void udp_open(lua_State *L) 56void 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\*-------------------------------------------------------------------------*/
70void 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\*-------------------------------------------------------------------------*/
83void udp_construct(lua_State *L, p_udp udp) 75static 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\*-------------------------------------------------------------------------*/
95p_udp udp_push(lua_State *L) 93static 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\*-------------------------------------------------------------------------*/
114static 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\*-------------------------------------------------------------------------*/
146static int udp_lua_receive(lua_State *L) 120static 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\*-------------------------------------------------------------------------*/
172static int udp_lua_receivefrom(lua_State *L) 139static 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\*-------------------------------------------------------------------------*/
209static int udp_lua_send(lua_State *L) 167static 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); 173static 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\*-------------------------------------------------------------------------*/
235static int udp_lua_sendto(lua_State *L) 182static 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\*-------------------------------------------------------------------------*/
267static int udp_lua_setsockname(lua_State * L) 191static 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 214static 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\*-------------------------------------------------------------------------*/
287static int udp_lua_setpeername(lua_State *L) 224static 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\*-------------------------------------------------------------------------*/
245int 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}
diff --git a/src/udp.h b/src/udp.h
index 928a99f..4ba53e6 100644
--- a/src/udp.h
+++ b/src/udp.h
@@ -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 \ 11typedef struct t_udp_ {
17 INET_FIELDS; \ 12 t_sock sock;
18 int udp_connected 13 t_tm tm;
19
20typedef struct t_udp_tag {
21 UDP_FIELDS;
22} t_udp; 14} t_udp;
23typedef t_udp *p_udp; 15typedef t_udp *p_udp;
24 16
25void udp_inherit(lua_State *L, cchar *lsclass);
26void udp_construct(lua_State *L, p_udp udp);
27void udp_open(lua_State *L); 17void udp_open(lua_State *L);
28p_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\*=========================================================================*/
15static cchar *try_setoption(lua_State *L, COMPAT_FD sock); 15static const char *try_setoption(lua_State *L, p_sock ps);
16static cchar *try_setbooloption(lua_State *L, COMPAT_FD sock, int name); 16static const char *try_setbooloption(lua_State *L, p_sock ps, int name);
17 17
18/*=========================================================================*\ 18/*=========================================================================*\
19* Exported functions. 19* Exported functions.
20\*=========================================================================*/ 20\*=========================================================================*/
21int compat_open(lua_State *L) 21int 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
31COMPAT_FD compat_accept(COMPAT_FD s, struct sockaddr *addr, 31void sock_destroy(p_sock ps)
32 size_t *len, int deadline)
33{ 32{
33 close(*ps);
34}
35
36const 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
46const 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
52const 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
58void sock_listen(p_sock ps, int backlog)
59{
60 listen(*ps, backlog);
61}
62
63void 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
44int compat_send(COMPAT_FD c, cchar *data, size_t count, size_t *sent, 76int 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
77int compat_sendto(COMPAT_FD c, cchar *data, size_t count, size_t *sent, 110int 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
110int compat_recv(COMPAT_FD c, char *data, size_t count, size_t *got, 144int 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
137int compat_recvfrom(COMPAT_FD c, char *data, size_t count, size_t *got, 171int 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\*-------------------------------------------------------------------------*/
167const char *compat_hoststrerror(void) 202const 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\*-------------------------------------------------------------------------*/
181const char *compat_socketstrerror(void) 216const 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\*-------------------------------------------------------------------------*/
195const char *compat_bindstrerror(void) 230const 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\*-------------------------------------------------------------------------*/
212const char *compat_connectstrerror(void) 247const 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\*-------------------------------------------------------------------------*/
232void compat_setreuseaddr(COMPAT_FD sock) 267void 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
238COMPAT_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\*-------------------------------------------------------------------------*/
251void compat_setblocking(COMPAT_FD sock) 276void 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\*-------------------------------------------------------------------------*/
261void compat_setnonblocking(COMPAT_FD sock) 286void 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\*-------------------------------------------------------------------------*/
276cchar *compat_trysetoptions(lua_State *L, COMPAT_FD sock) 301const 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\*=========================================================================*/
291static 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\*-------------------------------------------------------------------------*/
311static cchar *try_setoption(lua_State *L, COMPAT_FD sock) 321static 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\*=========================================================================*/
339static 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 34typedef int t_sock;
35#define COMPAT_INVALIDFD (-1) 35typedef 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 */