diff options
author | Diego Nehab <diego@tecgraf.puc-rio.br> | 2000-06-02 17:55:14 +0000 |
---|---|---|
committer | Diego Nehab <diego@tecgraf.puc-rio.br> | 2000-06-02 17:55:14 +0000 |
commit | d455d1707fbdd03592f78a5c5476e90822221359 (patch) | |
tree | a90731352375798ad94dd2031a1dfb5e2b399ac2 /src | |
download | luasocket-d455d1707fbdd03592f78a5c5476e90822221359.tar.gz luasocket-d455d1707fbdd03592f78a5c5476e90822221359.tar.bz2 luasocket-d455d1707fbdd03592f78a5c5476e90822221359.zip |
Initial revision
Diffstat (limited to 'src')
-rw-r--r-- | src/luasocket.c | 1357 |
1 files changed, 1357 insertions, 0 deletions
diff --git a/src/luasocket.c b/src/luasocket.c new file mode 100644 index 0000000..027afa3 --- /dev/null +++ b/src/luasocket.c | |||
@@ -0,0 +1,1357 @@ | |||
1 | /*=========================================================================*\ | ||
2 | * TCP/IP bind for the Lua language | ||
3 | * Diego Nehab | ||
4 | * 26/11/1999 | ||
5 | * | ||
6 | * Module: LSOCK.C | ||
7 | * | ||
8 | * This module is part of an effort to make the most important features | ||
9 | * of the TCP/IP protocol available for Lua scripts. | ||
10 | * The main intent of the project was the distribution with the CGILua | ||
11 | * toolkit, in which is is used to implement the SMTP client functions. | ||
12 | * The Lua interface to TCP/IP follows the BSD TCP/IP API closely, | ||
13 | * trying to simplify all tasks involved in setting up a client connection | ||
14 | * and simple server connections. | ||
15 | * The provided IO routines, send and receive, follow the Lua style, being | ||
16 | * very similar to the read and write functions found in that language. | ||
17 | * The module implements both a BSD bind and a Winsock2 bind, and has | ||
18 | * been tested on several Unix flavors, as well as Windows 98 and NT. | ||
19 | \*=========================================================================*/ | ||
20 | |||
21 | /*=========================================================================*\ | ||
22 | * Common include files | ||
23 | \*=========================================================================*/ | ||
24 | #include <stdio.h> | ||
25 | #include <stdlib.h> | ||
26 | #include <errno.h> | ||
27 | #include <string.h> | ||
28 | #include <signal.h> | ||
29 | |||
30 | #include <assert.h> | ||
31 | |||
32 | #define LUA_REENTRANT | ||
33 | |||
34 | #include <lua.h> | ||
35 | #include <lauxlib.h> | ||
36 | #include <lualib.h> | ||
37 | |||
38 | #include "lsock.h" | ||
39 | |||
40 | /*=========================================================================*\ | ||
41 | * WinSock2 include files | ||
42 | \*=========================================================================*/ | ||
43 | #ifdef WIN32 | ||
44 | #include <winsock2.h> | ||
45 | #include <winbase.h> | ||
46 | |||
47 | /*=========================================================================*\ | ||
48 | * BSD include files | ||
49 | \*=========================================================================*/ | ||
50 | #else | ||
51 | /* close function */ | ||
52 | #include <unistd.h> | ||
53 | /* fnctnl function and associated constants */ | ||
54 | #include <fcntl.h> | ||
55 | /* struct timeval and CLK_TCK */ | ||
56 | #include <sys/time.h> | ||
57 | /* times function and struct tms */ | ||
58 | #include <sys/times.h> | ||
59 | /* internet protocol definitions */ | ||
60 | #include <netinet/in.h> | ||
61 | #include <arpa/inet.h> | ||
62 | /* struct sockaddr */ | ||
63 | #include <sys/types.h> | ||
64 | /* socket function */ | ||
65 | #include <sys/socket.h> | ||
66 | /* gethostbyname and gethostbyaddr functions */ | ||
67 | #include <netdb.h> | ||
68 | /* for some reason, bcopy and it's friends are not defined automatically | ||
69 | ** on the IRIX plataforms... */ | ||
70 | #ifdef __sgi | ||
71 | #include <bstring.h> | ||
72 | #endif | ||
73 | #endif | ||
74 | |||
75 | /*=========================================================================*\ | ||
76 | * Datatype compatibilization and some simple changes | ||
77 | \*=========================================================================*/ | ||
78 | #ifndef WIN32 | ||
79 | #define closesocket close /* WinSock2 has a closesock function instead | ||
80 | ** of using the regular close function */ | ||
81 | #define SOCKET int /* it defines a SOCKET type instead of | ||
82 | ** using an integer file descriptor */ | ||
83 | #define INVALID_SOCKET (-1) /* and uses the this macro to represent and | ||
84 | ** invalid socket */ | ||
85 | #ifndef INADDR_NONE /* some unix flavours don't define this */ | ||
86 | #define INADDR_NONE (-1) | ||
87 | #endif | ||
88 | #ifndef CLK_TCK /* SunOS, for instance, does not define */ | ||
89 | #define CLK_TCK 60 /* CLK_TCK */ | ||
90 | #endif | ||
91 | #endif | ||
92 | |||
93 | /*=========================================================================*\ | ||
94 | * Module definitions | ||
95 | \*=========================================================================*/ | ||
96 | /*-------------------------------------------------------------------------*\ | ||
97 | * The send and receive function can return one of the following return | ||
98 | * codes. The values are mapped into Lua values by the function | ||
99 | * push_error. | ||
100 | \*-------------------------------------------------------------------------*/ | ||
101 | #define NET_DONE -1 /* operation completed successfully */ | ||
102 | #define NET_TIMEOUT 0 /* operation timed out */ | ||
103 | #define NET_CLOSED 1 /* the connection has been closed */ | ||
104 | |||
105 | /*-------------------------------------------------------------------------*\ | ||
106 | * As far as a Lua script is concerned, there are two kind of objects | ||
107 | * representing a socket. A client socket is an object created by the | ||
108 | * function connect, and implementing the methods send, receive, timeout | ||
109 | * and close. A server socket is an object created by the function bind, | ||
110 | * and implementing the methods listen, accept and close. Lua tag values | ||
111 | * for these objects are created in the lua_socklibopen function, and | ||
112 | * passed as closure values (first argumnents to every library function, | ||
113 | # because we can't have any global variables. | ||
114 | \*-------------------------------------------------------------------------*/ | ||
115 | #define CLIENT_TAG 1 | ||
116 | #define SERVER_TAG 2 | ||
117 | #define FIRST_PAR 3 | ||
118 | |||
119 | /*-------------------------------------------------------------------------*\ | ||
120 | * Both socket types are stored in the same structure to simplify | ||
121 | * implementation. The tag value used is different, though. The timeout | ||
122 | * fields are not used for the server socket object. | ||
123 | * There are two timeout values. The block timeout specifies the maximum | ||
124 | * time the any IO operation performed by luasock can be blocked waiting | ||
125 | * for completion. The return timeout specifies the maximum time a Lua script | ||
126 | * can be blocked waiting for an luasock IO operation to complete. | ||
127 | \*-------------------------------------------------------------------------*/ | ||
128 | typedef struct t_sock { | ||
129 | SOCKET sock; /* operating system socket object */ | ||
130 | int b; /* block timeout in ms */ | ||
131 | int r; /* return timeout in ms */ | ||
132 | int blocking; /* is this socket in blocking mode? */ | ||
133 | } t_sock; | ||
134 | typedef t_sock *p_sock; | ||
135 | |||
136 | /*-------------------------------------------------------------------------*\ | ||
137 | * Macros and internal declarations | ||
138 | \*-------------------------------------------------------------------------*/ | ||
139 | /* internal function prototypes */ | ||
140 | #include "sock.h" | ||
141 | |||
142 | /* return time since marked start in ms */ | ||
143 | #define time_since(start) (get_time()-start) | ||
144 | |||
145 | /* min and max macros */ | ||
146 | #ifndef min | ||
147 | #define min(x, y) ((x) < (y) ? x : y) | ||
148 | #endif | ||
149 | #ifndef max | ||
150 | #define max(x, y) ((x) > (y) ? x : y) | ||
151 | #endif | ||
152 | |||
153 | /*=========================================================================*\ | ||
154 | * Test support functions | ||
155 | \*=========================================================================*/ | ||
156 | #ifdef _DEBUG | ||
157 | /*-------------------------------------------------------------------------*\ | ||
158 | * Returns the time the system has been up, in secconds. | ||
159 | \*-------------------------------------------------------------------------*/ | ||
160 | static void net_time(lua_State *L); | ||
161 | static void net_time(lua_State *L) | ||
162 | { | ||
163 | lua_pushnumber(L, get_time()/1000.0); | ||
164 | } | ||
165 | |||
166 | /*-------------------------------------------------------------------------*\ | ||
167 | * Causes a Lua script to sleep for the specified number of secconds | ||
168 | \*-------------------------------------------------------------------------*/ | ||
169 | static void net_sleep(lua_State *L); | ||
170 | static void net_sleep(lua_State *L) | ||
171 | { | ||
172 | int sec = (int) luaL_check_number(L, 1); | ||
173 | #ifdef WIN32 | ||
174 | Sleep(1000*sec); | ||
175 | #else | ||
176 | sleep(sec); | ||
177 | #endif | ||
178 | } | ||
179 | |||
180 | #endif | ||
181 | |||
182 | /*=========================================================================*\ | ||
183 | * Lua exported functions | ||
184 | * These functions can be accessed from a Lua script. | ||
185 | \*=========================================================================*/ | ||
186 | /*-------------------------------------------------------------------------*\ | ||
187 | * Creates a client socket and returns it to the Lua script. The timeout | ||
188 | * values are initialized as -1 so that the socket will block at any | ||
189 | * IO operation. | ||
190 | * Input | ||
191 | * host: host name or ip address to connect to | ||
192 | * port: port number on host | ||
193 | * Returns | ||
194 | * On success: client socket | ||
195 | * On error: nil, followed by an error message | ||
196 | \*-------------------------------------------------------------------------*/ | ||
197 | static void net_connect(lua_State *L) | ||
198 | { | ||
199 | const char *hostname = luaL_check_string(L, FIRST_PAR); | ||
200 | unsigned short port = (unsigned short) luaL_check_number(L, FIRST_PAR+1); | ||
201 | struct sockaddr_in server; | ||
202 | p_sock sock = create_tcpsock(); | ||
203 | if (!sock) { | ||
204 | lua_pushnil(L); | ||
205 | lua_pushstring(L, sock_strerror()); | ||
206 | } | ||
207 | /* fills the sockaddr structure with the information needed to | ||
208 | ** connect our socket with the remote host */ | ||
209 | if (!fill_sockaddr(&server, hostname, port)) { | ||
210 | free(sock); | ||
211 | lua_pushnil(L); | ||
212 | lua_pushstring(L, host_strerror()); | ||
213 | return; | ||
214 | } | ||
215 | if (connect(sock->sock,(struct sockaddr *)&server,sizeof(server)) < 0) { | ||
216 | /* no connection? we close the socket to free the descriptor */ | ||
217 | closesocket(sock->sock); | ||
218 | lua_pushnil(L); | ||
219 | lua_pushstring(L, connect_strerror()); | ||
220 | return; | ||
221 | } | ||
222 | push_client(L, sock); | ||
223 | /* no need to push second return value, since it would be nil anyways */ | ||
224 | } | ||
225 | |||
226 | /*-------------------------------------------------------------------------*\ | ||
227 | * Specifies the number of connections that can be queued on a server | ||
228 | * socket. | ||
229 | * Input | ||
230 | * sock: server socket created by the bind function | ||
231 | * Returns | ||
232 | * On success: nil | ||
233 | * On error: an error message | ||
234 | \*-------------------------------------------------------------------------*/ | ||
235 | static void net_listen(lua_State *L) | ||
236 | { | ||
237 | p_sock sock = check_server(L, FIRST_PAR); | ||
238 | unsigned int backlog = (unsigned int) luaL_check_number(L, FIRST_PAR+1); | ||
239 | |||
240 | if (listen(sock->sock, backlog) < 0) | ||
241 | lua_pushstring(L, "listen error"); | ||
242 | /* no need to push return value, since it would be nil anyways */ | ||
243 | } | ||
244 | |||
245 | /*-------------------------------------------------------------------------*\ | ||
246 | * Returns a client socket attempting to connect to a server socket. | ||
247 | * The function blocks until a client shows up. | ||
248 | * Input | ||
249 | * sock: server socket created by the bind function | ||
250 | * Returns | ||
251 | * On success: client socket attempting connection | ||
252 | * On error: nil followed by an error message | ||
253 | \*-------------------------------------------------------------------------*/ | ||
254 | static void net_accept(lua_State *L) | ||
255 | { | ||
256 | struct sockaddr_in client_addr; | ||
257 | p_sock server = check_server(L, FIRST_PAR); | ||
258 | int client_sock = -1; | ||
259 | unsigned int client_len = sizeof(client_addr); | ||
260 | p_sock client; | ||
261 | /* waits for a connection */ | ||
262 | client_sock = accept(server->sock, (struct sockaddr *) &client_addr, | ||
263 | &client_len); | ||
264 | /* we create and return a client socket object, passing the received | ||
265 | ** socket to Lua, as a client socket */ | ||
266 | client = create_sock(); | ||
267 | if (!client) { | ||
268 | lua_pushnil(L); | ||
269 | lua_pushstring(L, "out of memory"); | ||
270 | return; | ||
271 | } | ||
272 | client->sock = client_sock; | ||
273 | push_client(L, client); | ||
274 | } | ||
275 | |||
276 | /*-------------------------------------------------------------------------*\ | ||
277 | * Associates an address to a server socket. | ||
278 | * Input | ||
279 | * host: host name or ip address to bind to | ||
280 | * port: port to bind to | ||
281 | * backlog: optional parameter specifying the number of connections | ||
282 | * to keep waiting before refuse a connection. the default value is 1. | ||
283 | * Returns | ||
284 | * On success: server socket bound to address | ||
285 | * On error: nil, followed by an error message | ||
286 | \*-------------------------------------------------------------------------*/ | ||
287 | static void net_bind(lua_State *L) | ||
288 | { | ||
289 | const char *hostname = luaL_check_string(L, FIRST_PAR); | ||
290 | unsigned short port = (unsigned short) luaL_check_number(L, FIRST_PAR+1); | ||
291 | unsigned int backlog = (unsigned int) luaL_opt_number(L, FIRST_PAR+2, 1.0); | ||
292 | struct sockaddr_in server; | ||
293 | p_sock sock = create_tcpsock(); | ||
294 | if (!sock) { | ||
295 | lua_pushnil(L); | ||
296 | lua_pushstring(L, sock_strerror()); | ||
297 | } | ||
298 | /* fills the sockaddr structure with the information needed to | ||
299 | ** connect our socket with local address */ | ||
300 | if (!fill_sockaddr(&server, hostname, port)) { | ||
301 | free(sock); | ||
302 | lua_pushnil(L); | ||
303 | lua_pushstring(L, host_strerror()); | ||
304 | return; | ||
305 | } | ||
306 | if (bind(sock->sock,(struct sockaddr *)&server,sizeof(server)) < 0) { | ||
307 | lua_pushnil(L); | ||
308 | lua_pushstring(L, bind_strerror()); | ||
309 | return; | ||
310 | } | ||
311 | /* define the connection waiting queue length */ | ||
312 | if (listen(sock->sock, backlog) < 0) { | ||
313 | lua_pushnil(L); | ||
314 | lua_pushstring(L, "listen error"); | ||
315 | return; | ||
316 | } | ||
317 | /* pass the created socket to Lua, as a server socket */ | ||
318 | push_server(L, sock); | ||
319 | /* no need to push return value, since it would be nil anyways */ | ||
320 | } | ||
321 | |||
322 | /*-------------------------------------------------------------------------*\ | ||
323 | * Sets timeout values for IO operations on a client socket | ||
324 | * Input | ||
325 | * sock: client socket created by the connect function | ||
326 | * time: time out value in seconds | ||
327 | * mode: optional timeout mode. "block" specifies the upper bound on | ||
328 | * the time any IO operation on sock can cause the program to block. | ||
329 | * "return" specifies the upper bound on the time elapsed before the | ||
330 | * function returns control to the script. "block" is the default. | ||
331 | * Returns | ||
332 | * no return value | ||
333 | \*-------------------------------------------------------------------------*/ | ||
334 | static void net_timeout(lua_State *L) | ||
335 | { | ||
336 | p_sock sock = check_client(L, FIRST_PAR); | ||
337 | int ms = (int) (luaL_check_number(L, FIRST_PAR+1)*1000.0); | ||
338 | const char *mode = luaL_opt_string(L, FIRST_PAR+2, "b"); | ||
339 | switch (*mode) { | ||
340 | case 'b': | ||
341 | sock->b = ms; | ||
342 | break; | ||
343 | case 'r': | ||
344 | sock->r = ms; | ||
345 | break; | ||
346 | default: | ||
347 | luaL_arg_check(L, 0, FIRST_PAR+2, "invalid timeout mode"); | ||
348 | break; | ||
349 | } | ||
350 | } | ||
351 | |||
352 | /*-------------------------------------------------------------------------*\ | ||
353 | * Send data through a socket | ||
354 | * Input: sock, a_1 [, a_2, a_3 ... a_n] | ||
355 | * sock: client socket created by the connect function | ||
356 | * a_i: strings to be sent. The strings will be sent on the order they | ||
357 | * appear as parameters | ||
358 | * Returns | ||
359 | * On success: nil, followed by the total number of bytes sent | ||
360 | * On error: NET_TIMEOUT if the connection timedout, or NET_CLOSED if | ||
361 | * the connection has been closed | ||
362 | \*-------------------------------------------------------------------------*/ | ||
363 | static void net_send(lua_State *L) | ||
364 | { | ||
365 | p_sock sock = check_client(L, FIRST_PAR); | ||
366 | const char *data; | ||
367 | long size; | ||
368 | int start = get_time(); | ||
369 | long total = 0; | ||
370 | int arg = FIRST_PAR+1; | ||
371 | int err = NET_DONE; | ||
372 | int end; | ||
373 | #ifdef _DEBUG_BLOCK | ||
374 | printf("luasock: send start\n"); | ||
375 | #endif | ||
376 | while ((data = luaL_opt_lstr(L, arg++, NULL, &size)) && err == NET_DONE) | ||
377 | total += send_raw(sock, data, size, start, &err, &end); | ||
378 | push_error(L, err); | ||
379 | lua_pushnumber(L, (double) total); | ||
380 | #ifdef _DEBUG_BLOCK | ||
381 | printf("luasock: send end\n"); | ||
382 | #endif | ||
383 | #ifdef _DEBUG | ||
384 | /* pass the time elapsed during function execution to Lua, so that | ||
385 | ** the test script can make sure we respected the timeouts */ | ||
386 | lua_pushnumber(L, (end-start)/1000.0); | ||
387 | #endif | ||
388 | } | ||
389 | |||
390 | /*-------------------------------------------------------------------------*\ | ||
391 | * Receive data from a socket | ||
392 | * Input: sock [pat_1, pat_2 ... pat_n] | ||
393 | * sock: client socket created by the connect function | ||
394 | * pat_i: may be one of the following | ||
395 | * "*l": reads a text line, defined as a string of caracters terminates | ||
396 | * by a LF character, preceded or not by a CR character. This is | ||
397 | * the default pattern | ||
398 | * "*lu": reads a text line, terminanted by a CR character only. (Unix mode) | ||
399 | * number: reads 'number' characters from the socket | ||
400 | * Returns | ||
401 | * On success: one string for each pattern | ||
402 | * On error: all strings for which there was no error, followed by on | ||
403 | * nil value for each failed string, followed by an error code | ||
404 | \*-------------------------------------------------------------------------*/ | ||
405 | static void net_receive(lua_State *L) | ||
406 | { | ||
407 | static const char *const modenames[] = {"*l", "*lu", NULL}; | ||
408 | p_sock sock = check_client(L, FIRST_PAR); | ||
409 | int err = NET_DONE, arg = FIRST_PAR+1, got = 0; | ||
410 | char *data = NULL; | ||
411 | int start = get_time(); | ||
412 | const char *mode = luaL_opt_string(L, arg++, "*l"); | ||
413 | int end; | ||
414 | #ifdef _DEBUG_BLOCK | ||
415 | printf("luasock: receive start\n"); | ||
416 | #endif | ||
417 | do { | ||
418 | /* if one pattern failed, we just skip all other patterns */ | ||
419 | if (err != NET_DONE) { | ||
420 | lua_pushnil(L); | ||
421 | continue; | ||
422 | } | ||
423 | /* get next pattern */ | ||
424 | switch (luaL_findstring(mode, modenames)) { | ||
425 | /* DOS line mode */ | ||
426 | case 0: | ||
427 | got = receive_dosline(L, sock, &data, start, &err, &end); | ||
428 | break; | ||
429 | /* Unix line mode */ | ||
430 | case 2: | ||
431 | got = receive_unixline(L, sock, &data, start, &err, &end); | ||
432 | break; | ||
433 | /* else it must be a number, raw mode */ | ||
434 | default: { | ||
435 | long size = (long) luaL_check_number(L, arg-1); | ||
436 | got = receive_raw(L, sock, size, &data, start, &err, &end); | ||
437 | break; | ||
438 | } | ||
439 | } | ||
440 | /* pass result */ | ||
441 | lua_pushlstring(L, data, got); | ||
442 | } while ((mode = luaL_opt_string(L, arg++, NULL))); | ||
443 | /* last return is an error code */ | ||
444 | push_error(L, err); | ||
445 | #ifdef _DEBUG_BLOCK | ||
446 | printf("luasock: receive end\n"); | ||
447 | #endif | ||
448 | #ifdef _DEBUG | ||
449 | /* pass the time elapsed during function execution to Lua, so that | ||
450 | ** the test script can make sure we respected the timeouts */ | ||
451 | lua_pushnumber(L, (end-start)/1000.0); | ||
452 | #endif | ||
453 | } | ||
454 | |||
455 | /*-------------------------------------------------------------------------*\ | ||
456 | * Closes a socket. | ||
457 | * Input | ||
458 | * sock: socket to be closed | ||
459 | \*-------------------------------------------------------------------------*/ | ||
460 | static void net_close(lua_State *L) | ||
461 | { | ||
462 | p_sock sock = check_sock(L, FIRST_PAR); | ||
463 | closesocket(sock->sock); | ||
464 | /* set value to -1 so that we can later detect the use of a | ||
465 | ** closed socket */ | ||
466 | sock->sock = -1; | ||
467 | } | ||
468 | |||
469 | /*-------------------------------------------------------------------------*\ | ||
470 | * Gettable fallback for the client socket. This function provides the | ||
471 | * alternative interface client:receive, client:send etc for the client | ||
472 | * socket methods. | ||
473 | \*-------------------------------------------------------------------------*/ | ||
474 | static void client_gettable(lua_State *L) | ||
475 | { | ||
476 | static const char *const net_api[] = {"receive","send","timeout","close", | ||
477 | "connect", NULL}; | ||
478 | const char *idx = luaL_check_string(L, FIRST_PAR+1); | ||
479 | switch (luaL_findstring(idx, net_api)) { | ||
480 | case 0: | ||
481 | lua_pushnumber(L, get_tag(L, CLIENT_TAG)); | ||
482 | lua_pushnumber(L, get_tag(L, SERVER_TAG)); | ||
483 | lua_pushcclosure(L, net_receive, 2); | ||
484 | break; | ||
485 | case 1: | ||
486 | lua_pushnumber(L, get_tag(L, CLIENT_TAG)); | ||
487 | lua_pushnumber(L, get_tag(L, SERVER_TAG)); | ||
488 | lua_pushcclosure(L, net_send, 2); | ||
489 | break; | ||
490 | case 2: | ||
491 | lua_pushnumber(L, get_tag(L, CLIENT_TAG)); | ||
492 | lua_pushnumber(L, get_tag(L, SERVER_TAG)); | ||
493 | lua_pushcclosure(L, net_timeout, 2); | ||
494 | break; | ||
495 | case 3: | ||
496 | lua_pushnumber(L, get_tag(L, CLIENT_TAG)); | ||
497 | lua_pushnumber(L, get_tag(L, SERVER_TAG)); | ||
498 | lua_pushcclosure(L, net_close, 2); | ||
499 | break; | ||
500 | default: | ||
501 | lua_pushnil(L); | ||
502 | break; | ||
503 | } | ||
504 | } | ||
505 | |||
506 | /*-------------------------------------------------------------------------*\ | ||
507 | * Gettable fallback for the server socket. This function provides the | ||
508 | * alternative interface server:listen, server:accept etc for the server | ||
509 | * socket methods. | ||
510 | \*-------------------------------------------------------------------------*/ | ||
511 | static void server_gettable(lua_State *L) | ||
512 | { | ||
513 | static const char *const net_api[] = {"listen","accept","close", NULL}; | ||
514 | const char *idx = luaL_check_string(L, FIRST_PAR+1); | ||
515 | switch (luaL_findstring(idx, net_api)) { | ||
516 | case 0: | ||
517 | lua_pushnumber(L, get_tag(L, CLIENT_TAG)); | ||
518 | lua_pushnumber(L, get_tag(L, SERVER_TAG)); | ||
519 | lua_pushcclosure(L, net_listen, 2); | ||
520 | break; | ||
521 | case 1: | ||
522 | lua_pushnumber(L, get_tag(L, CLIENT_TAG)); | ||
523 | lua_pushnumber(L, get_tag(L, SERVER_TAG)); | ||
524 | lua_pushcclosure(L, net_accept, 2); | ||
525 | break; | ||
526 | case 2: | ||
527 | lua_pushnumber(L, get_tag(L, CLIENT_TAG)); | ||
528 | lua_pushnumber(L, get_tag(L, SERVER_TAG)); | ||
529 | lua_pushcclosure(L, net_close, 2); | ||
530 | break; | ||
531 | default: | ||
532 | lua_pushnil(L); | ||
533 | break; | ||
534 | } | ||
535 | } | ||
536 | |||
537 | /*-------------------------------------------------------------------------*\ | ||
538 | * Garbage collection fallback for the socket objects. This function | ||
539 | * makes sure that all collected sockets are closed and that the memory | ||
540 | * used by the C structure t_sock is properly released. | ||
541 | \*-------------------------------------------------------------------------*/ | ||
542 | static void sock_gc(lua_State *L) | ||
543 | { | ||
544 | p_sock sock = check_sock(L, FIRST_PAR); | ||
545 | if (sock->sock >= 0) | ||
546 | closesocket(sock->sock); | ||
547 | free(sock); | ||
548 | } | ||
549 | |||
550 | /*=========================================================================*\ | ||
551 | * Internal functions | ||
552 | \*=========================================================================*/ | ||
553 | /*-------------------------------------------------------------------------*\ | ||
554 | * Instals a handler to ignore sigpipe. That is, unless the signal had | ||
555 | * already been redefined. This function is not needed on the WinSock2, | ||
556 | * since it's sockets don't raise this signal. | ||
557 | \*-------------------------------------------------------------------------*/ | ||
558 | #ifndef WIN32 | ||
559 | static void handle_sigpipe(void); | ||
560 | static void handle_sigpipe(void) | ||
561 | { | ||
562 | struct sigaction old, new; | ||
563 | bzero(&new, sizeof new); | ||
564 | new.sa_handler = SIG_IGN; | ||
565 | sigaction(SIGPIPE, &new, &old); | ||
566 | /* test if the signal had been before, and restore it if so */ | ||
567 | if (old.sa_handler != SIG_DFL) { | ||
568 | #ifdef _DEBUG | ||
569 | /* this is a somewhat dangerous situation. we can only hope the | ||
570 | ** installed signal handler understands that this signal can be | ||
571 | ** raised by a socket operation */ | ||
572 | printf("SIGPIPE ALREADY REDEFINED!!!\n"); | ||
573 | #endif | ||
574 | sigaction(SIGPIPE, &old, NULL); | ||
575 | } | ||
576 | } | ||
577 | #endif | ||
578 | |||
579 | /*-------------------------------------------------------------------------*\ | ||
580 | * Creates a t_sock structure with default values. | ||
581 | \*-------------------------------------------------------------------------*/ | ||
582 | static p_sock create_sock(void) | ||
583 | { | ||
584 | p_sock sock = (p_sock) malloc(sizeof(t_sock)); | ||
585 | if (!sock) | ||
586 | return NULL; | ||
587 | sock->sock = -1; | ||
588 | sock->r = -1; | ||
589 | sock->b = -1; | ||
590 | sock->blocking = 1; | ||
591 | return sock; | ||
592 | } | ||
593 | |||
594 | /*-------------------------------------------------------------------------*\ | ||
595 | * Creates a TCP/IP socket. | ||
596 | * Returns | ||
597 | * A pointer to a t_sock structure or NULL in case of error | ||
598 | \*-------------------------------------------------------------------------*/ | ||
599 | static p_sock create_tcpsock(void) | ||
600 | { | ||
601 | p_sock sock = create_sock(); | ||
602 | if (!sock) | ||
603 | return NULL; | ||
604 | sock->sock = socket(AF_INET, SOCK_STREAM, 0); | ||
605 | if (sock->sock < 0) { | ||
606 | free(sock); | ||
607 | sock = NULL; | ||
608 | } | ||
609 | #ifdef _DEBUG | ||
610 | /* this allow us to re-bind onto an address even if there is still | ||
611 | ** a TIME_WAIT condition. debugging is much more confortable, because | ||
612 | ** we don't get "address already in use" errors all the time we | ||
613 | ** re-run the program before the OS is ready. in real life, though | ||
614 | ** there could be data pending on the socket and this could lead to | ||
615 | ** some weird errors. */ | ||
616 | { | ||
617 | int val = 1; | ||
618 | setsockopt(sock->sock, SOL_SOCKET, SO_REUSEADDR, (char *) &val, | ||
619 | sizeof(val)); | ||
620 | } | ||
621 | #endif | ||
622 | return sock; | ||
623 | } | ||
624 | |||
625 | /*-------------------------------------------------------------------------*\ | ||
626 | * Fills a sockaddr structure according to a given host name of ip | ||
627 | * address and a port number. | ||
628 | * Input | ||
629 | * address: pointer to sockaddr structure to be filled | ||
630 | * hostname: host name or ip address | ||
631 | * port: port number | ||
632 | * Returns | ||
633 | * 1 in case of success, 0 otherwise | ||
634 | \*-------------------------------------------------------------------------*/ | ||
635 | static int fill_sockaddr(struct sockaddr_in *address, const char *hostname, | ||
636 | unsigned short port) | ||
637 | { | ||
638 | struct hostent *host = NULL; | ||
639 | unsigned long addr = inet_addr(hostname); | ||
640 | /* BSD says we could have used gethostbyname even if the hostname is | ||
641 | ** in ip address form, but WinSock2 says we can't. Therefore we | ||
642 | ** choose a method that works on both plataforms */ | ||
643 | if (addr == INADDR_NONE) | ||
644 | host = gethostbyname(hostname); | ||
645 | else | ||
646 | host = gethostbyaddr((char * ) &addr, sizeof(unsigned long), AF_INET); | ||
647 | if (!host) | ||
648 | return 0; | ||
649 | memset(address, 0, sizeof(struct sockaddr_in)); | ||
650 | address->sin_family = AF_INET; | ||
651 | address->sin_port = htons(port); | ||
652 | memcpy(&(address->sin_addr), host->h_addr, (unsigned) host->h_length); | ||
653 | return 1; | ||
654 | } | ||
655 | |||
656 | /*-------------------------------------------------------------------------*\ | ||
657 | * Determine the time limit to be passed to the select function, given | ||
658 | * the time elapsed since the beginning of the operation. | ||
659 | * Input | ||
660 | * sock: socket structure being used in operation | ||
661 | * elapsed: time elapsed since operation started | ||
662 | * Returns | ||
663 | * time limit before function return in ms or -1 in case there is no | ||
664 | * time limit | ||
665 | \*-------------------------------------------------------------------------*/ | ||
666 | static int get_timeout(p_sock sock, int elapsed) | ||
667 | { | ||
668 | /* no timeout */ | ||
669 | if (sock->b < 0 && sock->r < 0) | ||
670 | return -1; | ||
671 | /* there is no block timeout, we use the return timeout */ | ||
672 | if (sock->b < 0) | ||
673 | return max(0, sock->r - elapsed); | ||
674 | /* there is no return timeout, we use the block timeout */ | ||
675 | else if (sock->r < 0) | ||
676 | return sock->b; | ||
677 | /* both timeouts are specified */ | ||
678 | else | ||
679 | return min(sock->b, max(0, sock->r - elapsed)); | ||
680 | } | ||
681 | |||
682 | /*-------------------------------------------------------------------------*\ | ||
683 | * Determines if we have a timeout condition or if we can proceed with | ||
684 | * an IO read operation. | ||
685 | * Input | ||
686 | * sock: socket structure being used in operation | ||
687 | * elapsed: time elapsed since operation started | ||
688 | * Returns | ||
689 | * 1 if we can proceed, 0 if a timeou has occured | ||
690 | \*-------------------------------------------------------------------------*/ | ||
691 | static int read_or_timeout(p_sock sock, int elapsed) | ||
692 | { | ||
693 | fd_set set; /* file descriptor set */ | ||
694 | struct timeval to; /* timeout structure */ | ||
695 | int ms = get_timeout(sock, elapsed); | ||
696 | int err; | ||
697 | /* got timeout */ | ||
698 | if (ms == 0) | ||
699 | return 0; | ||
700 | FD_ZERO(&set); | ||
701 | FD_SET(sock->sock, &set); | ||
702 | /* we have a limit on the time we can wait */ | ||
703 | if (ms > 0) { | ||
704 | to.tv_sec = ms / 1000; | ||
705 | to.tv_usec = (ms % 1000) * 1000; | ||
706 | err = select(sock->sock+1, &set, NULL, NULL, &to); | ||
707 | set_nonblocking(sock); | ||
708 | /* we can wait forever */ | ||
709 | } else { | ||
710 | err = select(sock->sock+1, &set, NULL, NULL, NULL); | ||
711 | set_blocking(sock); | ||
712 | } | ||
713 | return (err > 0); | ||
714 | } | ||
715 | |||
716 | /*-------------------------------------------------------------------------*\ | ||
717 | * Determines if we have a timeout condition or if we can proceed with | ||
718 | * an IO write operation. | ||
719 | * Input | ||
720 | * sock: socket structure being used in operation | ||
721 | * elapsed: time elapsed since operation started | ||
722 | * Returns | ||
723 | * 1 if we can proceed, 0 if a timeou has occured | ||
724 | \*-------------------------------------------------------------------------*/ | ||
725 | static int write_or_timeout(p_sock sock, int elapsed) | ||
726 | { | ||
727 | fd_set set; /* file descriptor set */ | ||
728 | struct timeval to; /* timeout structure */ | ||
729 | int ms = get_timeout(sock, elapsed); | ||
730 | int err; | ||
731 | /* got timeout */ | ||
732 | if (ms == 0) | ||
733 | return 0; | ||
734 | FD_ZERO(&set); | ||
735 | FD_SET(sock->sock, &set); | ||
736 | /* we have a limit on the time we can wait */ | ||
737 | if (ms > 0) { | ||
738 | to.tv_sec = ms / 1000; | ||
739 | to.tv_usec = (ms % 1000) * 1000; | ||
740 | err = select(sock->sock+1, NULL, &set, NULL, &to); | ||
741 | set_nonblocking(sock); | ||
742 | /* we can wait forever */ | ||
743 | } else { | ||
744 | err = select(sock->sock+1, NULL, &set, NULL, NULL); | ||
745 | set_blocking(sock); | ||
746 | } | ||
747 | return (err > 0); | ||
748 | } | ||
749 | |||
750 | /*-------------------------------------------------------------------------*\ | ||
751 | * Sends a raw block of data through a socket. The operations are all | ||
752 | * non-blocking and the function respects the timeout values in sock. | ||
753 | * Input | ||
754 | * sock: socket structure being used in operation | ||
755 | * data: buffer to be sent | ||
756 | * wanted: number of bytes in buffer | ||
757 | * start: time the operation started, in ms | ||
758 | * Output | ||
759 | * err: operation error code. NET_DONE, NET_TIMEOUT or NET_CLOSED | ||
760 | * Returns | ||
761 | * Number of bytes written | ||
762 | \*-------------------------------------------------------------------------*/ | ||
763 | static int send_raw(p_sock sock, const char *data, int wanted, | ||
764 | int start, int *err, int *end) | ||
765 | { | ||
766 | int put = 0, total = 0; | ||
767 | *end = start; | ||
768 | while (wanted > 0) { | ||
769 | if(!write_or_timeout(sock, time_since(start))) { | ||
770 | #ifdef _DEBUG | ||
771 | *end = get_time(); | ||
772 | #endif | ||
773 | *err = NET_TIMEOUT; | ||
774 | return total; | ||
775 | } | ||
776 | #ifdef _DEBUG | ||
777 | /* the lua_pushlstring function can take a long time to pass a large block | ||
778 | ** to Lua, therefore, we mark the time before passing the result. | ||
779 | ** also, the call to write of read might take longer then the time we had | ||
780 | ** left, so that the end of the operation is marked before the last call | ||
781 | ** to the OS */ | ||
782 | *end = get_time(); | ||
783 | #endif | ||
784 | put = send(sock->sock, data, wanted, 0); | ||
785 | if (put <= 0) { | ||
786 | #ifdef WIN32 | ||
787 | /* on WinSock, a select over a socket on which there is a | ||
788 | ** non-blocking operation pending returns immediately, even | ||
789 | ** if the call would block. therefore, we have to do a busy | ||
790 | ** wait here. */ | ||
791 | if (WSAGetLastError() == WSAEWOULDBLOCK) | ||
792 | continue; | ||
793 | #endif | ||
794 | *err = NET_CLOSED; | ||
795 | return total; | ||
796 | } | ||
797 | #ifdef _DEBUG_BLOCK | ||
798 | printf("luasock: sent %d bytes, %dms elapsed\n", put, time_since(start)); | ||
799 | #endif | ||
800 | wanted -= put; | ||
801 | data += put; | ||
802 | total += put; | ||
803 | } | ||
804 | *err = NET_DONE; | ||
805 | return total; | ||
806 | } | ||
807 | |||
808 | /*-------------------------------------------------------------------------*\ | ||
809 | * Reads a raw block of data from a socket. The operations are all | ||
810 | * non-blocking and the function respects the timeout values in sock. | ||
811 | * Input | ||
812 | * sock: socket structure being used in operation | ||
813 | * wanted: number of bytes to be read | ||
814 | * start: time the operation started, in ms | ||
815 | * Output | ||
816 | * data: pointer to an internal buffer containing the data read | ||
817 | * err: operation error code. NET_DONE, NET_TIMEOUT or NET_CLOSED | ||
818 | * Returns | ||
819 | * Number of bytes read | ||
820 | \*-------------------------------------------------------------------------*/ | ||
821 | static int receive_raw(lua_State *L, p_sock sock, int wanted, char **data, | ||
822 | int start, int *err, int *end) | ||
823 | { | ||
824 | int got = 0; | ||
825 | char *buffer = NULL; | ||
826 | *end = start; | ||
827 | luaL_resetbuffer(L); | ||
828 | while (wanted > 0) { | ||
829 | buffer = luaL_openspace(L, wanted); | ||
830 | if(!read_or_timeout(sock, time_since(start))) { | ||
831 | #ifdef _DEBUG | ||
832 | *end = get_time(); | ||
833 | #endif | ||
834 | *data = luaL_buffer(L); | ||
835 | *err = NET_TIMEOUT; | ||
836 | return luaL_getsize(L); | ||
837 | } | ||
838 | #ifdef _DEBUG | ||
839 | *end = get_time(); | ||
840 | #endif | ||
841 | got = recv(sock->sock, buffer, wanted, 0); | ||
842 | #ifdef _DEBUG_BLOCK | ||
843 | printf("luasock: wanted %d, got %d, %dms elapsed\n", wanted, got, time_since(start)); | ||
844 | #endif | ||
845 | if (got <= 0) { | ||
846 | *data = luaL_buffer(L); | ||
847 | *err = NET_CLOSED; | ||
848 | return luaL_getsize(L); | ||
849 | } | ||
850 | wanted -= got; | ||
851 | luaL_addsize(L,got); | ||
852 | } | ||
853 | *data = luaL_buffer(L); | ||
854 | *err = NET_DONE; | ||
855 | return luaL_getsize(L); | ||
856 | } | ||
857 | |||
858 | /*-------------------------------------------------------------------------*\ | ||
859 | * Reads a line terminated by a CR LF pair or just by a LF. The CR and LF | ||
860 | * are not returned by the function. All operations are non-blocking and the | ||
861 | * function respects the timeout values in sock. | ||
862 | * Input | ||
863 | * sock: socket structure being used in operation | ||
864 | * wanted: number of bytes in buffer | ||
865 | * start: time the operation started, in ms | ||
866 | * Output | ||
867 | * data: pointer to an internal buffer containing the data read | ||
868 | * err: operation error code. NET_DONE, NET_TIMEOUT or NET_CLOSED | ||
869 | * Returns | ||
870 | * Number of bytes read | ||
871 | \*-------------------------------------------------------------------------*/ | ||
872 | static long receive_dosline(lua_State *L, p_sock sock, char **data, | ||
873 | int start, int *err, int *end) | ||
874 | { | ||
875 | char c = ' '; | ||
876 | long got = 0; | ||
877 | *end = start; | ||
878 | luaL_resetbuffer(L); | ||
879 | while (c != '\n') { | ||
880 | if (read_or_timeout(sock, time_since(start))) { | ||
881 | #ifdef _DEBUG | ||
882 | *end = get_time(); | ||
883 | #endif | ||
884 | got = recv(sock->sock, &c, 1, 0); | ||
885 | if (got <= 0) { | ||
886 | *err = NET_CLOSED; | ||
887 | *data = luaL_buffer(L); | ||
888 | return luaL_getsize(L); | ||
889 | } | ||
890 | luaL_addchar(L, c); | ||
891 | } else { | ||
892 | *err = NET_TIMEOUT; | ||
893 | *data = luaL_buffer(L); | ||
894 | return luaL_getsize(L); | ||
895 | } | ||
896 | } | ||
897 | *err = NET_DONE; | ||
898 | *data = luaL_buffer(L); | ||
899 | got = luaL_getsize(L); | ||
900 | if ((*data)[got-2] == '\r') return got-2; | ||
901 | else return got-1; | ||
902 | } | ||
903 | |||
904 | /*-------------------------------------------------------------------------*\ | ||
905 | * Reads a line terminated by a LF character, which is not returned by | ||
906 | * the function. All operations are non-blocking and the function respects | ||
907 | * the timeout values in sock. | ||
908 | * Input | ||
909 | * sock: socket structure being used in operation | ||
910 | * wanted: number of bytes in buffer | ||
911 | * start: time the operation started, in ms | ||
912 | * Output | ||
913 | * data: pointer to an internal buffer containing the data read | ||
914 | * err: operation error code. NET_DONE, NET_TIMEOUT or NET_CLOSED | ||
915 | * Returns | ||
916 | * Number of bytes read | ||
917 | \*-------------------------------------------------------------------------*/ | ||
918 | static long receive_unixline(lua_State *L, p_sock sock, char **data, | ||
919 | int start, int *err, int *end) | ||
920 | { | ||
921 | char c = ' '; | ||
922 | *end = start; | ||
923 | luaL_resetbuffer(L); | ||
924 | while (c != '\n') { | ||
925 | if (read_or_timeout(sock, time_since(start))) { | ||
926 | #ifdef _DEBUG | ||
927 | *end = get_time(); | ||
928 | #endif | ||
929 | if (recv(sock->sock, &c, 1, 0) <= 0) { | ||
930 | *err = NET_CLOSED; | ||
931 | *data = luaL_buffer(L); | ||
932 | return luaL_getsize(L); | ||
933 | } | ||
934 | luaL_addchar(L, c); | ||
935 | } else { | ||
936 | *err = NET_TIMEOUT; | ||
937 | *data = luaL_buffer(L); | ||
938 | return luaL_getsize(L); | ||
939 | } | ||
940 | } | ||
941 | *err = NET_DONE; | ||
942 | *data = luaL_buffer(L); | ||
943 | return luaL_getsize(L) - 1; | ||
944 | } | ||
945 | |||
946 | /*-------------------------------------------------------------------------*\ | ||
947 | * Gets a tag from a closure parameter | ||
948 | * Input | ||
949 | * L: lua environment | ||
950 | * par: parameter number | ||
951 | \*-------------------------------------------------------------------------*/ | ||
952 | static int get_tag(lua_State *L, int par) | ||
953 | { | ||
954 | return (int) lua_getnumber(L, lua_getparam(L, par)); | ||
955 | } | ||
956 | |||
957 | /*-------------------------------------------------------------------------*\ | ||
958 | * Passes an error code to Lua. The NET_DONE error is translated to nil. | ||
959 | * Input | ||
960 | * err: error code to be passed to Lua | ||
961 | \*-------------------------------------------------------------------------*/ | ||
962 | static void push_error(lua_State *L, int err) | ||
963 | { | ||
964 | switch (err) { | ||
965 | case NET_DONE: | ||
966 | lua_pushnil(L); | ||
967 | break; | ||
968 | case NET_TIMEOUT: | ||
969 | lua_pushstring(L, "timeout"); | ||
970 | break; | ||
971 | case NET_CLOSED: | ||
972 | lua_pushstring(L, "closed"); | ||
973 | break; | ||
974 | } | ||
975 | } | ||
976 | |||
977 | /*-------------------------------------------------------------------------*\ | ||
978 | * Passes a client socket to Lua. | ||
979 | * Must be called from a closure receiving the socket tags as its | ||
980 | * parameters. | ||
981 | * Input | ||
982 | * L: lua environment | ||
983 | * sock: pointer to socket structure to be used | ||
984 | \*-------------------------------------------------------------------------*/ | ||
985 | static void push_client(lua_State *L, p_sock sock) | ||
986 | { | ||
987 | lua_pushusertag(L, (void *) sock, get_tag(L, CLIENT_TAG)); | ||
988 | } | ||
989 | |||
990 | /*-------------------------------------------------------------------------*\ | ||
991 | * Passes a server socket to Lua. | ||
992 | * Must be called from a closure receiving the socket tags as its | ||
993 | * parameters. | ||
994 | * Input | ||
995 | * L: lua environment | ||
996 | * sock: pointer to socket structure to be used | ||
997 | \*-------------------------------------------------------------------------*/ | ||
998 | static void push_server(lua_State *L, p_sock sock) | ||
999 | { | ||
1000 | lua_pushusertag(L, (void *) sock, get_tag(L, SERVER_TAG)); | ||
1001 | } | ||
1002 | |||
1003 | /*=========================================================================*\ | ||
1004 | * WinSock2 specific functions. | ||
1005 | \*=========================================================================*/ | ||
1006 | #ifdef WIN32 | ||
1007 | /*-------------------------------------------------------------------------*\ | ||
1008 | * Initializes WinSock2 library. | ||
1009 | * Returns | ||
1010 | * 1 in case of success. 0 in case of error. | ||
1011 | \*-------------------------------------------------------------------------*/ | ||
1012 | static int wsock_open(void) | ||
1013 | { | ||
1014 | WORD wVersionRequested;WSADATA wsaData;int err; | ||
1015 | wVersionRequested = MAKEWORD( 2, 0 ); | ||
1016 | err = WSAStartup( wVersionRequested, &wsaData ); | ||
1017 | if ( err != 0 ) { | ||
1018 | return 0; | ||
1019 | } | ||
1020 | if ( LOBYTE( wsaData.wVersion ) != 2 || | ||
1021 | HIBYTE( wsaData.wVersion ) != 0 ) { | ||
1022 | WSACleanup( ); | ||
1023 | return 0; | ||
1024 | } | ||
1025 | return 1; | ||
1026 | } | ||
1027 | |||
1028 | /*-------------------------------------------------------------------------*\ | ||
1029 | * Gets time in ms, relative to system startup. | ||
1030 | * Returns | ||
1031 | * time in ms. | ||
1032 | \*-------------------------------------------------------------------------*/ | ||
1033 | static int get_time(void) | ||
1034 | { | ||
1035 | return GetTickCount(); | ||
1036 | } | ||
1037 | |||
1038 | /*-------------------------------------------------------------------------*\ | ||
1039 | * Put socket into blocking mode. | ||
1040 | \*-------------------------------------------------------------------------*/ | ||
1041 | static void set_blocking(p_sock sock) | ||
1042 | { | ||
1043 | u_long argp = 0; | ||
1044 | if (!sock->blocking) { | ||
1045 | ioctlsocket(sock->sock, FIONBIO, &argp); | ||
1046 | sock->blocking = 1; | ||
1047 | } | ||
1048 | } | ||
1049 | |||
1050 | /*-------------------------------------------------------------------------*\ | ||
1051 | * Put socket into non-blocking mode. | ||
1052 | \*-------------------------------------------------------------------------*/ | ||
1053 | static void set_nonblocking(p_sock sock) | ||
1054 | { | ||
1055 | u_long argp = 1; | ||
1056 | if (sock->blocking) { | ||
1057 | ioctlsocket(sock->sock, FIONBIO, &argp); | ||
1058 | sock->blocking = 0; | ||
1059 | } | ||
1060 | } | ||
1061 | |||
1062 | /*-------------------------------------------------------------------------*\ | ||
1063 | * Returns a string describing the last host manipulation error. | ||
1064 | \*-------------------------------------------------------------------------*/ | ||
1065 | static char *host_strerror(void) | ||
1066 | { | ||
1067 | switch (WSAGetLastError()) { | ||
1068 | case HOST_NOT_FOUND: return "host not found"; | ||
1069 | case NO_ADDRESS: return "unable to resolve host name"; | ||
1070 | case NO_RECOVERY: return "name server error"; | ||
1071 | case TRY_AGAIN: return "name server unavailable, try again later."; | ||
1072 | default: return "unknown error"; | ||
1073 | } | ||
1074 | } | ||
1075 | |||
1076 | /*-------------------------------------------------------------------------*\ | ||
1077 | * Returns a string describing the last socket manipulation error. | ||
1078 | \*-------------------------------------------------------------------------*/ | ||
1079 | static char *sock_strerror(void) | ||
1080 | { | ||
1081 | switch (WSAGetLastError()) { | ||
1082 | case WSANOTINITIALISED: return "not initialized"; | ||
1083 | case WSAENETDOWN: return "network is down"; | ||
1084 | case WSAEMFILE: return "descriptor table is full"; | ||
1085 | case WSAENOBUFS: return "insufficient buffer space"; | ||
1086 | default: return "unknown error"; | ||
1087 | } | ||
1088 | } | ||
1089 | |||
1090 | /*-------------------------------------------------------------------------*\ | ||
1091 | * Returns a string describing the last bind operation error. | ||
1092 | \*-------------------------------------------------------------------------*/ | ||
1093 | static char *bind_strerror(void) | ||
1094 | { | ||
1095 | switch (WSAGetLastError()) { | ||
1096 | case WSANOTINITIALISED: return "not initialized"; | ||
1097 | case WSAENETDOWN: return "network is down"; | ||
1098 | case WSAEADDRINUSE: return "address already in use"; | ||
1099 | case WSAEINVAL: return "socket already bound"; | ||
1100 | case WSAENOBUFS: return "too many connections"; | ||
1101 | case WSAEFAULT: return "invalid address"; | ||
1102 | case WSAENOTSOCK: return "not a socket descriptor"; | ||
1103 | default: return "unknown error"; | ||
1104 | } | ||
1105 | } | ||
1106 | |||
1107 | /*-------------------------------------------------------------------------*\ | ||
1108 | * Returns a string describing the last connect operationerror. | ||
1109 | \*-------------------------------------------------------------------------*/ | ||
1110 | static char *connect_strerror(void) | ||
1111 | { | ||
1112 | switch (WSAGetLastError()) { | ||
1113 | case WSANOTINITIALISED: return "not initialized"; | ||
1114 | case WSAENETDOWN: return "network is down"; | ||
1115 | case WSAEADDRINUSE: return "address already in use"; | ||
1116 | case WSAEADDRNOTAVAIL: return "address unavailable"; | ||
1117 | case WSAECONNREFUSED: return "connection refused"; | ||
1118 | case WSAENETUNREACH: return "network is unreachable"; | ||
1119 | default: return "unknown error"; | ||
1120 | } | ||
1121 | } | ||
1122 | #else | ||
1123 | |||
1124 | /*=========================================================================*\ | ||
1125 | * BSD specific functions. | ||
1126 | \*=========================================================================*/ | ||
1127 | /*-------------------------------------------------------------------------*\ | ||
1128 | * Gets time in ms, relative to system startup. | ||
1129 | * Returns | ||
1130 | * time in ms. | ||
1131 | \*-------------------------------------------------------------------------*/ | ||
1132 | static int get_time(void) | ||
1133 | { | ||
1134 | struct tms t; | ||
1135 | return (times(&t)*1000)/CLK_TCK; | ||
1136 | } | ||
1137 | |||
1138 | /*-------------------------------------------------------------------------*\ | ||
1139 | * Put socket into blocking mode. | ||
1140 | \*-------------------------------------------------------------------------*/ | ||
1141 | static void set_blocking(p_sock sock) | ||
1142 | { | ||
1143 | if (!sock->blocking) { | ||
1144 | int flags = fcntl(sock->sock, F_GETFL, 0); | ||
1145 | flags &= (~(O_NONBLOCK)); | ||
1146 | fcntl(sock->sock, F_SETFL, flags); | ||
1147 | sock->blocking = 1; | ||
1148 | } | ||
1149 | } | ||
1150 | |||
1151 | /*-------------------------------------------------------------------------*\ | ||
1152 | * Put socket into non-blocking mode. | ||
1153 | \*-------------------------------------------------------------------------*/ | ||
1154 | static void set_nonblocking(p_sock sock) | ||
1155 | { | ||
1156 | if (sock->blocking) { | ||
1157 | int flags = fcntl(sock->sock, F_GETFL, 0); | ||
1158 | flags |= O_NONBLOCK; | ||
1159 | fcntl(sock->sock, F_SETFL, flags); | ||
1160 | sock->blocking = 0; | ||
1161 | } | ||
1162 | } | ||
1163 | |||
1164 | /*-------------------------------------------------------------------------*\ | ||
1165 | * Returns a string describing the last host manipulation error. | ||
1166 | \*-------------------------------------------------------------------------*/ | ||
1167 | static char *host_strerror(void) | ||
1168 | { | ||
1169 | switch (h_errno) { | ||
1170 | case HOST_NOT_FOUND: return "host not found"; | ||
1171 | case NO_ADDRESS: return "unable to resolve host name"; | ||
1172 | case NO_RECOVERY: return "name server error"; | ||
1173 | case TRY_AGAIN: return "name server unavailable, try again later"; | ||
1174 | default: return "unknown error"; | ||
1175 | } | ||
1176 | } | ||
1177 | |||
1178 | /*-------------------------------------------------------------------------*\ | ||
1179 | * Returns a string describing the last socket manipulation error. | ||
1180 | \*-------------------------------------------------------------------------*/ | ||
1181 | static char *sock_strerror(void) | ||
1182 | { | ||
1183 | switch (errno) { | ||
1184 | case EACCES: return "access denied"; | ||
1185 | case EMFILE: return "descriptor table is full"; | ||
1186 | case ENFILE: return "too many open files"; | ||
1187 | case ENOBUFS: return "insuffucient buffer space"; | ||
1188 | default: return "unknown error"; | ||
1189 | } | ||
1190 | } | ||
1191 | |||
1192 | /*-------------------------------------------------------------------------*\ | ||
1193 | * Returns a string describing the last bind command error. | ||
1194 | \*-------------------------------------------------------------------------*/ | ||
1195 | static char *bind_strerror(void) | ||
1196 | { | ||
1197 | switch (errno) { | ||
1198 | case EBADF: return "invalid descriptor"; | ||
1199 | case EINVAL: return "socket already bound"; | ||
1200 | case EACCES: return "access denied"; | ||
1201 | case ENOTSOCK: return "not a socket descriptor"; | ||
1202 | case EADDRINUSE: return "address already in use"; | ||
1203 | case EADDRNOTAVAIL: return "address unavailable"; | ||
1204 | case ENOMEM: return "out of memory"; | ||
1205 | default: return "unknown error"; | ||
1206 | } | ||
1207 | } | ||
1208 | |||
1209 | /*-------------------------------------------------------------------------*\ | ||
1210 | * Returns a string describing the last connect error. | ||
1211 | \*-------------------------------------------------------------------------*/ | ||
1212 | static char *connect_strerror(void) | ||
1213 | { | ||
1214 | switch (errno) { | ||
1215 | case EBADF: return "invalid descriptor"; | ||
1216 | case ENOTSOCK: return "not a socket descriptor"; | ||
1217 | case EADDRNOTAVAIL: return "address not availabe"; | ||
1218 | case ETIMEDOUT: return "connection timed out"; | ||
1219 | case ECONNREFUSED: return "connection refused"; | ||
1220 | case EACCES: return "access denied"; | ||
1221 | case ENETUNREACH: return "network is unreachable"; | ||
1222 | case EADDRINUSE: return "address already in use"; | ||
1223 | default: return "unknown error"; | ||
1224 | } | ||
1225 | } | ||
1226 | |||
1227 | #endif | ||
1228 | |||
1229 | /*=========================================================================*\ | ||
1230 | * Module exported functions | ||
1231 | \*=========================================================================*/ | ||
1232 | /*-------------------------------------------------------------------------*\ | ||
1233 | * Initializes the library interface with Lua and the socket library. | ||
1234 | * Defines the symbols exported to Lua. | ||
1235 | \*-------------------------------------------------------------------------*/ | ||
1236 | void lua_socklibopen(lua_State *L) | ||
1237 | { | ||
1238 | int client_tag, server_tag; | ||
1239 | static struct luaL_reg funcs[] = { | ||
1240 | {"connect", net_connect}, | ||
1241 | {"bind", net_bind}, | ||
1242 | {"listen", net_listen}, | ||
1243 | {"accept", net_accept}, | ||
1244 | {"close", net_close}, | ||
1245 | {"send", net_send}, | ||
1246 | {"receive", net_receive}, | ||
1247 | {"timeout", net_timeout} | ||
1248 | }; | ||
1249 | int i; | ||
1250 | |||
1251 | #ifdef WIN32 | ||
1252 | wsock_open(); | ||
1253 | #endif | ||
1254 | /* declare new Lua tags for used userdata values */ | ||
1255 | client_tag = lua_newtag(L); | ||
1256 | server_tag = lua_newtag(L); | ||
1257 | /* Lua exported functions */ | ||
1258 | for (i = 0; i < sizeof(funcs)/sizeof(funcs[0]); i++) { | ||
1259 | lua_pushnumber(L, client_tag); | ||
1260 | lua_pushnumber(L, server_tag); | ||
1261 | lua_pushcclosure(L, funcs[i].func, 2 ); | ||
1262 | lua_setglobal(L, funcs[i].name ); | ||
1263 | } | ||
1264 | /* fallbacks */ | ||
1265 | lua_pushnumber(L, client_tag); | ||
1266 | lua_pushnumber(L, server_tag); | ||
1267 | lua_pushcclosure(L, client_gettable, 2); | ||
1268 | lua_settagmethod(L, client_tag, "gettable"); | ||
1269 | |||
1270 | lua_pushnumber(L, client_tag); | ||
1271 | lua_pushnumber(L, server_tag); | ||
1272 | lua_pushcclosure(L, server_gettable, 2); | ||
1273 | lua_settagmethod(L, server_tag, "gettable"); | ||
1274 | |||
1275 | lua_pushnumber(L, client_tag); | ||
1276 | lua_pushnumber(L, server_tag); | ||
1277 | lua_pushcclosure(L, sock_gc, 2); | ||
1278 | lua_settagmethod(L, client_tag, "gc"); | ||
1279 | |||
1280 | lua_pushnumber(L, client_tag); | ||
1281 | lua_pushnumber(L, server_tag); | ||
1282 | lua_pushcclosure(L, sock_gc, 2); | ||
1283 | lua_settagmethod(L, server_tag, "gc"); | ||
1284 | |||
1285 | /* avoid stupid compiler warnings */ | ||
1286 | (void) set_blocking; | ||
1287 | |||
1288 | #ifndef WIN32 | ||
1289 | /* avoid getting killed by a SIGPIPE signal */ | ||
1290 | handle_sigpipe(); | ||
1291 | #endif | ||
1292 | |||
1293 | #ifdef _DEBUG | ||
1294 | /* test support functions */ | ||
1295 | lua_pushcfunction(L, net_sleep); lua_setglobal(L, "sleep"); | ||
1296 | lua_pushcfunction(L, net_time); lua_setglobal(L, "time"); | ||
1297 | #endif | ||
1298 | } | ||
1299 | |||
1300 | /*=========================================================================*\ | ||
1301 | * Lua2c and c2lua stack auxiliary functions | ||
1302 | \*=========================================================================*/ | ||
1303 | /*-------------------------------------------------------------------------*\ | ||
1304 | * Checks if argument is a client socket, printing an error message in | ||
1305 | * case of error | ||
1306 | * Input | ||
1307 | * numArg: argument position in lua2c stack | ||
1308 | * Returns | ||
1309 | * pointer to client socket, or doesn't return in case of error | ||
1310 | \*-------------------------------------------------------------------------*/ | ||
1311 | static p_sock check_client(lua_State *L, int numArg) | ||
1312 | { | ||
1313 | p_sock sock; | ||
1314 | lua_Object o = lua_getparam(L, numArg); | ||
1315 | luaL_arg_check(L, lua_tag(L, o) == get_tag(L, CLIENT_TAG), | ||
1316 | numArg, "client socket expected"); | ||
1317 | sock = (p_sock) lua_getuserdata(L, o); | ||
1318 | if (sock->sock < 0) | ||
1319 | lua_error(L, "operation on closed socket"); | ||
1320 | return sock; | ||
1321 | } | ||
1322 | |||
1323 | /*-------------------------------------------------------------------------*\ | ||
1324 | * Checks if argument is a server socket, printing an error message in | ||
1325 | * case of error | ||
1326 | * Input | ||
1327 | * numArg: argument position in lua2c stack | ||
1328 | * Returns | ||
1329 | * pointer to server socket, or doesn't return in case of error | ||
1330 | \*-------------------------------------------------------------------------*/ | ||
1331 | static p_sock check_server(lua_State *L, int numArg) | ||
1332 | { | ||
1333 | p_sock sock; | ||
1334 | lua_Object o = lua_getparam(L, numArg); | ||
1335 | luaL_arg_check(L, lua_tag(L, o) == get_tag(L, SERVER_TAG), | ||
1336 | numArg, "server socket expected"); | ||
1337 | sock = (p_sock) lua_getuserdata(L, o); | ||
1338 | if (sock->sock < 0) | ||
1339 | lua_error(L, "operation on closed socket"); | ||
1340 | return sock; | ||
1341 | } | ||
1342 | |||
1343 | /*-------------------------------------------------------------------------*\ | ||
1344 | * Checks if argument is a socket, printing an error message in | ||
1345 | * case of error | ||
1346 | * Input | ||
1347 | * numArg: argument position in lua2c stack | ||
1348 | * Returns | ||
1349 | * pointer to socket, or doesn't return in case of error | ||
1350 | \*-------------------------------------------------------------------------*/ | ||
1351 | static p_sock check_sock(lua_State *L, int numArg) | ||
1352 | { | ||
1353 | lua_Object o = lua_getparam(L, numArg); | ||
1354 | luaL_arg_check(L, (lua_tag(L, o) == get_tag(L, CLIENT_TAG)) || | ||
1355 | (lua_tag(L, o) == get_tag(L, SERVER_TAG)), numArg, "socket expected"); | ||
1356 | return lua_getuserdata(L, o); | ||
1357 | } | ||