diff options
author | Diego Nehab <diego@tecgraf.puc-rio.br> | 2001-01-25 21:53:02 +0000 |
---|---|---|
committer | Diego Nehab <diego@tecgraf.puc-rio.br> | 2001-01-25 21:53:02 +0000 |
commit | 973295ba18631846ef2d2d1f891f436cfa5199e5 (patch) | |
tree | 56536be2cf1d7cd6a1707d8338ea76775dfd3570 | |
parent | 7674d3b649af95d43a0b43aa900d48fc8d2a381f (diff) | |
download | luasocket-973295ba18631846ef2d2d1f891f436cfa5199e5.tar.gz luasocket-973295ba18631846ef2d2d1f891f436cfa5199e5.tar.bz2 luasocket-973295ba18631846ef2d2d1f891f436cfa5199e5.zip |
UDP code implemented.
DNS code has been rewritten.
Almost everything has been changed. :-)
-rw-r--r-- | src/luasocket.c | 2263 |
1 files changed, 1466 insertions, 797 deletions
diff --git a/src/luasocket.c b/src/luasocket.c index e6f423c..b81bca7 100644 --- a/src/luasocket.c +++ b/src/luasocket.c | |||
@@ -1,12 +1,12 @@ | |||
1 | /*=========================================================================*\ | 1 | /*=========================================================================*\ |
2 | * TCP/IP bind for the Lua language | 2 | * IPv4 Sockets for the Lua language |
3 | * Diego Nehab | 3 | * Diego Nehab |
4 | * 26/11/1999 | 4 | * 26/11/1999 |
5 | * | 5 | * |
6 | * Module: LUASOCKET.C | 6 | * Module: luasocket.c |
7 | * | 7 | * |
8 | * This module is part of an effort to make the most important features | 8 | * This module is part of an effort to make the most important features |
9 | * of the TCP/IP protocol available to Lua scripts. | 9 | * of the IPv4 Socket layer available to Lua scripts. |
10 | * The Lua interface to TCP/IP follows the BSD TCP/IP API closely, | 10 | * The Lua interface to TCP/IP follows the BSD TCP/IP API closely, |
11 | * trying to simplify all tasks involved in setting up a client connection | 11 | * trying to simplify all tasks involved in setting up a client connection |
12 | * and simple server connections. | 12 | * and simple server connections. |
@@ -60,28 +60,20 @@ | |||
60 | #include <sys/socket.h> | 60 | #include <sys/socket.h> |
61 | /* gethostbyname and gethostbyaddr functions */ | 61 | /* gethostbyname and gethostbyaddr functions */ |
62 | #include <netdb.h> | 62 | #include <netdb.h> |
63 | /* for some reason, bcopy and it's friends are not defined automatically | ||
64 | ** on the IRIX plataforms... */ | ||
65 | #ifdef __sgi | ||
66 | #include <bstring.h> | ||
67 | #endif | ||
68 | #endif | 63 | #endif |
69 | 64 | ||
70 | /*=========================================================================*\ | 65 | /*=========================================================================*\ |
71 | * Datatype compatibilization and some simple changes | 66 | * Datatype compatibilization and some simple changes |
72 | \*=========================================================================*/ | 67 | \*=========================================================================*/ |
73 | #ifndef WIN32 | 68 | #ifndef WIN32 |
74 | #define closesocket close /* WinSock2 has a closesock function instead | 69 | #define closesocket close /* WinSock2 has a closesock function instead |
75 | ** of using the regular close function */ | 70 | ** of using the regular close function */ |
76 | #define SOCKET int /* it defines a SOCKET type instead of | 71 | #define SOCKET int /* it defines a SOCKET type instead of |
77 | ** using an integer file descriptor */ | 72 | ** using an integer file descriptor */ |
78 | #define INVALID_SOCKET (-1) /* and uses the this macro to represent and | 73 | #define INVALID_SOCKET (-1) /* and uses the this macro to represent and |
79 | ** invalid socket */ | 74 | ** invalid socket */ |
80 | #ifndef INADDR_NONE /* some unix flavours don't define this */ | 75 | #ifndef CLK_TCK /* SunOS, does not define CLK_TCK */ |
81 | #define INADDR_NONE (-1) | 76 | #define CLK_TCK 60 |
82 | #endif | ||
83 | #ifndef CLK_TCK /* SunOS, for instance, does not define */ | ||
84 | #define CLK_TCK 60 /* CLK_TCK */ | ||
85 | #endif | 77 | #endif |
86 | #endif | 78 | #endif |
87 | 79 | ||
@@ -93,9 +85,10 @@ | |||
93 | * codes. The values are mapped into Lua values by the function | 85 | * codes. The values are mapped into Lua values by the function |
94 | * push_error. | 86 | * push_error. |
95 | \*-------------------------------------------------------------------------*/ | 87 | \*-------------------------------------------------------------------------*/ |
96 | #define NET_DONE -1 /* operation completed successfully */ | 88 | #define NET_DONE -1 /* operation completed successfully */ |
97 | #define NET_TIMEOUT 0 /* operation timed out */ | 89 | #define NET_TIMEOUT 0 /* operation timed out */ |
98 | #define NET_CLOSED 1 /* the connection has been closed */ | 90 | #define NET_CLOSED 1 /* the connection has been closed */ |
91 | #define NET_REFUSED 2 /* the data transfer has been refused */ | ||
99 | 92 | ||
100 | /*-------------------------------------------------------------------------*\ | 93 | /*-------------------------------------------------------------------------*\ |
101 | * Time out mode to be checked | 94 | * Time out mode to be checked |
@@ -110,24 +103,31 @@ | |||
110 | #define P_SOCK "(p_sock)sock" | 103 | #define P_SOCK "(p_sock)sock" |
111 | 104 | ||
112 | /*-------------------------------------------------------------------------*\ | 105 | /*-------------------------------------------------------------------------*\ |
106 | * The maximum message size handled (576 bytes should be enough...) | ||
107 | \*-------------------------------------------------------------------------*/ | ||
108 | #define UDPMAX 4096 | ||
109 | |||
110 | /*-------------------------------------------------------------------------*\ | ||
113 | * Both socket types are stored in the same structure to simplify | 111 | * Both socket types are stored in the same structure to simplify |
114 | * implementation. The tag value used is different, though. | 112 | * implementation. The tag value used is different, though. |
115 | * The timeout and buffer parameters are not used by server sockets. | 113 | * The buffer parameters are not used by server and UDP sockets. |
116 | \*-------------------------------------------------------------------------*/ | 114 | \*-------------------------------------------------------------------------*/ |
117 | typedef struct t_sock { | 115 | typedef struct t_sock { |
118 | /* operating system socket object */ | 116 | /* operating system socket object */ |
119 | SOCKET sock; | 117 | SOCKET sock; |
120 | /* start time of the current operation */ | 118 | /* start time of the current operation */ |
121 | int tm_start; | 119 | int tm_start; |
122 | /* return and blocking timeout values (-1 if no limit) */ | 120 | /* return and blocking timeout values (-1 if no limit) */ |
123 | int tm_return, tm_block; | 121 | int tm_return, tm_block; |
124 | /* buffered I/O storage */ | 122 | /* buffered I/O storage */ |
125 | unsigned char bf_buffer[LUASOCKET_BUFFERSIZE]; | 123 | unsigned char bf_buffer[LUASOCKET_BUFFERSIZE]; |
126 | /* first and last red bytes not yet passed to application */ | 124 | /* first and last red bytes not yet passed to application */ |
127 | int bf_first, bf_last; | 125 | int bf_first, bf_last; |
126 | /* is this udp socket in "connected" state? */ | ||
127 | int is_connected; | ||
128 | #ifdef _DEBUG | 128 | #ifdef _DEBUG |
129 | /* end time of current operation, for debug purposes */ | 129 | /* end time of current operation, for debug purposes */ |
130 | int tm_end; | 130 | int tm_end; |
131 | #endif | 131 | #endif |
132 | } t_sock; | 132 | } t_sock; |
133 | typedef t_sock *p_sock; | 133 | typedef t_sock *p_sock; |
@@ -136,7 +136,7 @@ typedef t_sock *p_sock; | |||
136 | * Tags passed as closure values to global LuaSocket API functions | 136 | * Tags passed as closure values to global LuaSocket API functions |
137 | \*-------------------------------------------------------------------------*/ | 137 | \*-------------------------------------------------------------------------*/ |
138 | typedef struct t_tags { | 138 | typedef struct t_tags { |
139 | int client, server, table; | 139 | int client, server, table, udp; |
140 | } t_tags; | 140 | } t_tags; |
141 | typedef t_tags *p_tags; | 141 | typedef t_tags *p_tags; |
142 | 142 | ||
@@ -151,27 +151,46 @@ typedef t_tags *p_tags; | |||
151 | #define max(x, y) ((x) > (y) ? x : y) | 151 | #define max(x, y) ((x) > (y) ? x : y) |
152 | #endif | 152 | #endif |
153 | 153 | ||
154 | /* we are lazy.. */ | ||
155 | typedef struct sockaddr SA; | ||
156 | |||
154 | /*=========================================================================*\ | 157 | /*=========================================================================*\ |
155 | * Internal function prototypes | 158 | * Internal function prototypes |
156 | \*=========================================================================*/ | 159 | \*=========================================================================*/ |
157 | /* luasocket API functions */ | 160 | /* luasocket global API functions */ |
158 | static int global_connect(lua_State *L); | 161 | static int global_tcpconnect(lua_State *L); |
159 | static int global_bind(lua_State *L); | 162 | static int global_tcpbind(lua_State *L); |
160 | static int table_listen(lua_State *L); | 163 | static int global_udpsocket(lua_State *L); |
161 | static int table_accept(lua_State *L); | 164 | static int global_toip(lua_State *L); |
162 | static int table_send(lua_State *L); | 165 | static int global_tohostname(lua_State *L); |
163 | static int table_receive(lua_State *L); | 166 | |
167 | /* luasocket table method API functions */ | ||
168 | static int table_tcpaccept(lua_State *L); | ||
169 | static int table_tcpsend(lua_State *L); | ||
170 | static int table_tcpreceive(lua_State *L); | ||
171 | static int table_udpsendto(lua_State *L); | ||
172 | static int table_udpreceivefrom(lua_State *L); | ||
173 | static int table_udpsetpeername(lua_State *L); | ||
164 | static int table_timeout(lua_State *L); | 174 | static int table_timeout(lua_State *L); |
165 | static int table_close(lua_State *L); | 175 | static int table_close(lua_State *L); |
176 | static int table_poll(lua_State *L); | ||
177 | static int table_getpeername(lua_State *L); | ||
178 | static int table_getsockname(lua_State *L); | ||
179 | |||
180 | /* luasocket optional global API functions */ | ||
166 | #ifndef LUASOCKET_NOGLOBALS | 181 | #ifndef LUASOCKET_NOGLOBALS |
167 | static int global_listen(lua_State *L); | 182 | static int global_tcpaccept(lua_State *L); |
168 | static int global_accept(lua_State *L); | 183 | static int global_udpsendto(lua_State *L); |
184 | static int global_udpreceivefrom(lua_State *L); | ||
185 | static int global_udpsetpeername(lua_State *L); | ||
186 | static int global_udpsetsockname(lua_State *L); | ||
187 | static int global_getsockname(lua_State *L); | ||
188 | static int global_getpeername(lua_State *L); | ||
169 | static int global_send(lua_State *L); | 189 | static int global_send(lua_State *L); |
170 | static int global_receive(lua_State *L); | 190 | static int global_receive(lua_State *L); |
171 | static int global_timeout(lua_State *L); | 191 | static int global_timeout(lua_State *L); |
172 | static int global_close(lua_State *L); | 192 | static int global_close(lua_State *L); |
173 | static p_sock get_selfclientsock(lua_State *L, p_tags tags); | 193 | static int global_poll(lua_State *L); |
174 | static p_sock get_selfserversock(lua_State *L, p_tags tags); | ||
175 | #endif | 194 | #endif |
176 | 195 | ||
177 | /* buffered I/O management */ | 196 | /* buffered I/O management */ |
@@ -195,29 +214,49 @@ static int receive_all(lua_State *L, p_sock sock); | |||
195 | /* parameter manipulation functions */ | 214 | /* parameter manipulation functions */ |
196 | static p_tags pop_tags(lua_State *L); | 215 | static p_tags pop_tags(lua_State *L); |
197 | static p_sock pop_sock(lua_State *L); | 216 | static p_sock pop_sock(lua_State *L); |
198 | static p_sock get_selfsock(lua_State *L, p_tags tags); | 217 | static p_sock get_selfsock(lua_State *L, p_tags tags, int *tag); |
199 | static int gc_sock(lua_State *L); | ||
200 | static p_sock push_servertable(lua_State *L, p_tags tags); | 218 | static p_sock push_servertable(lua_State *L, p_tags tags); |
201 | static p_sock push_clienttable(lua_State *L, p_tags tags); | 219 | static p_sock push_clienttable(lua_State *L, p_tags tags); |
220 | static p_sock push_udptable(lua_State *L, p_tags tags); | ||
202 | static void push_error(lua_State *L, int err); | 221 | static void push_error(lua_State *L, int err); |
222 | static void push_resolved(lua_State *L, struct hostent *hp); | ||
203 | 223 | ||
204 | /* error code translations functions */ | 224 | /* error code translations functions */ |
205 | static char *host_strerror(void); | 225 | static char *host_strerror(void); |
206 | static char *bind_strerror(void); | 226 | static char *bind_strerror(void); |
207 | static char *sock_strerror(void); | 227 | static char *socket_strerror(void); |
208 | static char *connect_strerror(void); | 228 | static char *connect_strerror(void); |
209 | 229 | ||
210 | /* auxiliary functions */ | 230 | /* socket auxiliary functions */ |
231 | const char *tcp_trybind(p_sock sock, const char *address, | ||
232 | unsigned short port, int backlog); | ||
233 | const char *tcp_tryconnect(p_sock sock, const char *address, | ||
234 | unsigned short port); | ||
235 | const char *udp_setpeername(p_sock sock, const char *address, | ||
236 | unsigned short port); | ||
237 | const char *udp_setsockname(p_sock sock, const char *address, | ||
238 | unsigned short port); | ||
239 | static void set_reuseaddr(p_sock sock); | ||
211 | static void set_blocking(p_sock sock); | 240 | static void set_blocking(p_sock sock); |
212 | static void set_nonblocking(p_sock sock); | 241 | static void set_nonblocking(p_sock sock); |
213 | static int create_tcpsocket(p_sock sock); | ||
214 | static int fill_sockaddr(struct sockaddr_in *server, const char *hostname, | ||
215 | unsigned short port); | ||
216 | 242 | ||
217 | #ifdef WIN32 | 243 | #ifdef WIN32 |
218 | static int winsock_open(void); | 244 | static int winsock_open(void); |
245 | #define LUASOCKET_ATON | ||
246 | #endif | ||
247 | |||
248 | #ifdef LUASOCKET_ATON | ||
249 | static int inet_aton(const char *cp, struct in_addr *inp); | ||
219 | #endif | 250 | #endif |
220 | 251 | ||
252 | #ifndef LUASOCKET_NOGLOBALS | ||
253 | static p_sock get_selfserversock(lua_State *L, p_tags tags); | ||
254 | static p_sock get_selfudpsock(lua_State *L, p_tags tags); | ||
255 | #endif | ||
256 | |||
257 | /* tag methods */ | ||
258 | static int gc_table(lua_State *L); | ||
259 | |||
221 | /*=========================================================================*\ | 260 | /*=========================================================================*\ |
222 | * Test support functions | 261 | * Test support functions |
223 | \*=========================================================================*/ | 262 | \*=========================================================================*/ |
@@ -228,8 +267,8 @@ static int winsock_open(void); | |||
228 | static int global_time(lua_State *L); | 267 | static int global_time(lua_State *L); |
229 | static int global_time(lua_State *L) | 268 | static int global_time(lua_State *L) |
230 | { | 269 | { |
231 | lua_pushnumber(L, tm_gettime()/1000.0); | 270 | lua_pushnumber(L, tm_gettime()/1000.0); |
232 | return 1; | 271 | return 1; |
233 | } | 272 | } |
234 | 273 | ||
235 | /*-------------------------------------------------------------------------*\ | 274 | /*-------------------------------------------------------------------------*\ |
@@ -244,7 +283,7 @@ static int global_sleep(lua_State *L) | |||
244 | #else | 283 | #else |
245 | sleep(sec); | 284 | sleep(sec); |
246 | #endif | 285 | #endif |
247 | return 0; | 286 | return 0; |
248 | } | 287 | } |
249 | 288 | ||
250 | #endif | 289 | #endif |
@@ -257,244 +296,427 @@ static int global_sleep(lua_State *L) | |||
257 | * Creates a client socket and returns it to the Lua script. The timeout | 296 | * Creates a client socket and returns it to the Lua script. The timeout |
258 | * values are initialized as -1 so that the socket will block at any | 297 | * values are initialized as -1 so that the socket will block at any |
259 | * IO operation. | 298 | * IO operation. |
260 | * Lua Input | 299 | * Lua Input: address, port |
261 | * host: host name or ip address to connect to | 300 | * address: host name or ip address to connect to |
262 | * port: port number on host | 301 | * port: port number on host |
263 | * Lua Returns | 302 | * Lua Returns |
264 | * On success: client socket | 303 | * On success: client socket object |
265 | * On error: nil, followed by an error message | 304 | * On error: nil, followed by an error message |
266 | \*-------------------------------------------------------------------------*/ | 305 | \*-------------------------------------------------------------------------*/ |
267 | static int global_connect(lua_State *L) | 306 | static int global_tcpconnect(lua_State *L) |
268 | { | 307 | { |
269 | p_tags tags = pop_tags(L); | 308 | p_tags tags = pop_tags(L); |
270 | const char *hostname = luaL_check_string(L, 1); | 309 | const char *address = luaL_check_string(L, 1); |
271 | unsigned short port = (unsigned short) luaL_check_number(L, 2); | 310 | unsigned short port = (unsigned short) luaL_check_number(L, 2); |
272 | struct sockaddr_in server; | 311 | p_sock sock = push_clienttable(L, tags); |
273 | p_sock sock = push_clienttable(L, tags); | 312 | const char *err; |
274 | if (!sock) { | 313 | if (!sock) { |
275 | lua_pushnil(L); | 314 | lua_pushnil(L); |
276 | lua_pushstring(L, "out of memory"); | 315 | lua_pushstring(L, "out of memory"); |
277 | return 2; | 316 | return 2; |
278 | } | 317 | } |
279 | if (!create_tcpsocket(sock)) { | 318 | err = tcp_tryconnect(sock, address, port); |
280 | lua_pushnil(L); | 319 | if (err) { |
281 | lua_pushstring(L, sock_strerror()); | 320 | lua_pushnil(L); |
282 | return 2; | 321 | lua_pushstring(L, err); |
283 | } | 322 | return 2; |
284 | /* fills the sockaddr structure with the information needed to | 323 | } |
285 | ** connect our socket with the remote host */ | 324 | set_nonblocking(sock); |
286 | if (!fill_sockaddr(&server, hostname, port)) { | 325 | return 1; |
287 | lua_pushnil(L); | ||
288 | lua_pushstring(L, host_strerror()); | ||
289 | return 2; | ||
290 | } | ||
291 | if (connect(sock->sock, (struct sockaddr *)&server, sizeof(server)) < 0) { | ||
292 | /* no connection? we close the socket to free the descriptor */ | ||
293 | closesocket(sock->sock); | ||
294 | lua_pushnil(L); | ||
295 | lua_pushstring(L, connect_strerror()); | ||
296 | return 2; | ||
297 | } | ||
298 | /* all operations on client sockets are non-blocking */ | ||
299 | set_nonblocking(sock); | ||
300 | lua_pushnil(L); | ||
301 | return 2; | ||
302 | } | 326 | } |
303 | 327 | ||
304 | /*-------------------------------------------------------------------------*\ | 328 | /*-------------------------------------------------------------------------*\ |
305 | * Converts from ip number to host name | 329 | * Creates a udp socket object and returns it to the Lua script. |
306 | * Lua Input | 330 | * The timeout values are initialized as -1 so that the socket will block |
307 | * ip: ip number | 331 | * at any IO operation. |
308 | * Lua Returns | 332 | * Lua Returns |
309 | * On success: domain name | 333 | * On success: udp socket |
310 | * On error: nil, followed by an error message | 334 | * On error: nil, followed by an error message |
311 | \*-------------------------------------------------------------------------*/ | 335 | \*-------------------------------------------------------------------------*/ |
312 | static int global_toip(lua_State *L) | 336 | static int global_udpsocket(lua_State *L) |
313 | { | 337 | { |
314 | struct hostent *host; | 338 | p_tags tags = pop_tags(L); |
315 | struct in_addr addr; | 339 | p_sock sock = push_udptable(L, tags); |
316 | pop_tags(L); | 340 | if (!sock) return 2; |
317 | host = gethostbyname(luaL_check_string(L, 1)); | 341 | return 1; |
318 | if (!host) { | ||
319 | lua_pushnil(L); | ||
320 | lua_pushstring(L, host_strerror()); | ||
321 | return 2; | ||
322 | } | ||
323 | memcpy(&addr, host->h_addr, (unsigned) host->h_length); | ||
324 | lua_pushstring(L, inet_ntoa(addr)); | ||
325 | return 1; | ||
326 | } | 342 | } |
327 | 343 | ||
328 | /*-------------------------------------------------------------------------*\ | 344 | /*-------------------------------------------------------------------------*\ |
329 | * Specifies the number of connections that can be queued on a server | 345 | * Waits for and returns a client socket object attempting connection |
330 | * socket. | 346 | * with a server socket. The function blocks until a client shows up or |
331 | * Lua Input | 347 | * until a timeout condition is met. |
348 | * Lua Input: sock | ||
332 | * sock: server socket created by the bind function | 349 | * sock: server socket created by the bind function |
333 | * Lua Returns | 350 | * Lua Returns |
334 | * On success: nil | 351 | * On success: client socket attempting connection |
335 | * On error: an error message | 352 | * On error: nil followed by an error message |
336 | \*-------------------------------------------------------------------------*/ | 353 | \*-------------------------------------------------------------------------*/ |
337 | static int table_listen(lua_State *L) | 354 | static int table_tcpaccept(lua_State *L) |
338 | { | 355 | { |
339 | p_sock sock = pop_sock(L); | 356 | struct sockaddr_in client_addr; |
340 | unsigned int backlog = (unsigned int) luaL_check_number(L, 2); | 357 | size_t client_len = sizeof(client_addr); |
341 | if (listen(sock->sock, backlog) < 0) { | 358 | p_sock server = pop_sock(L); |
342 | lua_pushstring(L, "listen error"); | 359 | p_tags tags = pop_tags(L); |
343 | return 1; | 360 | p_sock client = push_clienttable(L, tags); |
361 | tm_markstart(server); | ||
362 | if (tm_gettimeleft(server) >= 0) { | ||
363 | set_nonblocking(server); | ||
364 | do { | ||
365 | if (tm_timedout(server, TM_RECEIVE)) { | ||
366 | lua_pushnil(L); | ||
367 | push_error(L, NET_TIMEOUT); | ||
368 | return 2; | ||
369 | } | ||
370 | client->sock = accept(server->sock, (SA *) &client_addr, | ||
371 | &client_len); | ||
372 | } while (client->sock == INVALID_SOCKET); | ||
373 | |||
344 | } else { | 374 | } else { |
345 | lua_pushnil(L); | 375 | set_blocking(server); |
346 | return 1; | 376 | client->sock = accept(server->sock, (SA *) &client_addr, &client_len); |
347 | } | 377 | } |
378 | set_nonblocking(client); | ||
379 | return 1; | ||
348 | } | 380 | } |
349 | 381 | ||
350 | /*-------------------------------------------------------------------------*\ | 382 | /*-------------------------------------------------------------------------*\ |
351 | * Returns a client socket attempting to connect to a server socket. | 383 | * Associates an address to a server socket. |
352 | * The function blocks until a client shows up. | 384 | * Lua Input: address, port [, backlog] |
353 | * Lua Input | 385 | * address: host name or ip address to bind to |
354 | * sock: server socket created by the bind function | 386 | * port: port to bind to |
387 | * backlog: connection queue length (default: 1) | ||
355 | * Lua Returns | 388 | * Lua Returns |
356 | * On success: client socket attempting connection | 389 | * On success: server socket bound to address |
357 | * On error: nil followed by an error message | 390 | * On error: nil, followed by an error message |
358 | \*-------------------------------------------------------------------------*/ | 391 | \*-------------------------------------------------------------------------*/ |
359 | static int table_accept(lua_State *L) | 392 | static int global_tcpbind(lua_State *L) |
360 | { | 393 | { |
361 | struct sockaddr_in client_addr; | 394 | p_tags tags = pop_tags(L); |
362 | size_t client_len = sizeof(client_addr); | 395 | const char *address = luaL_check_string(L, 1); |
363 | p_sock server = pop_sock(L); | 396 | unsigned short port = (unsigned short) luaL_check_number(L, 2); |
364 | p_tags tags = pop_tags(L); | 397 | int backlog = (int) luaL_opt_number(L, 3, 1); |
365 | p_sock client = push_clienttable(L, tags); | 398 | p_sock sock = push_servertable(L, tags); |
366 | SOCKET accepted = accept(server->sock, (struct sockaddr *) &client_addr, | 399 | const char *err; |
367 | &client_len); | 400 | if (!sock) { |
368 | client->sock = accepted; | 401 | lua_pushnil(L); |
369 | set_nonblocking(client); | 402 | lua_pushstring(L, "out of memory"); |
370 | lua_pushnil(L); | 403 | return 2; |
371 | return 2; | 404 | } |
405 | err = tcp_trybind(sock, address, port, backlog); | ||
406 | if (err) { | ||
407 | lua_pushnil(L); | ||
408 | lua_pushstring(L, err); | ||
409 | return 2; | ||
410 | } | ||
411 | return 1; | ||
372 | } | 412 | } |
373 | 413 | ||
374 | /*-------------------------------------------------------------------------*\ | 414 | /*-------------------------------------------------------------------------*\ |
375 | * Associates an address to a server socket. | 415 | * Associates a local address to UDP socket |
376 | * Input | 416 | * Lua Input: address, port |
377 | * host: host name or ip address to bind to | 417 | * address: host name or ip address to bind to |
378 | * port: port to bind to | 418 | * port: port to bind to |
379 | * backlog: optional parameter specifying the number of connections | 419 | * Lua Returns |
380 | * to keep waiting before refuse a connection. the default value is 1. | 420 | * On success: nil |
381 | * Returns | 421 | * On error: error message |
382 | * On success: server socket bound to address, the ip address and port bound | ||
383 | * On error: nil, followed by an error message | ||
384 | \*-------------------------------------------------------------------------*/ | 422 | \*-------------------------------------------------------------------------*/ |
385 | static int global_bind(lua_State *L) | 423 | static int table_udpsetsockname(lua_State *L) |
386 | { | 424 | { |
387 | p_tags tags = pop_tags(L); | 425 | p_sock sock = pop_sock(L); |
388 | const char *hostname = luaL_check_string(L, 1); | 426 | const char *address = luaL_check_string(L, 2); |
389 | unsigned short port = (unsigned short) luaL_check_number(L, 2); | 427 | unsigned short port = (unsigned short) luaL_check_number(L, 3); |
390 | unsigned int backlog = (unsigned int) luaL_opt_number(L, 3, 1.0); | 428 | const char *err = udp_setsockname(sock, address, port); |
391 | struct sockaddr_in server; | 429 | if (err) { |
392 | size_t server_size = sizeof(server); | 430 | lua_pushstring(L, err); |
393 | p_sock sock = push_servertable(L, tags); | 431 | return 1; |
394 | if (!sock) { | 432 | } |
395 | lua_pushnil(L); | 433 | lua_pushnil(L); |
396 | lua_pushstring(L, sock_strerror()); | 434 | return 1; |
397 | return 2; | ||
398 | } | ||
399 | /* fills the sockaddr structure with the information needed to | ||
400 | ** connect our socket with local address */ | ||
401 | else if (!fill_sockaddr(&server, hostname, port)) { | ||
402 | free(sock); | ||
403 | lua_pushnil(L); | ||
404 | lua_pushstring(L, host_strerror()); | ||
405 | return 2; | ||
406 | } | ||
407 | else if (bind(sock->sock,(struct sockaddr *)&server, server_size) < 0) { | ||
408 | lua_pushnil(L); | ||
409 | lua_pushstring(L, bind_strerror()); | ||
410 | return 2; | ||
411 | } | ||
412 | /* define the connection waiting queue length */ | ||
413 | else if (listen(sock->sock, backlog) < 0) { | ||
414 | lua_pushnil(L); | ||
415 | lua_pushstring(L, "listen error"); | ||
416 | return 2; | ||
417 | } | ||
418 | /* pass the created socket to Lua, as a server socket */ | ||
419 | else { | ||
420 | /* get used address and port */ | ||
421 | getsockname(sock->sock, (struct sockaddr *)&server, &server_size); | ||
422 | /* pass ip number */ | ||
423 | lua_pushstring(L, inet_ntoa(server.sin_addr)); | ||
424 | /* pass port number */ | ||
425 | lua_pushnumber(L, ntohs(server.sin_port)); | ||
426 | lua_pushnil(L); | ||
427 | return 4; | ||
428 | } | ||
429 | } | 435 | } |
430 | 436 | ||
431 | /*-------------------------------------------------------------------------*\ | 437 | /*-------------------------------------------------------------------------*\ |
432 | * Sets timeout values for IO operations on a client socket | 438 | * Sets a peer for a UDP socket |
433 | * Lua Input | 439 | * Lua Input: address, port |
440 | * address: remote host name | ||
441 | * port: remote host port | ||
442 | * Lua Returns | ||
443 | * On success: nil | ||
444 | * On error: error message | ||
445 | \*-------------------------------------------------------------------------*/ | ||
446 | static int table_udpsetpeername(lua_State *L) | ||
447 | { | ||
448 | p_sock sock = pop_sock(L); | ||
449 | const char *address = luaL_check_string(L, 2); | ||
450 | unsigned short port = (unsigned short) luaL_check_number(L, 3); | ||
451 | const char *err = udp_setpeername(sock, address, port); | ||
452 | if (err) { | ||
453 | lua_pushstring(L, err); | ||
454 | return 1; | ||
455 | } | ||
456 | sock->is_connected = 1; | ||
457 | lua_pushnil(L); | ||
458 | return 1; | ||
459 | } | ||
460 | |||
461 | /*-------------------------------------------------------------------------*\ | ||
462 | * Sets timeout values for IO operations on a socket | ||
463 | * Lua Input: sock, time [, mode] | ||
434 | * sock: client socket created by the connect function | 464 | * sock: client socket created by the connect function |
435 | * time: time out value in seconds | 465 | * time: time out value in seconds |
436 | * mode: optional timeout mode. "block" specifies the upper bound on | 466 | * mode: "b" for block timeout, "r" for return timeout. (default: b) |
437 | * the time any IO operation on sock can cause the program to block. | ||
438 | * "return" specifies the upper bound on the time elapsed before the | ||
439 | * function returns control to the script. "block" is the default. | ||
440 | \*-------------------------------------------------------------------------*/ | 467 | \*-------------------------------------------------------------------------*/ |
441 | static int table_timeout(lua_State *L) | 468 | static int table_timeout(lua_State *L) |
442 | { | 469 | { |
443 | p_sock sock = pop_sock(L); | 470 | p_sock sock = pop_sock(L); |
444 | int ms = (int) (luaL_check_number(L, 2)*1000.0); | 471 | int ms = lua_isnil(L, 2) ? -1 : (int) (luaL_check_number(L, 2)*1000.0); |
445 | const char *mode = luaL_opt_string(L, 3, "b"); | 472 | const char *mode = luaL_opt_string(L, 3, "b"); |
446 | switch (*mode) { | 473 | switch (*mode) { |
447 | case 'b': | 474 | case 'b': |
448 | sock->tm_block = ms; | 475 | sock->tm_block = ms; |
449 | break; | 476 | break; |
450 | case 'r': | 477 | case 'r': |
451 | sock->tm_return = ms; | 478 | sock->tm_return = ms; |
452 | break; | 479 | break; |
453 | default: | 480 | default: |
454 | luaL_arg_check(L, 0, 3, "invalid timeout mode"); | 481 | luaL_arg_check(L, 0, 3, "invalid timeout mode"); |
455 | break; | 482 | break; |
456 | } | 483 | } |
457 | return 0; | 484 | return 0; |
458 | } | 485 | } |
459 | 486 | ||
460 | /*-------------------------------------------------------------------------*\ | 487 | /*-------------------------------------------------------------------------*\ |
461 | * Send data through a socket | 488 | * Send data through a TCP socket |
462 | * Lua Input: sock, a_1 [, a_2, a_3 ... a_n] | 489 | * Lua Input: sock, a_1 [, a_2, a_3 ... a_n] |
463 | * sock: client socket created by the connect function | 490 | * sock: client socket created by the connect function |
464 | * a_i: strings to be sent. The strings will be sent on the order they | 491 | * a_i: strings to be sent. The strings will be sent on the order they |
465 | * appear as parameters | 492 | * appear as parameters |
466 | * Lua Returns | 493 | * Lua Returns |
467 | * On success: nil, followed by the total number of bytes sent | 494 | * On success: nil, followed by the total number of bytes sent |
468 | * On error: NET_TIMEOUT if the connection timedout, or NET_CLOSED if | 495 | * On error: error message |
469 | * the connection has been closed, followed by the total number of | ||
470 | * bytes sent | ||
471 | \*-------------------------------------------------------------------------*/ | 496 | \*-------------------------------------------------------------------------*/ |
472 | static int table_send(lua_State *L) | 497 | static int table_tcpsend(lua_State *L) |
473 | { | 498 | { |
474 | int arg; | 499 | int arg; |
475 | p_sock sock = pop_sock(L); | 500 | p_sock sock = pop_sock(L); |
476 | int top = lua_gettop(L); | 501 | int top = lua_gettop(L); |
477 | int total = 0; | 502 | int total = 0; |
478 | int err = NET_DONE; | 503 | int err = NET_DONE; |
479 | tm_markstart(sock); | 504 | tm_markstart(sock); |
480 | for (arg = 2; arg <= top; arg++) { /* skip self table */ | 505 | for (arg = 2; arg <= top; arg++) { /* skip self table */ |
481 | int sent, wanted; | 506 | int sent; |
482 | const char *data = luaL_opt_lstr(L, arg, NULL, &wanted); | 507 | size_t wanted; |
483 | if (!data || err != NET_DONE) break; | 508 | const char *data = luaL_opt_lstr(L, arg, NULL, &wanted); |
484 | err = send_raw(sock, data, wanted, &sent); | 509 | if (!data || err != NET_DONE) break; |
485 | total += sent; | 510 | err = send_raw(sock, data, wanted, &sent); |
486 | } | 511 | total += sent; |
487 | push_error(L, err); | 512 | } |
488 | lua_pushnumber(L, (double) total); | 513 | push_error(L, err); |
514 | lua_pushnumber(L, total); | ||
489 | #ifdef _DEBUG | 515 | #ifdef _DEBUG |
490 | /* push time elapsed during operation as the last return value */ | 516 | /* push time elapsed during operation as the last return value */ |
491 | lua_pushnumber(L, (sock->tm_end - sock->tm_start)/1000.0); | 517 | lua_pushnumber(L, (sock->tm_end - sock->tm_start)/1000.0); |
492 | #endif | 518 | #endif |
493 | return lua_gettop(L) - top; | 519 | return lua_gettop(L) - top; |
520 | } | ||
521 | |||
522 | /*-------------------------------------------------------------------------*\ | ||
523 | * Send data through a unconnected UDP socket | ||
524 | * Lua Input: sock, data, ip, port | ||
525 | * sock: udp socket | ||
526 | * data: data to be sent | ||
527 | * ip: ip address of target | ||
528 | * port: port in target | ||
529 | * Lua Returns | ||
530 | * On success: nil, followed by the total number of bytes sent | ||
531 | * On error: error message | ||
532 | \*-------------------------------------------------------------------------*/ | ||
533 | static int table_udpsendto(lua_State *L) | ||
534 | { | ||
535 | p_sock sock = pop_sock(L); | ||
536 | size_t wanted; | ||
537 | const char *data = luaL_check_lstr(L, 2, &wanted); | ||
538 | const char *ip = luaL_check_string(L, 3); | ||
539 | unsigned short port = (unsigned short) luaL_check_number(L, 4); | ||
540 | struct sockaddr_in peer; | ||
541 | int sent; | ||
542 | if (sock->is_connected) lua_error(L, "sendto on connected socket"); | ||
543 | tm_markstart(sock); | ||
544 | if (tm_timedout(sock, TM_SEND)) { | ||
545 | push_error(L, NET_TIMEOUT); | ||
546 | return 1; | ||
547 | } | ||
548 | memset(&peer, 0, sizeof(peer)); | ||
549 | peer.sin_family = AF_INET; | ||
550 | peer.sin_port = htons(port); | ||
551 | if (!inet_aton(ip, &peer.sin_addr)) lua_error(L, "invalid ip address"); | ||
552 | sent = sendto(sock->sock, data, wanted, 0, (SA *) &peer, sizeof(peer)); | ||
553 | if (sent >= 0) { | ||
554 | lua_pushnil(L); | ||
555 | lua_pushnumber(L, sent); | ||
556 | return 2; | ||
557 | } else { | ||
558 | push_error(L, NET_REFUSED); | ||
559 | return 1; | ||
560 | } | ||
561 | } | ||
562 | |||
563 | /*-------------------------------------------------------------------------*\ | ||
564 | * Returns the list of ip addresses associated with a host name | ||
565 | * Lua Input: address | ||
566 | * address: ip address or hostname to dns lookup | ||
567 | * Lua Returns | ||
568 | * On success: first IP address followed by a resolved table | ||
569 | * On error: nil, followed by an error message | ||
570 | \*-------------------------------------------------------------------------*/ | ||
571 | static int global_toip(lua_State *L) | ||
572 | { | ||
573 | const char *address = luaL_check_string(L, 1); | ||
574 | struct in_addr addr; | ||
575 | struct hostent *hp; | ||
576 | if (inet_aton(address, &addr)) | ||
577 | hp = gethostbyaddr((char *) &addr, sizeof(addr), AF_INET); | ||
578 | else hp = gethostbyname(address); | ||
579 | if (!hp) { | ||
580 | lua_pushnil(L); | ||
581 | lua_pushstring(L, host_strerror()); | ||
582 | return 2; | ||
583 | } | ||
584 | addr = *((struct in_addr *) hp->h_addr); | ||
585 | lua_pushstring(L, inet_ntoa(addr)); | ||
586 | push_resolved(L, hp); | ||
587 | return 2; | ||
588 | } | ||
589 | |||
590 | /*-------------------------------------------------------------------------*\ | ||
591 | * Returns the list of host names associated with an ip address | ||
592 | * Lua Input: address | ||
593 | * address: ip address or host name to reverse dns lookup | ||
594 | * Lua Returns | ||
595 | * On success: canonic name followed by a resolved table | ||
596 | * On error: nil, followed by an error message | ||
597 | \*-------------------------------------------------------------------------*/ | ||
598 | static int global_tohostname(lua_State *L) | ||
599 | { | ||
600 | const char *address = luaL_check_string(L, 1); | ||
601 | struct in_addr addr; | ||
602 | struct hostent *hp; | ||
603 | if (inet_aton(address, &addr)) | ||
604 | hp = gethostbyaddr((char *) &addr, sizeof(addr), AF_INET); | ||
605 | else hp = gethostbyname(address); | ||
606 | if (!hp) { | ||
607 | lua_pushnil(L); | ||
608 | lua_pushstring(L, host_strerror()); | ||
609 | return 2; | ||
610 | } | ||
611 | lua_pushstring(L, hp->h_name); | ||
612 | push_resolved(L, hp); | ||
613 | return 2; | ||
614 | } | ||
615 | |||
616 | /*-------------------------------------------------------------------------*\ | ||
617 | * Send data through a connected UDP socket | ||
618 | * Lua Input: sock, data | ||
619 | * sock: udp socket | ||
620 | * data: data to be sent | ||
621 | * Lua Returns | ||
622 | * On success: nil, followed by the total number of bytes sent | ||
623 | * On error: error message | ||
624 | \*-------------------------------------------------------------------------*/ | ||
625 | static int table_udpsend(lua_State *L) | ||
626 | { | ||
627 | p_sock sock = pop_sock(L); | ||
628 | size_t wanted; | ||
629 | int sent; | ||
630 | const char *data = luaL_check_lstr(L, 2, &wanted); | ||
631 | if (!sock->is_connected) lua_error(L, "send on unconnected socket"); | ||
632 | tm_markstart(sock); | ||
633 | if (tm_timedout(sock, TM_SEND)) { | ||
634 | push_error(L, NET_TIMEOUT); | ||
635 | return 1; | ||
636 | } | ||
637 | sent = send(sock->sock, data, wanted, 0); | ||
638 | if (sent >= 0) { | ||
639 | lua_pushnil(L); | ||
640 | lua_pushnumber(L, sent); | ||
641 | return 2; | ||
642 | } else { | ||
643 | push_error(L, NET_REFUSED); | ||
644 | return 1; | ||
645 | } | ||
646 | } | ||
647 | |||
648 | /*-------------------------------------------------------------------------*\ | ||
649 | * Receives a datagram from a UDP socket | ||
650 | * Lua Input: sock [, wanted] | ||
651 | * sock: client socket created by the connect function | ||
652 | * wanted: the number of bytes expected (default: UDPMAX) | ||
653 | * Lua Returns | ||
654 | * On success: datagram received, ip and port of sender | ||
655 | * On error: nil, followed by an error message | ||
656 | \*-------------------------------------------------------------------------*/ | ||
657 | static int table_udpreceivefrom(lua_State *L) | ||
658 | { | ||
659 | p_sock sock = pop_sock(L); | ||
660 | size_t wanted = (int) luaL_opt_number(L, 2, UDPMAX); | ||
661 | struct sockaddr_in peer; | ||
662 | size_t peer_len = sizeof(peer); | ||
663 | unsigned char buffer[UDPMAX]; | ||
664 | int got; | ||
665 | if (sock->is_connected) lua_error(L, "receivefrom on connected socket"); | ||
666 | tm_markstart(sock); | ||
667 | if (tm_timedout(sock, TM_RECEIVE)) { | ||
668 | lua_pushnil(L); | ||
669 | push_error(L, NET_TIMEOUT); | ||
670 | return 2; | ||
671 | } | ||
672 | wanted = min(wanted, sizeof(buffer)); | ||
673 | got = recvfrom(sock->sock, buffer, wanted, 0, (SA *) &peer, &peer_len); | ||
674 | if (got >= 0) { | ||
675 | lua_pushlstring(L, buffer, got); | ||
676 | lua_pushstring(L, inet_ntoa(peer.sin_addr)); | ||
677 | lua_pushnumber(L, ntohs(peer.sin_port)); | ||
678 | return 3; | ||
679 | } else { | ||
680 | lua_pushnil(L); | ||
681 | push_error(L, NET_REFUSED); | ||
682 | return 2; | ||
683 | } | ||
494 | } | 684 | } |
495 | 685 | ||
496 | /*-------------------------------------------------------------------------*\ | 686 | /*-------------------------------------------------------------------------*\ |
497 | * Receive data from a socket | 687 | * Receives data from a UDP socket |
688 | * Lua Input: sock [, wanted] | ||
689 | * sock: client socket created by the connect function | ||
690 | * wanted: the number of bytes expected (default: UDPMAX) | ||
691 | * Lua Returns | ||
692 | * On success: datagram received | ||
693 | * On error: nil, followed by an error message | ||
694 | \*-------------------------------------------------------------------------*/ | ||
695 | static int table_udpreceive(lua_State *L) | ||
696 | { | ||
697 | p_sock sock = pop_sock(L); | ||
698 | size_t wanted = (size_t) luaL_opt_number(L, 2, UDPMAX); | ||
699 | unsigned char buffer[UDPMAX]; | ||
700 | int got; | ||
701 | tm_markstart(sock); | ||
702 | if (tm_timedout(sock, TM_RECEIVE)) { | ||
703 | lua_pushnil(L); | ||
704 | push_error(L, NET_TIMEOUT); | ||
705 | return 2; | ||
706 | } | ||
707 | got = recv(sock->sock, buffer, min(wanted, sizeof(buffer)), 0); | ||
708 | if (got >= 0) { | ||
709 | lua_pushlstring(L, buffer, got); | ||
710 | return 1; | ||
711 | } else { | ||
712 | lua_pushnil(L); | ||
713 | push_error(L, NET_REFUSED); | ||
714 | return 2; | ||
715 | } | ||
716 | } | ||
717 | |||
718 | /*-------------------------------------------------------------------------*\ | ||
719 | * Receive data from a TCP socket | ||
498 | * Lua Input: sock [pat_1, pat_2 ... pat_n] | 720 | * Lua Input: sock [pat_1, pat_2 ... pat_n] |
499 | * sock: client socket created by the connect function | 721 | * sock: client socket created by the connect function |
500 | * pat_i: may be one of the following | 722 | * pat_i: may be one of the following |
@@ -509,60 +731,106 @@ static int table_send(lua_State *L) | |||
509 | * On error: all strings for which there was no error, followed by one | 731 | * On error: all strings for which there was no error, followed by one |
510 | * nil value for the remaining strings, followed by an error code | 732 | * nil value for the remaining strings, followed by an error code |
511 | \*-------------------------------------------------------------------------*/ | 733 | \*-------------------------------------------------------------------------*/ |
512 | static int table_receive(lua_State *L) | 734 | static int table_tcpreceive(lua_State *L) |
513 | { | 735 | { |
514 | static const char *const modenames[] = {"*l", "*lu", "*a", NULL}; | 736 | static const char *const modenames[] = {"*l", "*lu", "*a", NULL}; |
515 | const char *mode; | 737 | const char *mode; |
516 | int err = NET_DONE; | 738 | int err = NET_DONE; |
517 | int arg; | 739 | int arg; |
518 | p_sock sock = pop_sock(L); | 740 | p_sock sock = pop_sock(L); |
519 | int top = lua_gettop(L); | 741 | int top = lua_gettop(L); |
520 | tm_markstart(sock); | 742 | tm_markstart(sock); |
521 | /* push default pattern if need be */ | 743 | /* push default pattern if need be */ |
522 | if (top < 2) { | 744 | if (top < 2) { |
523 | lua_pushstring(L, "*l"); | 745 | lua_pushstring(L, "*l"); |
524 | top++; | 746 | top++; |
525 | } | 747 | } |
526 | /* receive all patterns */ | 748 | /* make sure we have enough stack space */ |
527 | for (arg = 2; arg <= top; arg++) { | 749 | luaL_checkstack(L, top+LUA_MINSTACK, "too many arguments"); |
528 | /* if one pattern failed, we just skip all other patterns */ | 750 | /* receive all patterns */ |
529 | if (err != NET_DONE) { | 751 | for (arg = 2; arg <= top; arg++) { |
530 | lua_pushnil(L); | 752 | /* if one pattern failed, we just skip all other patterns */ |
531 | continue; | 753 | if (err != NET_DONE) { |
532 | } | 754 | lua_pushnil(L); |
533 | if (lua_isnumber(L, arg)) { | 755 | continue; |
534 | int size = (int) lua_tonumber(L, arg); | 756 | } |
535 | err = receive_raw(L, sock, size); | 757 | if (lua_isnumber(L, arg)) { |
536 | } else { | 758 | int size = (int) lua_tonumber(L, arg); |
537 | mode = luaL_opt_string(L, arg, NULL); | 759 | err = receive_raw(L, sock, size); |
538 | /* get next pattern */ | 760 | } else { |
539 | switch (luaL_findstring(mode, modenames)) { | 761 | mode = luaL_opt_string(L, arg, NULL); |
540 | /* DOS line mode */ | 762 | /* get next pattern */ |
541 | case 0: | 763 | switch (luaL_findstring(mode, modenames)) { |
542 | err = receive_dosline(L, sock); | 764 | /* DOS line mode */ |
543 | break; | 765 | case 0: |
544 | /* Unix line mode */ | 766 | err = receive_dosline(L, sock); |
545 | case 1: | 767 | break; |
546 | err = receive_unixline(L, sock); | 768 | /* Unix line mode */ |
547 | break; | 769 | case 1: |
548 | /* until closed mode */ | 770 | err = receive_unixline(L, sock); |
549 | case 2: | 771 | break; |
550 | err = receive_all(L, sock); | 772 | /* until closed mode */ |
551 | break; | 773 | case 2: |
552 | /* else it is an error */ | 774 | err = receive_all(L, sock); |
553 | default: | 775 | break; |
554 | luaL_arg_check(L, 0, arg, "invalid receive pattern"); | 776 | /* else it is an error */ |
555 | break; | 777 | default: |
556 | } | 778 | luaL_arg_check(L, 0, arg, "invalid receive pattern"); |
557 | } | 779 | break; |
558 | } | 780 | } |
559 | /* last return is an error code */ | 781 | } |
560 | push_error(L, err); | 782 | } |
783 | /* last return is an error code */ | ||
784 | push_error(L, err); | ||
561 | #ifdef _DEBUG | 785 | #ifdef _DEBUG |
562 | /* push time elapsed during operation as the last return value */ | 786 | /* push time elapsed during operation as the last return value */ |
563 | lua_pushnumber(L, (sock->tm_end - sock->tm_start)/1000.0); | 787 | lua_pushnumber(L, (sock->tm_end - sock->tm_start)/1000.0); |
564 | #endif | 788 | #endif |
565 | return lua_gettop(L) - top; | 789 | return lua_gettop(L) - top; |
790 | } | ||
791 | |||
792 | /*-------------------------------------------------------------------------*\ | ||
793 | * Retrieves socket peer name | ||
794 | * Lua Input: sock | ||
795 | * sock: socket | ||
796 | * Lua Returns | ||
797 | * On success: ip address and port of peer | ||
798 | * On error: nil | ||
799 | \*-------------------------------------------------------------------------*/ | ||
800 | static int table_getpeername(lua_State *L) | ||
801 | { | ||
802 | p_sock sock = pop_sock(L); | ||
803 | struct sockaddr_in peer; | ||
804 | size_t peer_len = sizeof(peer); | ||
805 | if (getpeername(sock->sock, (SA *) &peer, &peer_len) < 0) { | ||
806 | lua_pushnil(L); | ||
807 | return 1; | ||
808 | } | ||
809 | lua_pushstring(L, inet_ntoa(peer.sin_addr)); | ||
810 | lua_pushnumber(L, ntohs(peer.sin_port)); | ||
811 | return 2; | ||
812 | } | ||
813 | |||
814 | /*-------------------------------------------------------------------------*\ | ||
815 | * Retrieves socket local name | ||
816 | * Lua Input: sock | ||
817 | * sock: socket | ||
818 | * Lua Returns | ||
819 | * On success: local ip address and port | ||
820 | * On error: nil | ||
821 | \*-------------------------------------------------------------------------*/ | ||
822 | static int table_getsockname(lua_State *L) | ||
823 | { | ||
824 | p_sock sock = pop_sock(L); | ||
825 | struct sockaddr_in local; | ||
826 | size_t local_len = sizeof(local); | ||
827 | if (getsockname(sock->sock, (SA *) &local, &local_len) < 0) { | ||
828 | lua_pushnil(L); | ||
829 | return 1; | ||
830 | } | ||
831 | lua_pushstring(L, inet_ntoa(local.sin_addr)); | ||
832 | lua_pushnumber(L, ntohs(local.sin_port)); | ||
833 | return 2; | ||
566 | } | 834 | } |
567 | 835 | ||
568 | /*-------------------------------------------------------------------------*\ | 836 | /*-------------------------------------------------------------------------*\ |
@@ -572,25 +840,68 @@ static int table_receive(lua_State *L) | |||
572 | \*-------------------------------------------------------------------------*/ | 840 | \*-------------------------------------------------------------------------*/ |
573 | static int table_close(lua_State *L) | 841 | static int table_close(lua_State *L) |
574 | { | 842 | { |
575 | /* close socket and set value to -1 so that pop_socket can later | 843 | /* close socket and set value to INVALID_SOCKET so that |
576 | ** detect the use of a closed socket */ | 844 | ** pop_socket can later detect the use of a closed socket */ |
577 | p_sock sock = pop_sock(L); | 845 | p_sock sock = pop_sock(L); |
578 | closesocket(sock->sock); | 846 | closesocket(sock->sock); |
579 | sock->sock = -1; | 847 | sock->sock = INVALID_SOCKET; |
580 | return 0; | 848 | return 0; |
849 | } | ||
850 | |||
851 | /*-------------------------------------------------------------------------*\ | ||
852 | * Tests if we can immediately read or write on a socket | ||
853 | * Lua Input | ||
854 | * sock: socket to be closed | ||
855 | * operation: operation to query "*r", "*s" | ||
856 | * Lua Returns | ||
857 | * 1 if operation will be accepted, nil otherwise | ||
858 | \*-------------------------------------------------------------------------*/ | ||
859 | static int table_poll(lua_State *L) | ||
860 | { | ||
861 | p_sock sock = pop_sock(L); | ||
862 | const char *op = luaL_check_string(L, 2); | ||
863 | int tm_block = sock->tm_block; | ||
864 | int tm_return = sock->tm_return; | ||
865 | if (!*op || *op != '*') lua_error(L, "invalid poll pattern"); | ||
866 | op++; | ||
867 | tm_markstart(sock); | ||
868 | switch (*op) { | ||
869 | case 'r': | ||
870 | sock->tm_block = sock->tm_return = 0; | ||
871 | if (bf_isempty(sock) && tm_timedout(sock, TM_RECEIVE)) | ||
872 | lua_pushnil(L); | ||
873 | else lua_pushnumber(L, 1); | ||
874 | sock->tm_block = tm_block; | ||
875 | sock->tm_return = tm_return; | ||
876 | break; | ||
877 | case 's': | ||
878 | sock->tm_block = sock->tm_return = 0; | ||
879 | if (tm_timedout(sock, TM_SEND)) lua_pushnil(L); | ||
880 | else lua_pushnumber(L, 1); | ||
881 | sock->tm_block = tm_block; | ||
882 | sock->tm_return = tm_return; | ||
883 | break; | ||
884 | default: | ||
885 | lua_error(L, "invalid poll pattern"); | ||
886 | break; | ||
887 | } | ||
888 | return 1; | ||
581 | } | 889 | } |
582 | 890 | ||
583 | /*-------------------------------------------------------------------------*\ | 891 | /*-------------------------------------------------------------------------*\ |
584 | * Garbage collection fallback for the socket objects. This function | 892 | * Garbage collection fallback for the socket objects. This function |
585 | * makes sure that all collected sockets are closed. | 893 | * makes sure that all collected sockets are closed. |
586 | \*-------------------------------------------------------------------------*/ | 894 | \*-------------------------------------------------------------------------*/ |
587 | static int gc_sock(lua_State *L) | 895 | static int gc_table(lua_State *L) |
588 | { | 896 | { |
589 | p_tags tags = pop_tags(L); | 897 | p_tags tags = pop_tags(L); |
590 | p_sock sock = get_selfsock(L, tags); | 898 | p_sock sock = get_selfsock(L, tags, NULL); |
591 | /* sock might have been closed */ | 899 | /* sock might have been closed before */ |
592 | if (sock->sock >= 0) closesocket(sock->sock); | 900 | if (sock->sock != INVALID_SOCKET) { |
593 | return 0; | 901 | closesocket(sock->sock); |
902 | sock->sock = INVALID_SOCKET; | ||
903 | } | ||
904 | return 0; | ||
594 | } | 905 | } |
595 | 906 | ||
596 | /*=========================================================================*\ | 907 | /*=========================================================================*\ |
@@ -605,150 +916,210 @@ static int gc_sock(lua_State *L) | |||
605 | static void handle_sigpipe(void); | 916 | static void handle_sigpipe(void); |
606 | static void handle_sigpipe(void) | 917 | static void handle_sigpipe(void) |
607 | { | 918 | { |
608 | struct sigaction new; | 919 | struct sigaction new; |
609 | memset(&new, 0, sizeof(new)); | 920 | memset(&new, 0, sizeof(new)); |
610 | new.sa_handler = SIG_IGN; | 921 | new.sa_handler = SIG_IGN; |
611 | sigaction(SIGPIPE, &new, NULL); | 922 | sigaction(SIGPIPE, &new, NULL); |
612 | } | 923 | } |
613 | #endif | 924 | #endif |
614 | 925 | ||
615 | /*-------------------------------------------------------------------------*\ | 926 | /*-------------------------------------------------------------------------*\ |
616 | * Creates a TCP/IP socket. | 927 | * Tries to create a TCP socket and connect to remote address (address, port) |
617 | * Input | 928 | * Input |
618 | * sock: structure to receive new socket | 929 | * address: host name or ip address |
930 | * port: port number to bind to | ||
619 | * Returns | 931 | * Returns |
620 | * 1 if successfull, 0 in case or error | 932 | * NULL in case of success, error message otherwise |
621 | \*-------------------------------------------------------------------------*/ | 933 | \*-------------------------------------------------------------------------*/ |
622 | static int create_tcpsocket(p_sock sock) | 934 | const char *tcp_tryconnect(p_sock sock, const char *address, |
623 | { | 935 | unsigned short port) |
624 | sock->sock = socket(AF_INET, SOCK_STREAM, 0); | ||
625 | if (sock->sock < 0) return 0; | ||
626 | #ifdef _DEBUG | ||
627 | /* this allow us to re-bind onto an address even if there is still | ||
628 | ** a TIME_WAIT condition. debugging is much more confortable, because | ||
629 | ** we don't get "address already in use" errors all the time we | ||
630 | ** re-run the program before the OS is ready. in real life, though | ||
631 | ** there could be data pending on the socket and this could lead to | ||
632 | ** some weird errors. */ | ||
633 | { | 936 | { |
634 | int val = 1; | 937 | struct sockaddr_in remote; |
635 | setsockopt(sock->sock, SOL_SOCKET, SO_REUSEADDR, (char *) &val, | 938 | memset(&remote, 0, sizeof(remote)); |
636 | sizeof(val)); | 939 | if (inet_aton(address, &remote.sin_addr)) { |
940 | remote.sin_family = AF_INET; | ||
941 | remote.sin_port = htons(port); | ||
942 | sock->sock = socket(AF_INET, SOCK_STREAM, 0); | ||
943 | if (sock->sock == INVALID_SOCKET) return socket_strerror(); | ||
944 | if (connect(sock->sock, (SA *) &remote, sizeof(remote)) < 0) { | ||
945 | closesocket(sock->sock); | ||
946 | sock->sock = INVALID_SOCKET; | ||
947 | return connect_strerror(); | ||
948 | } | ||
949 | /* go ahead and try by hostname resolution */ | ||
950 | } else { | ||
951 | struct hostent *hp = gethostbyname(address); | ||
952 | struct in_addr **addr; | ||
953 | if (!hp) return host_strerror(); | ||
954 | addr = (struct in_addr **) hp->h_addr_list; | ||
955 | for (; *addr != NULL; addr++) { | ||
956 | memcpy(&remote.sin_addr, *addr, sizeof(struct in_addr)); | ||
957 | remote.sin_family = AF_INET; | ||
958 | remote.sin_port = htons(port); | ||
959 | sock->sock = socket(AF_INET, SOCK_STREAM, 0); | ||
960 | if (sock->sock == INVALID_SOCKET) return socket_strerror(); | ||
961 | if (connect(sock->sock, (SA *) &remote, sizeof(remote)) == 0) | ||
962 | break; | ||
963 | closesocket(sock->sock); | ||
964 | sock->sock = INVALID_SOCKET; | ||
965 | memset(&remote, 0, sizeof(remote)); | ||
966 | } | ||
967 | } | ||
968 | if (sock->sock == INVALID_SOCKET) return connect_strerror(); | ||
969 | return NULL; | ||
637 | } | 970 | } |
638 | #endif | 971 | |
639 | return 1; | 972 | /*-------------------------------------------------------------------------*\ |
973 | * Sets the SO_REUSEADDR socket option | ||
974 | * Input | ||
975 | * sock: socket to set option | ||
976 | \*-------------------------------------------------------------------------*/ | ||
977 | void set_reuseaddr(p_sock sock) | ||
978 | { | ||
979 | int val = 1; | ||
980 | setsockopt(sock->sock, SOL_SOCKET, SO_REUSEADDR, (char *)&val, sizeof(val)); | ||
640 | } | 981 | } |
641 | 982 | ||
642 | /*-------------------------------------------------------------------------*\ | 983 | /*-------------------------------------------------------------------------*\ |
643 | * Fills a sockaddr structure according to a given host name of ip | 984 | * Tries to create a TCP socket and bind it to (address, port) |
644 | * address and a port number. | ||
645 | * Input | 985 | * Input |
646 | * address: pointer to sockaddr structure to be filled | 986 | * address: host name or ip address |
647 | * hostname: host name or ip address | 987 | * port: port number to bind to |
648 | * port: port number | 988 | * backlog: backlog to set |
649 | * Returns | 989 | * Returns |
650 | * 1 in case of success, 0 otherwise | 990 | * NULL in case of success, error message otherwise |
651 | \*-------------------------------------------------------------------------*/ | 991 | \*-------------------------------------------------------------------------*/ |
652 | static int fill_sockaddr(struct sockaddr_in *address, const char *hostname, | 992 | const char *tcp_trybind(p_sock sock, const char *address, |
653 | unsigned short port) | 993 | unsigned short port, int backlog) |
654 | { | 994 | { |
655 | struct hostent *host = NULL; | 995 | struct sockaddr_in local; |
656 | unsigned long addr = inet_addr(hostname); | 996 | memset(&local, 0, sizeof(local)); |
657 | memset(address, 0, sizeof(struct sockaddr_in)); | 997 | local.sin_port = htons(port); |
658 | if (strcmp(hostname, "*")) { | 998 | local.sin_family = AF_INET; |
659 | /* BSD says we could have used gethostbyname even if the hostname is | 999 | local.sin_addr.s_addr = htonl(INADDR_ANY); |
660 | ** in ip address form, but WinSock2 says we can't. Therefore we | 1000 | sock->sock = socket(AF_INET, SOCK_STREAM, 0); |
661 | ** choose a method that works on both plataforms */ | 1001 | if (sock->sock == INVALID_SOCKET) return socket_strerror(); |
662 | if (addr == INADDR_NONE) host = gethostbyname(hostname); | 1002 | set_reuseaddr(sock); |
663 | else host = gethostbyaddr((char * ) &addr, sizeof(unsigned long), | 1003 | /* address is either wildcard or a valid ip address */ |
664 | AF_INET); | 1004 | if (!strcmp(address, "*") || inet_aton(address, &local.sin_addr)) { |
665 | if (!host) | 1005 | if (bind(sock->sock, (SA *) &local, sizeof(local)) < 0) { |
666 | return 0; | 1006 | closesocket(sock->sock); |
667 | memcpy(&(address->sin_addr), host->h_addr, (unsigned) host->h_length); | 1007 | sock->sock = INVALID_SOCKET; |
668 | } else { | 1008 | return bind_strerror(); |
669 | address->sin_addr.s_addr = htonl(INADDR_ANY); | 1009 | } |
670 | } | 1010 | /* otherwise, proceed with domain name resolution */ |
671 | address->sin_family = AF_INET; | 1011 | } else { |
672 | address->sin_port = htons(port); | 1012 | struct hostent *hp = gethostbyname(address); |
673 | return 1; | 1013 | struct in_addr **addr; |
1014 | if (!hp) return host_strerror(); | ||
1015 | addr = (struct in_addr **) hp->h_addr_list; | ||
1016 | for (; *addr != NULL; addr++) { | ||
1017 | memcpy(&local.sin_addr, *addr, sizeof(struct in_addr)); | ||
1018 | if (bind(sock->sock, (SA *) &local, sizeof(local)) < 0) { | ||
1019 | closesocket(sock->sock); | ||
1020 | sock->sock = socket(AF_INET, SOCK_DGRAM, 0); | ||
1021 | if (sock->sock == INVALID_SOCKET) return socket_strerror(); | ||
1022 | set_reuseaddr(sock); | ||
1023 | } else break; | ||
1024 | } | ||
1025 | if (*addr == NULL) return bind_strerror(); | ||
1026 | } | ||
1027 | /* set connection queue length */ | ||
1028 | if (listen(sock->sock, backlog) < 0) { | ||
1029 | closesocket(sock->sock); | ||
1030 | sock->sock = INVALID_SOCKET; | ||
1031 | return "listen error"; | ||
1032 | } | ||
1033 | /* no errors found */ | ||
1034 | return NULL; | ||
674 | } | 1035 | } |
675 | 1036 | ||
676 | /*-------------------------------------------------------------------------*\ | 1037 | /*-------------------------------------------------------------------------*\ |
677 | * Creates a t_sock structure with default values for a client sock. | 1038 | * Tries to bind the UDP socket to (address, port) |
678 | * Pushes the Lua table with sock fields and appropriate methods | ||
679 | * Input | 1039 | * Input |
680 | * tags: tags structure | 1040 | * address: host name or ip address |
1041 | * port: port number to bind to | ||
681 | * Returns | 1042 | * Returns |
682 | * pointer to allocated t_sock structure, NULL in case of error | 1043 | * NULL in case of success, error message otherwise |
683 | \*-------------------------------------------------------------------------*/ | 1044 | \*-------------------------------------------------------------------------*/ |
684 | static p_sock push_clienttable(lua_State *L, p_tags tags) | 1045 | const char *udp_setsockname(p_sock sock, const char *address, |
1046 | unsigned short port) | ||
685 | { | 1047 | { |
686 | static struct luaL_reg funcs[] = { | 1048 | struct sockaddr_in local; |
687 | {"send", table_send}, | 1049 | memset(&local, 0, sizeof(local)); |
688 | {"receive", table_receive}, | 1050 | local.sin_port = htons(port); |
689 | {"close", table_close}, | 1051 | local.sin_family = AF_INET; |
690 | {"timeout", table_timeout}, | 1052 | local.sin_addr.s_addr = htonl(INADDR_ANY); |
691 | }; | 1053 | set_reuseaddr(sock); |
692 | int i; | 1054 | /* address is either wildcard or a valid ip address */ |
693 | p_sock sock; | 1055 | if (!strcmp(address, "*") || inet_aton(address, &local.sin_addr)) { |
694 | lua_newtable(L); lua_settag(L, tags->table); | 1056 | if (bind(sock->sock, (SA *) &local, sizeof(local)) < 0) { |
695 | lua_pushstring(L, P_SOCK); | 1057 | closesocket(sock->sock); |
696 | sock = (p_sock) lua_newuserdata(L, sizeof(t_sock)); | 1058 | sock->sock = INVALID_SOCKET; |
697 | if (!sock) lua_error(L, "out of memory"); | 1059 | return bind_strerror(); |
698 | lua_settag(L, tags->client); | 1060 | } |
699 | lua_settable(L, -3); | 1061 | /* otherwise, proceed with domain name resolution */ |
700 | sock->sock = -1; | 1062 | } else { |
701 | sock->tm_block = -1; | 1063 | struct hostent *hp = gethostbyname(address); |
702 | sock->tm_return = -1; | 1064 | struct in_addr **addr; |
703 | sock->bf_first = sock->bf_last = 0; | 1065 | if (!hp) return host_strerror(); |
704 | for (i = 0; i < sizeof(funcs)/sizeof(funcs[0]); i++) { | 1066 | addr = (struct in_addr **) hp->h_addr_list; |
705 | lua_pushstring(L, funcs[i].name); | 1067 | for (; *addr != NULL; addr++) { |
706 | lua_pushusertag(L, sock, tags->client); | 1068 | memcpy(&local.sin_addr, *addr, sizeof(struct in_addr)); |
707 | lua_pushcclosure(L, funcs[i].func, 1); | 1069 | if (bind(sock->sock, (SA *) &local, sizeof(local)) < 0) { |
708 | lua_settable(L, -3); | 1070 | closesocket(sock->sock); |
709 | } | 1071 | sock->sock = socket(AF_INET, SOCK_DGRAM, 0); |
710 | return sock; | 1072 | if (sock->sock == INVALID_SOCKET) return socket_strerror(); |
1073 | set_reuseaddr(sock); | ||
1074 | } else break; | ||
1075 | } | ||
1076 | if (*addr == NULL) return bind_strerror(); | ||
1077 | } | ||
1078 | /* no errors found */ | ||
1079 | return NULL; | ||
711 | } | 1080 | } |
712 | 1081 | ||
713 | /*-------------------------------------------------------------------------*\ | 1082 | /*-------------------------------------------------------------------------*\ |
714 | * Creates a t_sock structure with default values for a server sock. | 1083 | * Tries to connect a UDP to remote address (address, port) |
715 | * Pushes the Lua table with sock fields and appropriate methods | ||
716 | * Input | 1084 | * Input |
717 | * tags: tags structure | 1085 | * address: host name or ip address |
1086 | * port: port number to bind to | ||
718 | * Returns | 1087 | * Returns |
719 | * pointer to allocated t_sock structure, NULL in case of error | 1088 | * NULL in case of success, error message otherwise |
720 | \*-------------------------------------------------------------------------*/ | 1089 | \*-------------------------------------------------------------------------*/ |
721 | static p_sock push_servertable(lua_State *L, p_tags tags) | 1090 | const char *udp_setpeername(p_sock sock, const char *address, |
1091 | unsigned short port) | ||
722 | { | 1092 | { |
723 | static struct luaL_reg funcs[] = { | 1093 | struct sockaddr_in local; |
724 | {"listen", table_listen}, | 1094 | memset(&local, 0, sizeof(local)); |
725 | {"close", table_close}, | 1095 | local.sin_port = htons(port); |
726 | }; | 1096 | local.sin_family = AF_INET; |
727 | int i; | 1097 | local.sin_addr.s_addr = htonl(INADDR_ANY); |
728 | p_sock sock; | 1098 | /* address is a valid ip address */ |
729 | lua_newtable(L); lua_settag(L, tags->table); | 1099 | if (inet_aton(address, &local.sin_addr)) { |
730 | lua_pushstring(L, P_SOCK); | 1100 | if (connect(sock->sock, (SA *) &local, sizeof(local)) < 0) { |
731 | sock = (p_sock) lua_newuserdata(L, sizeof(t_sock)); | 1101 | closesocket(sock->sock); |
732 | if (!sock) lua_error(L, "out of memory"); | 1102 | sock->sock = INVALID_SOCKET; |
733 | lua_settag(L, tags->server); | 1103 | return connect_strerror(); |
734 | lua_settable(L, -3); | 1104 | } |
735 | if (!create_tcpsocket(sock)) return NULL; | 1105 | /* otherwise, proceed with domain name resolution */ |
736 | sock->tm_block = -1; | 1106 | } else { |
737 | sock->tm_return = -1; | 1107 | struct hostent *hp = gethostbyname(address); |
738 | sock->bf_first = sock->bf_last = 0; | 1108 | struct in_addr **addr; |
739 | for (i = 0; i < sizeof(funcs)/sizeof(funcs[0]); i++) { | 1109 | if (!hp) return host_strerror(); |
740 | lua_pushstring(L, funcs[i].name); | 1110 | addr = (struct in_addr **) hp->h_addr_list; |
741 | lua_pushusertag(L, sock, tags->client); | 1111 | for (; *addr != NULL; addr++) { |
742 | lua_pushcclosure(L, funcs[i].func, 1); | 1112 | memcpy(&local.sin_addr, *addr, sizeof(struct in_addr)); |
743 | lua_settable(L, -3); | 1113 | if (connect(sock->sock, (SA *) &local, sizeof(local)) < 0) { |
744 | } | 1114 | closesocket(sock->sock); |
745 | /* the accept method is different, it needs the tags closure too */ | 1115 | sock->sock = socket(AF_INET, SOCK_DGRAM, 0); |
746 | lua_pushstring(L, "accept"); | 1116 | if (sock->sock == INVALID_SOCKET) return socket_strerror(); |
747 | lua_pushuserdata(L, tags); | 1117 | } else break; |
748 | lua_pushusertag(L, sock, tags->client); | 1118 | } |
749 | lua_pushcclosure(L, table_accept, 2); | 1119 | if (*addr == NULL) return connect_strerror(); |
750 | lua_settable(L, -3); | 1120 | } |
751 | return sock; | 1121 | /* no errors found */ |
1122 | return NULL; | ||
752 | } | 1123 | } |
753 | 1124 | ||
754 | /*=========================================================================*\ | 1125 | /*=========================================================================*\ |
@@ -764,23 +1135,23 @@ static p_sock push_servertable(lua_State *L, p_tags tags) | |||
764 | \*-------------------------------------------------------------------------*/ | 1135 | \*-------------------------------------------------------------------------*/ |
765 | static int tm_gettimeleft(p_sock sock) | 1136 | static int tm_gettimeleft(p_sock sock) |
766 | { | 1137 | { |
767 | /* no timeout */ | 1138 | /* no timeout */ |
768 | if (sock->tm_block < 0 && sock->tm_return < 0) | 1139 | if (sock->tm_block < 0 && sock->tm_return < 0) |
769 | return -1; | 1140 | return -1; |
770 | /* there is no block timeout, we use the return timeout */ | 1141 | /* there is no block timeout, we use the return timeout */ |
771 | else if (sock->tm_block < 0) | 1142 | else if (sock->tm_block < 0) |
772 | return max(sock->tm_return - tm_gettime() + sock->tm_start, 0); | 1143 | return max(sock->tm_return - tm_gettime() + sock->tm_start, 0); |
773 | /* there is no return timeout, we use the block timeout */ | 1144 | /* there is no return timeout, we use the block timeout */ |
774 | else if (sock->tm_return < 0) | 1145 | else if (sock->tm_return < 0) |
775 | return sock->tm_block; | 1146 | return sock->tm_block; |
776 | /* both timeouts are specified */ | 1147 | /* both timeouts are specified */ |
777 | else return min(sock->tm_block, | 1148 | else return min(sock->tm_block, |
778 | max(sock->tm_return - tm_gettime() + sock->tm_start, 0)); | 1149 | max(sock->tm_return - tm_gettime() + sock->tm_start, 0)); |
779 | } | 1150 | } |
780 | 1151 | ||
781 | /*-------------------------------------------------------------------------*\ | 1152 | /*-------------------------------------------------------------------------*\ |
782 | * Determines if we have a timeout condition or if we can proceed with | 1153 | * Determines if we have a timeout condition or if we can proceed with |
783 | * an IO write operation. | 1154 | * an IO operation. |
784 | * Input | 1155 | * Input |
785 | * sock: socket structure being used in operation | 1156 | * sock: socket structure being used in operation |
786 | * mode: TM_RECEIVE or TM_SEND | 1157 | * mode: TM_RECEIVE or TM_SEND |
@@ -789,30 +1160,29 @@ static int tm_gettimeleft(p_sock sock) | |||
789 | \*-------------------------------------------------------------------------*/ | 1160 | \*-------------------------------------------------------------------------*/ |
790 | static int tm_timedout(p_sock sock, int mode) | 1161 | static int tm_timedout(p_sock sock, int mode) |
791 | { | 1162 | { |
792 | fd_set fds; | 1163 | fd_set fds; |
793 | int ret, delta; | 1164 | int ret; |
794 | fd_set *preadfds = NULL, *pwritefds = NULL; | 1165 | fd_set *preadfds = NULL, *pwritefds = NULL; |
795 | struct timeval tm; | 1166 | struct timeval tm; |
796 | struct timeval *ptm = NULL; | 1167 | struct timeval *ptm = NULL; |
797 | /* find out how much time we have left, in ms */ | 1168 | /* find out how much time we have left, in ms */ |
798 | int ms = tm_gettimeleft(sock); | 1169 | int ms = tm_gettimeleft(sock); |
799 | /* fill file descriptor set */ | 1170 | /* fill file descriptor set */ |
800 | FD_ZERO(&fds); FD_SET(sock->sock, &fds); | 1171 | FD_ZERO(&fds); FD_SET(sock->sock, &fds); |
801 | /* fill timeval structure */ | 1172 | /* fill timeval structure */ |
802 | tm.tv_sec = ms / 1000; | 1173 | tm.tv_sec = ms / 1000; |
803 | tm.tv_usec = (ms % 1000) * 1000; | 1174 | tm.tv_usec = (ms % 1000) * 1000; |
804 | /* define function parameters */ | 1175 | /* define function parameters */ |
805 | if (ms > 0) ptm = &tm; /* ptm == NULL when we don't have timeout */ | 1176 | if (ms >= 0) ptm = &tm; /* ptm == NULL when we don't have timeout */ |
806 | if (mode == TM_RECEIVE) preadfds = &fds; | 1177 | if (mode == TM_RECEIVE) preadfds = &fds; |
807 | else pwritefds = &fds; | 1178 | else pwritefds = &fds; |
808 | delta = tm_gettime(); | 1179 | /* see if we can read, write or if we timedout */ |
809 | /* see if we can read or write or if we timedout */ | 1180 | ret = select(sock->sock+1, preadfds, pwritefds, NULL, ptm); |
810 | ret = select(sock->sock+1, preadfds, pwritefds, NULL, ptm); | ||
811 | #ifdef _DEBUG | 1181 | #ifdef _DEBUG |
812 | /* store end time for this operation next call to OS */ | 1182 | /* store end time for this operation next call to OS */ |
813 | sock->tm_end = tm_gettime(); | 1183 | sock->tm_end = tm_gettime(); |
814 | #endif | 1184 | #endif |
815 | return ret <= 0; | 1185 | return ret <= 0; |
816 | } | 1186 | } |
817 | 1187 | ||
818 | /*-------------------------------------------------------------------------*\ | 1188 | /*-------------------------------------------------------------------------*\ |
@@ -822,9 +1192,9 @@ static int tm_timedout(p_sock sock, int mode) | |||
822 | \*-------------------------------------------------------------------------*/ | 1192 | \*-------------------------------------------------------------------------*/ |
823 | static void tm_markstart(p_sock sock) | 1193 | static void tm_markstart(p_sock sock) |
824 | { | 1194 | { |
825 | sock->tm_start = tm_gettime(); | 1195 | sock->tm_start = tm_gettime(); |
826 | #ifdef _DEBUG | 1196 | #ifdef _DEBUG |
827 | sock->tm_end = sock->tm_start; | 1197 | sock->tm_end = sock->tm_start; |
828 | #endif | 1198 | #endif |
829 | } | 1199 | } |
830 | 1200 | ||
@@ -836,10 +1206,10 @@ static void tm_markstart(p_sock sock) | |||
836 | static int tm_gettime(void) | 1206 | static int tm_gettime(void) |
837 | { | 1207 | { |
838 | #ifdef _WIN32 | 1208 | #ifdef _WIN32 |
839 | return GetTickCount(); | 1209 | return GetTickCount(); |
840 | #else | 1210 | #else |
841 | struct tms t; | 1211 | struct tms t; |
842 | return (times(&t)*1000)/CLK_TCK; | 1212 | return (times(&t)*1000)/CLK_TCK; |
843 | #endif | 1213 | #endif |
844 | } | 1214 | } |
845 | 1215 | ||
@@ -855,7 +1225,7 @@ static int tm_gettime(void) | |||
855 | \*-------------------------------------------------------------------------*/ | 1225 | \*-------------------------------------------------------------------------*/ |
856 | static int bf_isempty(p_sock sock) | 1226 | static int bf_isempty(p_sock sock) |
857 | { | 1227 | { |
858 | return sock->bf_first >= sock->bf_last; | 1228 | return sock->bf_first >= sock->bf_last; |
859 | } | 1229 | } |
860 | 1230 | ||
861 | /*-------------------------------------------------------------------------*\ | 1231 | /*-------------------------------------------------------------------------*\ |
@@ -866,13 +1236,13 @@ static int bf_isempty(p_sock sock) | |||
866 | \*-------------------------------------------------------------------------*/ | 1236 | \*-------------------------------------------------------------------------*/ |
867 | static void bf_skip(p_sock sock, int length) | 1237 | static void bf_skip(p_sock sock, int length) |
868 | { | 1238 | { |
869 | sock->bf_first += length; | 1239 | sock->bf_first += length; |
870 | if (bf_isempty(sock)) sock->bf_first = sock->bf_last = 0; | 1240 | if (bf_isempty(sock)) sock->bf_first = sock->bf_last = 0; |
871 | } | 1241 | } |
872 | 1242 | ||
873 | /*-------------------------------------------------------------------------*\ | 1243 | /*-------------------------------------------------------------------------*\ |
874 | * Return any data avilable in buffer, or get more data from transport layer | 1244 | * Return any data avilable in buffer, or get more data from transport layer |
875 | * if there is none. | 1245 | * if buffer is empty. |
876 | * Input | 1246 | * Input |
877 | * sock: socket structure being used in operation | 1247 | * sock: socket structure being used in operation |
878 | * Output | 1248 | * Output |
@@ -882,18 +1252,19 @@ static void bf_skip(p_sock sock, int length) | |||
882 | \*-------------------------------------------------------------------------*/ | 1252 | \*-------------------------------------------------------------------------*/ |
883 | static const unsigned char *bf_receive(p_sock sock, int *length) | 1253 | static const unsigned char *bf_receive(p_sock sock, int *length) |
884 | { | 1254 | { |
885 | if (bf_isempty(sock)) { | 1255 | if (bf_isempty(sock)) { |
886 | int got = recv(sock->sock, sock->bf_buffer, LUASOCKET_BUFFERSIZE, 0); | 1256 | int got = recv(sock->sock, sock->bf_buffer, LUASOCKET_BUFFERSIZE, 0); |
887 | sock->bf_first = 0; | 1257 | sock->bf_first = 0; |
888 | if (got >= 0) sock->bf_last = got; | 1258 | if (got >= 0) sock->bf_last = got; |
889 | else sock->bf_last = 0; | 1259 | else sock->bf_last = 0; |
890 | } | 1260 | } |
891 | *length = sock->bf_last - sock->bf_first; | 1261 | *length = sock->bf_last - sock->bf_first; |
892 | return sock->bf_buffer + sock->bf_first; | 1262 | return sock->bf_buffer + sock->bf_first; |
893 | } | 1263 | } |
894 | 1264 | ||
895 | /*=========================================================================*\ | 1265 | /*=========================================================================*\ |
896 | * These are the function that are called for each I/O pattern | 1266 | * These are the function that are called for each I/O pattern |
1267 | * The read patterns leave their result on the Lua stack | ||
897 | \*=========================================================================*/ | 1268 | \*=========================================================================*/ |
898 | /*-------------------------------------------------------------------------*\ | 1269 | /*-------------------------------------------------------------------------*\ |
899 | * Sends a raw block of data through a socket. The operations are all | 1270 | * Sends a raw block of data through a socket. The operations are all |
@@ -909,26 +1280,26 @@ static const unsigned char *bf_receive(p_sock sock, int *length) | |||
909 | \*-------------------------------------------------------------------------*/ | 1280 | \*-------------------------------------------------------------------------*/ |
910 | static int send_raw(p_sock sock, const char *data, int wanted, int *total) | 1281 | static int send_raw(p_sock sock, const char *data, int wanted, int *total) |
911 | { | 1282 | { |
912 | int put = 0; | 1283 | int put = 0; |
913 | *total = 0; | 1284 | *total = 0; |
914 | while (wanted > 0) { | 1285 | while (wanted > 0) { |
915 | if (tm_timedout(sock, TM_SEND)) return NET_TIMEOUT; | 1286 | if (tm_timedout(sock, TM_SEND)) return NET_TIMEOUT; |
916 | put = send(sock->sock, data, wanted, 0); | 1287 | put = send(sock->sock, data, wanted, 0); |
917 | if (put <= 0) { | 1288 | if (put <= 0) { |
918 | #ifdef WIN32 | 1289 | #ifdef WIN32 |
919 | /* a bug in WinSock forces us to do a busy wait until we manage | 1290 | /* a bug in WinSock forces us to do a busy wait until we manage |
920 | ** to write, because select returns immediately even though it | 1291 | ** to write, because select returns immediately even though it |
921 | ** should have blocked us */ | 1292 | ** should have blocked us until we could write... */ |
922 | if (WSAGetLastError() == WSAEWOULDBLOCK) | 1293 | if (WSAGetLastError() == WSAEWOULDBLOCK) |
923 | continue; | 1294 | continue; |
924 | #endif | 1295 | #endif |
925 | return NET_CLOSED; | 1296 | return NET_CLOSED; |
926 | } | 1297 | } |
927 | wanted -= put; | 1298 | wanted -= put; |
928 | data += put; | 1299 | data += put; |
929 | *total += put; | 1300 | *total += put; |
930 | } | 1301 | } |
931 | return NET_DONE; | 1302 | return NET_DONE; |
932 | } | 1303 | } |
933 | 1304 | ||
934 | /*-------------------------------------------------------------------------*\ | 1305 | /*-------------------------------------------------------------------------*\ |
@@ -942,27 +1313,27 @@ static int send_raw(p_sock sock, const char *data, int wanted, int *total) | |||
942 | \*-------------------------------------------------------------------------*/ | 1313 | \*-------------------------------------------------------------------------*/ |
943 | static int receive_raw(lua_State *L, p_sock sock, int wanted) | 1314 | static int receive_raw(lua_State *L, p_sock sock, int wanted) |
944 | { | 1315 | { |
945 | int got = 0; | 1316 | int got = 0; |
946 | const unsigned char *buffer = NULL; | 1317 | const unsigned char *buffer = NULL; |
947 | luaL_Buffer b; | 1318 | luaL_Buffer b; |
948 | luaL_buffinit(L, &b); | 1319 | luaL_buffinit(L, &b); |
949 | while (wanted > 0) { | 1320 | while (wanted > 0) { |
950 | if (bf_isempty(sock) && tm_timedout(sock, TM_RECEIVE)) { | 1321 | if (bf_isempty(sock) && tm_timedout(sock, TM_RECEIVE)) { |
951 | luaL_pushresult(&b); | 1322 | luaL_pushresult(&b); |
952 | return NET_TIMEOUT; | 1323 | return NET_TIMEOUT; |
953 | } | 1324 | } |
954 | buffer = bf_receive(sock, &got); | 1325 | buffer = bf_receive(sock, &got); |
955 | if (got <= 0) { | 1326 | if (got <= 0) { |
956 | luaL_pushresult(&b); | 1327 | luaL_pushresult(&b); |
957 | return NET_CLOSED; | 1328 | return NET_CLOSED; |
958 | } | 1329 | } |
959 | got = min(got, wanted); | 1330 | got = min(got, wanted); |
960 | luaL_addlstring(&b, buffer, got); | 1331 | luaL_addlstring(&b, buffer, got); |
961 | bf_skip(sock, got); | 1332 | bf_skip(sock, got); |
962 | wanted -= got; | 1333 | wanted -= got; |
963 | } | 1334 | } |
964 | luaL_pushresult(&b); | 1335 | luaL_pushresult(&b); |
965 | return NET_DONE; | 1336 | return NET_DONE; |
966 | } | 1337 | } |
967 | 1338 | ||
968 | /*-------------------------------------------------------------------------*\ | 1339 | /*-------------------------------------------------------------------------*\ |
@@ -970,27 +1341,27 @@ static int receive_raw(lua_State *L, p_sock sock, int wanted) | |||
970 | * Input | 1341 | * Input |
971 | * sock: socket structure being used in operation | 1342 | * sock: socket structure being used in operation |
972 | * Result | 1343 | * Result |
973 | * operation error code. NET_DONE, NET_TIMEOUT or NET_CLOSED | 1344 | * operation error code. NET_DONE, NET_TIMEOUT |
974 | \*-------------------------------------------------------------------------*/ | 1345 | \*-------------------------------------------------------------------------*/ |
975 | static int receive_all(lua_State *L, p_sock sock) | 1346 | static int receive_all(lua_State *L, p_sock sock) |
976 | { | 1347 | { |
977 | int got = 0; | 1348 | int got = 0; |
978 | const unsigned char *buffer = NULL; | 1349 | const unsigned char *buffer = NULL; |
979 | luaL_Buffer b; | 1350 | luaL_Buffer b; |
980 | luaL_buffinit(L, &b); | 1351 | luaL_buffinit(L, &b); |
981 | for ( ;; ) { | 1352 | for ( ;; ) { |
982 | if (bf_isempty(sock) && tm_timedout(sock, TM_RECEIVE)) { | 1353 | if (bf_isempty(sock) && tm_timedout(sock, TM_RECEIVE)) { |
983 | luaL_pushresult(&b); | 1354 | luaL_pushresult(&b); |
984 | return NET_TIMEOUT; | 1355 | return NET_TIMEOUT; |
985 | } | 1356 | } |
986 | buffer = bf_receive(sock, &got); | 1357 | buffer = bf_receive(sock, &got); |
987 | if (got <= 0) { | 1358 | if (got <= 0) { |
988 | luaL_pushresult(&b); | 1359 | luaL_pushresult(&b); |
989 | return NET_DONE; | 1360 | return NET_DONE; |
990 | } | 1361 | } |
991 | luaL_addlstring(&b, buffer, got); | 1362 | luaL_addlstring(&b, buffer, got); |
992 | bf_skip(sock, got); | 1363 | bf_skip(sock, got); |
993 | } | 1364 | } |
994 | } | 1365 | } |
995 | 1366 | ||
996 | /*-------------------------------------------------------------------------*\ | 1367 | /*-------------------------------------------------------------------------*\ |
@@ -1005,37 +1376,37 @@ static int receive_all(lua_State *L, p_sock sock) | |||
1005 | \*-------------------------------------------------------------------------*/ | 1376 | \*-------------------------------------------------------------------------*/ |
1006 | static int receive_dosline(lua_State *L, p_sock sock) | 1377 | static int receive_dosline(lua_State *L, p_sock sock) |
1007 | { | 1378 | { |
1008 | int got = 0; | 1379 | int got = 0; |
1009 | const unsigned char *buffer = NULL; | 1380 | const unsigned char *buffer = NULL; |
1010 | luaL_Buffer b; | 1381 | luaL_Buffer b; |
1011 | luaL_buffinit(L, &b); | 1382 | luaL_buffinit(L, &b); |
1012 | for ( ;; ) { | 1383 | for ( ;; ) { |
1013 | if (bf_isempty(sock) && tm_timedout(sock, TM_RECEIVE)) { | 1384 | if (bf_isempty(sock) && tm_timedout(sock, TM_RECEIVE)) { |
1014 | luaL_pushresult(&b); | 1385 | luaL_pushresult(&b); |
1015 | return NET_TIMEOUT; | 1386 | return NET_TIMEOUT; |
1016 | } | 1387 | } |
1017 | buffer = bf_receive(sock, &got); | 1388 | buffer = bf_receive(sock, &got); |
1018 | if (got > 0) { | 1389 | if (got > 0) { |
1019 | int len = 0, end = 1; | 1390 | int len = 0, end = 1; |
1020 | while (len < got) { | 1391 | while (len < got) { |
1021 | if (buffer[len] == '\n') { /* found eol */ | 1392 | if (buffer[len] == '\n') { /* found eol */ |
1022 | if (len > 0 && buffer[len-1] == '\r') { | 1393 | if (len > 0 && buffer[len-1] == '\r') { |
1023 | end++; len--; | 1394 | end++; len--; |
1024 | } | 1395 | } |
1025 | luaL_addlstring(&b, buffer, len); | 1396 | luaL_addlstring(&b, buffer, len); |
1026 | bf_skip(sock, len + end); /* skip '\r\n' in stream */ | 1397 | bf_skip(sock, len + end); /* skip '\r\n' in stream */ |
1027 | luaL_pushresult(&b); | 1398 | luaL_pushresult(&b); |
1028 | return NET_DONE; | 1399 | return NET_DONE; |
1029 | } | 1400 | } |
1030 | len++; | 1401 | len++; |
1031 | } | 1402 | } |
1032 | luaL_addlstring(&b, buffer, got); | 1403 | luaL_addlstring(&b, buffer, got); |
1033 | bf_skip(sock, got); | 1404 | bf_skip(sock, got); |
1034 | } else { | 1405 | } else { |
1035 | luaL_pushresult(&b); | 1406 | luaL_pushresult(&b); |
1036 | return NET_CLOSED; | 1407 | return NET_CLOSED; |
1037 | } | 1408 | } |
1038 | } | 1409 | } |
1039 | } | 1410 | } |
1040 | 1411 | ||
1041 | /*-------------------------------------------------------------------------*\ | 1412 | /*-------------------------------------------------------------------------*\ |
@@ -1049,34 +1420,34 @@ static int receive_dosline(lua_State *L, p_sock sock) | |||
1049 | \*-------------------------------------------------------------------------*/ | 1420 | \*-------------------------------------------------------------------------*/ |
1050 | static int receive_unixline(lua_State *L, p_sock sock) | 1421 | static int receive_unixline(lua_State *L, p_sock sock) |
1051 | { | 1422 | { |
1052 | int got = 0; | 1423 | int got = 0; |
1053 | const unsigned char *buffer = NULL; | 1424 | const unsigned char *buffer = NULL; |
1054 | luaL_Buffer b; | 1425 | luaL_Buffer b; |
1055 | luaL_buffinit(L, &b); | 1426 | luaL_buffinit(L, &b); |
1056 | for ( ;; ) { | 1427 | for ( ;; ) { |
1057 | if (bf_isempty(sock) && tm_timedout(sock, TM_RECEIVE)) { | 1428 | if (bf_isempty(sock) && tm_timedout(sock, TM_RECEIVE)) { |
1058 | luaL_pushresult(&b); | 1429 | luaL_pushresult(&b); |
1059 | return NET_TIMEOUT; | 1430 | return NET_TIMEOUT; |
1060 | } | 1431 | } |
1061 | buffer = bf_receive(sock, &got); | 1432 | buffer = bf_receive(sock, &got); |
1062 | if (got > 0) { | 1433 | if (got > 0) { |
1063 | int len = 0; | 1434 | int len = 0; |
1064 | while (len < got) { | 1435 | while (len < got) { |
1065 | if (buffer[len] == '\n') { /* found eol */ | 1436 | if (buffer[len] == '\n') { /* found eol */ |
1066 | luaL_addlstring(&b, buffer, len); | 1437 | luaL_addlstring(&b, buffer, len); |
1067 | bf_skip(sock, len + 1); /* skip '\n' in stream */ | 1438 | bf_skip(sock, len + 1); /* skip '\n' in stream */ |
1068 | luaL_pushresult(&b); | 1439 | luaL_pushresult(&b); |
1069 | return NET_DONE; | 1440 | return NET_DONE; |
1070 | } | 1441 | } |
1071 | len++; | 1442 | len++; |
1072 | } | 1443 | } |
1073 | luaL_addlstring(&b, buffer, got); | 1444 | luaL_addlstring(&b, buffer, got); |
1074 | bf_skip(sock, got); | 1445 | bf_skip(sock, got); |
1075 | } else { | 1446 | } else { |
1076 | luaL_pushresult(&b); | 1447 | luaL_pushresult(&b); |
1077 | return NET_CLOSED; | 1448 | return NET_CLOSED; |
1078 | } | 1449 | } |
1079 | } | 1450 | } |
1080 | } | 1451 | } |
1081 | 1452 | ||
1082 | /*=========================================================================*\ | 1453 | /*=========================================================================*\ |
@@ -1088,190 +1459,460 @@ static int receive_unixline(lua_State *L, p_sock sock) | |||
1088 | \*-------------------------------------------------------------------------*/ | 1459 | \*-------------------------------------------------------------------------*/ |
1089 | void lua_socketlibopen(lua_State *L) | 1460 | void lua_socketlibopen(lua_State *L) |
1090 | { | 1461 | { |
1091 | static struct luaL_reg funcs[] = { | 1462 | static struct luaL_reg funcs[] = { |
1092 | {"connect", global_connect}, | 1463 | {"connect", global_tcpconnect}, |
1093 | {"bind", global_bind}, | 1464 | {"udpsocket", global_udpsocket}, |
1094 | {"toip", global_toip}, | 1465 | {"bind", global_tcpbind}, |
1095 | }; | 1466 | {"toip", global_toip}, |
1096 | int i; | 1467 | {"tohostname", global_tohostname}, |
1097 | /* declare new Lua tags for used userdata values */ | 1468 | }; |
1098 | p_tags tags = (p_tags) lua_newuserdata(L, sizeof(t_tags)); | 1469 | unsigned int i; |
1099 | if (!tags) lua_error(L, "out of memory"); | 1470 | /* declare new Lua tags for used userdata values */ |
1100 | tags->client = lua_newtag(L); | 1471 | p_tags tags = (p_tags) lua_newuserdata(L, sizeof(t_tags)); |
1101 | tags->server = lua_newtag(L); | 1472 | if (!tags) lua_error(L, "out of memory"); |
1102 | tags->table = lua_newtag(L); | 1473 | tags->client = lua_newtag(L); |
1103 | /* global functions exported */ | 1474 | tags->server = lua_newtag(L); |
1104 | for (i = 0; i < sizeof(funcs)/sizeof(funcs[0]); i++) { | 1475 | tags->table = lua_newtag(L); |
1105 | lua_pushuserdata(L, tags); | 1476 | tags->udp = lua_newtag(L); |
1106 | lua_pushcclosure(L, funcs[i].func, 1); | 1477 | /* global functions exported */ |
1107 | lua_setglobal(L, funcs[i].name); | 1478 | for (i = 0; i < sizeof(funcs)/sizeof(funcs[0]); i++) { |
1108 | } | 1479 | lua_pushuserdata(L, tags); |
1109 | /* socket garbage collection */ | 1480 | lua_pushcclosure(L, funcs[i].func, 1); |
1110 | lua_pushuserdata(L, tags); | 1481 | lua_setglobal(L, funcs[i].name); |
1111 | lua_pushcclosure(L, gc_sock, 1); | 1482 | } |
1112 | lua_settagmethod(L, tags->table, "gc"); | 1483 | /* socket garbage collection */ |
1484 | lua_pushuserdata(L, tags); | ||
1485 | lua_pushcclosure(L, gc_table, 1); | ||
1486 | lua_settagmethod(L, tags->table, "gc"); | ||
1113 | 1487 | ||
1114 | #ifndef LUASOCKET_NOGLOBALS | 1488 | #ifndef LUASOCKET_NOGLOBALS |
1115 | /* global version of socket table functions */ | 1489 | /* global version of socket table functions */ |
1116 | { static struct luaL_reg opt_funcs[] = { | 1490 | { static struct luaL_reg opt_funcs[] = { |
1117 | {"send", global_send}, | 1491 | {"accept", global_tcpaccept}, |
1118 | {"receive", global_receive}, | 1492 | {"setpeername", global_udpsetpeername}, |
1119 | {"accept", global_accept}, | 1493 | {"setsockname", global_udpsetsockname}, |
1120 | {"close", global_close}, | 1494 | {"getsockname", global_getsockname}, |
1121 | {"timeout", global_timeout}, | 1495 | {"getpeername", global_getpeername}, |
1122 | {"listen", global_listen}, | 1496 | {"sendto", global_udpsendto}, |
1123 | }; | 1497 | {"receivefrom", global_udpreceivefrom}, |
1124 | for (i = 0; i < sizeof(opt_funcs)/sizeof(opt_funcs[0]); i++) { | 1498 | {"timeout", global_timeout}, |
1125 | lua_pushuserdata(L, tags); | 1499 | {"send", global_send}, |
1126 | lua_pushcclosure(L, opt_funcs[i].func, 1); | 1500 | {"poll", global_poll}, |
1127 | lua_setglobal(L, opt_funcs[i].name); | 1501 | {"receive", global_receive}, |
1128 | } | 1502 | {"close", global_close}, |
1503 | }; | ||
1504 | for (i = 0; i < sizeof(opt_funcs)/sizeof(opt_funcs[0]); i++) { | ||
1505 | lua_pushuserdata(L, tags); | ||
1506 | lua_pushcclosure(L, opt_funcs[i].func, 1); | ||
1507 | lua_setglobal(L, opt_funcs[i].name); | ||
1508 | } | ||
1129 | } | 1509 | } |
1130 | #endif | 1510 | #endif |
1131 | #ifdef WIN32 | 1511 | #ifdef WIN32 |
1132 | /* WinSock needs special initialization */ | 1512 | /* WinSock needs special initialization */ |
1133 | winsock_open(); | 1513 | winsock_open(); |
1134 | #else | 1514 | #else |
1135 | /* avoid getting killed by a SIGPIPE signal thrown by send */ | 1515 | /* avoid getting killed by a SIGPIPE signal thrown by send */ |
1136 | handle_sigpipe(); | 1516 | handle_sigpipe(); |
1137 | #endif | 1517 | #endif |
1138 | #ifdef _DEBUG | 1518 | #ifdef _DEBUG |
1139 | /* test support functions */ | 1519 | /* test support functions */ |
1140 | lua_pushcfunction(L, global_sleep); lua_setglobal(L, "sleep"); | 1520 | lua_pushcfunction(L, global_sleep); lua_setglobal(L, "sleep"); |
1141 | lua_pushcfunction(L, global_time); lua_setglobal(L, "time"); | 1521 | lua_pushcfunction(L, global_time); lua_setglobal(L, "time"); |
1142 | #endif | 1522 | #endif |
1143 | /* avoid stupid compiler warnings */ | ||
1144 | (void) set_blocking; | ||
1145 | } | 1523 | } |
1146 | 1524 | ||
1147 | /*=========================================================================*\ | 1525 | /*=========================================================================*\ |
1148 | * Optional global version of socket table methods | 1526 | * Optional global version of socket table methods |
1527 | * Simply push socket object on top or stack and call the table methods. | ||
1149 | \*=========================================================================*/ | 1528 | \*=========================================================================*/ |
1150 | #ifndef LUASOCKET_NOGLOBALS | 1529 | #ifndef LUASOCKET_NOGLOBALS |
1151 | int global_accept(lua_State *L) | 1530 | int global_tcpaccept(lua_State *L) |
1531 | { | ||
1532 | p_tags tags = pop_tags(L); | ||
1533 | p_sock sock = get_selfserversock(L, tags); | ||
1534 | lua_pushuserdata(L, tags); | ||
1535 | lua_pushusertag(L, sock, tags->server); | ||
1536 | return table_tcpaccept(L); | ||
1537 | } | ||
1538 | |||
1539 | int global_udpsendto(lua_State *L) | ||
1152 | { | 1540 | { |
1153 | p_tags tags = pop_tags(L); | 1541 | p_tags tags = pop_tags(L); |
1154 | p_sock sock = get_selfserversock(L, tags); | 1542 | p_sock sock = get_selfudpsock(L, tags); |
1155 | lua_pushuserdata(L, tags); | 1543 | lua_pushusertag(L, sock, tags->udp); |
1156 | lua_pushusertag(L, sock, tags->server); | 1544 | return table_udpsendto(L); |
1157 | return table_accept(L); | ||
1158 | } | 1545 | } |
1159 | 1546 | ||
1160 | int global_listen(lua_State *L) | 1547 | int global_udpsetpeername(lua_State *L) |
1161 | { | 1548 | { |
1162 | p_tags tags = pop_tags(L); | 1549 | p_tags tags = pop_tags(L); |
1163 | p_sock sock = get_selfserversock(L, tags); | 1550 | p_sock sock = get_selfudpsock(L, tags); |
1164 | lua_pushusertag(L, sock, tags->server); | 1551 | lua_pushusertag(L, sock, tags->udp); |
1165 | return table_listen(L); | 1552 | return table_udpsetpeername(L); |
1553 | } | ||
1554 | |||
1555 | int global_udpsetsockname(lua_State *L) | ||
1556 | { | ||
1557 | p_tags tags = pop_tags(L); | ||
1558 | p_sock sock = get_selfudpsock(L, tags); | ||
1559 | lua_pushusertag(L, sock, tags->udp); | ||
1560 | return table_udpsetsockname(L); | ||
1561 | } | ||
1562 | |||
1563 | int global_udpreceivefrom(lua_State *L) | ||
1564 | { | ||
1565 | p_tags tags = pop_tags(L); | ||
1566 | p_sock sock = get_selfudpsock(L, tags); | ||
1567 | lua_pushusertag(L, sock, tags->udp); | ||
1568 | return table_udpreceivefrom(L); | ||
1569 | } | ||
1570 | |||
1571 | int global_poll(lua_State *L) | ||
1572 | { | ||
1573 | p_tags tags = pop_tags(L); | ||
1574 | int tag; | ||
1575 | p_sock sock = get_selfsock(L, tags, &tag); | ||
1576 | lua_pushusertag(L, sock, tag); | ||
1577 | return table_poll(L); | ||
1166 | } | 1578 | } |
1167 | 1579 | ||
1168 | int global_send(lua_State *L) | 1580 | int global_send(lua_State *L) |
1169 | { | 1581 | { |
1170 | p_tags tags = pop_tags(L); | 1582 | p_tags tags = pop_tags(L); |
1171 | p_sock sock = get_selfclientsock(L, tags); | 1583 | int tag; |
1172 | lua_pushusertag(L, sock, tags->client); | 1584 | p_sock sock = get_selfsock(L, tags, &tag); |
1173 | return table_send(L); | 1585 | if (tag == tags->udp) { |
1586 | lua_pushusertag(L, sock, tags->udp); | ||
1587 | return table_udpsend(L); | ||
1588 | } else if (tag == tags->client) { | ||
1589 | lua_pushusertag(L, sock, tags->client); | ||
1590 | return table_tcpsend(L); | ||
1591 | } else if (tag == tags->server) { | ||
1592 | lua_error(L, "send on server socket"); | ||
1593 | } else | ||
1594 | lua_error(L, "invalid socket object"); | ||
1595 | /* avoid compiler warnings */ | ||
1596 | return 0; | ||
1174 | } | 1597 | } |
1175 | 1598 | ||
1176 | int global_receive(lua_State *L) | 1599 | int global_receive(lua_State *L) |
1177 | { | 1600 | { |
1178 | p_tags tags = pop_tags(L); | 1601 | p_tags tags = pop_tags(L); |
1179 | p_sock sock = get_selfclientsock(L, tags); | 1602 | int tag; |
1180 | lua_pushusertag(L, sock, tags->client); | 1603 | p_sock sock = get_selfsock(L, tags, &tag); |
1181 | return table_receive(L); | 1604 | if (tag == tags->udp) { |
1605 | lua_pushusertag(L, sock, tags->udp); | ||
1606 | return table_udpreceive(L); | ||
1607 | } else if (tag == tags->client) { | ||
1608 | lua_pushusertag(L, sock, tags->client); | ||
1609 | return table_tcpreceive(L); | ||
1610 | } else if (tag == tags->server) { | ||
1611 | lua_error(L, "receive on server socket"); | ||
1612 | } else | ||
1613 | lua_error(L, "invalid socket object"); | ||
1614 | /* avoid compiler warnings */ | ||
1615 | return 0; | ||
1182 | } | 1616 | } |
1183 | 1617 | ||
1184 | int global_timeout(lua_State *L) | 1618 | int global_timeout(lua_State *L) |
1185 | { | 1619 | { |
1186 | p_tags tags = pop_tags(L); | 1620 | p_tags tags = pop_tags(L); |
1187 | p_sock sock = get_selfclientsock(L, tags); | 1621 | int tag; |
1188 | lua_pushusertag(L, sock, tags->client); | 1622 | p_sock sock = get_selfsock(L, tags, &tag); |
1189 | return table_timeout(L); | 1623 | lua_pushusertag(L, sock, tag); |
1624 | return table_timeout(L); | ||
1625 | } | ||
1626 | |||
1627 | int global_getpeername(lua_State *L) | ||
1628 | { | ||
1629 | p_tags tags = pop_tags(L); | ||
1630 | int tag; | ||
1631 | p_sock sock = get_selfsock(L, tags, &tag); | ||
1632 | if (tag == tags->server) lua_error(L, "getpeername on server socket"); | ||
1633 | lua_pushusertag(L, sock, tag); | ||
1634 | return table_getpeername(L); | ||
1635 | } | ||
1636 | |||
1637 | int global_getsockname(lua_State *L) | ||
1638 | { | ||
1639 | p_tags tags = pop_tags(L); | ||
1640 | int tag; | ||
1641 | p_sock sock = get_selfsock(L, tags, &tag); | ||
1642 | lua_pushusertag(L, sock, tag); | ||
1643 | return table_getsockname(L); | ||
1190 | } | 1644 | } |
1191 | 1645 | ||
1192 | int global_close(lua_State *L) | 1646 | int global_close(lua_State *L) |
1193 | { | 1647 | { |
1194 | return gc_sock(L); | 1648 | /* just call the garbage collection tag method. it knows what to do */ |
1649 | return gc_table(L); | ||
1195 | } | 1650 | } |
1196 | #endif | 1651 | #endif |
1197 | 1652 | ||
1198 | /*=========================================================================*\ | 1653 | /*=========================================================================*\ |
1199 | * Parameter manipulation functions | 1654 | * Lua Stack manipulation functions |
1200 | \*=========================================================================*/ | 1655 | \*=========================================================================*/ |
1201 | /*-------------------------------------------------------------------------*\ | 1656 | /*-------------------------------------------------------------------------*\ |
1657 | * Creates a t_sock structure with default values for a client sock. | ||
1658 | * Pushes the Lua table with sock fields and appropriate methods | ||
1659 | * Input | ||
1660 | * tags: tags structure | ||
1661 | * Returns | ||
1662 | * pointer to allocated t_sock structure, NULL in case of error | ||
1663 | \*-------------------------------------------------------------------------*/ | ||
1664 | static p_sock push_clienttable(lua_State *L, p_tags tags) | ||
1665 | { | ||
1666 | static struct luaL_reg funcs[] = { | ||
1667 | {"close", table_close}, | ||
1668 | {"getsockname", table_getsockname}, | ||
1669 | {"getpeername", table_getpeername}, | ||
1670 | {"poll", table_poll}, | ||
1671 | {"receive", table_tcpreceive}, | ||
1672 | {"send", table_tcpsend}, | ||
1673 | {"timeout", table_timeout}, | ||
1674 | }; | ||
1675 | unsigned int i; | ||
1676 | p_sock sock; | ||
1677 | lua_newtable(L); lua_settag(L, tags->table); | ||
1678 | lua_pushstring(L, P_SOCK); | ||
1679 | sock = (p_sock) lua_newuserdata(L, sizeof(t_sock)); | ||
1680 | if (!sock) return NULL; | ||
1681 | lua_settag(L, tags->client); | ||
1682 | lua_settable(L, -3); | ||
1683 | sock->sock = -1; | ||
1684 | sock->is_connected = 0; | ||
1685 | sock->tm_block = -1; | ||
1686 | sock->tm_return = -1; | ||
1687 | sock->bf_first = sock->bf_last = 0; | ||
1688 | for (i = 0; i < sizeof(funcs)/sizeof(funcs[0]); i++) { | ||
1689 | lua_pushstring(L, funcs[i].name); | ||
1690 | lua_pushusertag(L, sock, tags->client); | ||
1691 | lua_pushcclosure(L, funcs[i].func, 1); | ||
1692 | lua_settable(L, -3); | ||
1693 | } | ||
1694 | return sock; | ||
1695 | } | ||
1696 | |||
1697 | /*-------------------------------------------------------------------------*\ | ||
1698 | * Creates a t_sock structure with default values for a server sock. | ||
1699 | * Pushes the Lua table with sock fields and appropriate methods | ||
1700 | * Input | ||
1701 | * tags: tags structure | ||
1702 | * Returns | ||
1703 | * pointer to allocated t_sock structure, NULL in case of error | ||
1704 | \*-------------------------------------------------------------------------*/ | ||
1705 | static p_sock push_servertable(lua_State *L, p_tags tags) | ||
1706 | { | ||
1707 | static struct luaL_reg funcs[] = { | ||
1708 | {"close", table_close}, | ||
1709 | {"getsockname", table_getsockname}, | ||
1710 | {"poll", table_poll}, | ||
1711 | {"timeout", table_timeout}, | ||
1712 | }; | ||
1713 | unsigned int i; | ||
1714 | p_sock sock; | ||
1715 | lua_newtable(L); lua_settag(L, tags->table); | ||
1716 | lua_pushstring(L, P_SOCK); | ||
1717 | sock = (p_sock) lua_newuserdata(L, sizeof(t_sock)); | ||
1718 | if (!sock) return NULL; | ||
1719 | lua_settag(L, tags->server); | ||
1720 | lua_settable(L, -3); | ||
1721 | sock->sock = INVALID_SOCKET; | ||
1722 | sock->tm_block = -1; | ||
1723 | sock->tm_return = -1; | ||
1724 | sock->bf_first = sock->bf_last = 0; | ||
1725 | for (i = 0; i < sizeof(funcs)/sizeof(funcs[0]); i++) { | ||
1726 | lua_pushstring(L, funcs[i].name); | ||
1727 | lua_pushusertag(L, sock, tags->client); | ||
1728 | lua_pushcclosure(L, funcs[i].func, 1); | ||
1729 | lua_settable(L, -3); | ||
1730 | } | ||
1731 | /* the accept method is different, it needs the tags closure too */ | ||
1732 | lua_pushstring(L, "accept"); | ||
1733 | lua_pushuserdata(L, tags); | ||
1734 | lua_pushusertag(L, sock, tags->client); | ||
1735 | lua_pushcclosure(L, table_tcpaccept, 2); | ||
1736 | lua_settable(L, -3); | ||
1737 | return sock; | ||
1738 | } | ||
1739 | |||
1740 | /*-------------------------------------------------------------------------*\ | ||
1741 | * Creates a t_sock structure with default values for a udp sock. | ||
1742 | * Pushes the Lua table with sock fields and appropriate methods | ||
1743 | * Input | ||
1744 | * tags: tags structure | ||
1745 | * Returns | ||
1746 | * pointer to allocated t_sock structure, NULL in case of error | ||
1747 | \*-------------------------------------------------------------------------*/ | ||
1748 | static p_sock push_udptable(lua_State *L, p_tags tags) | ||
1749 | { | ||
1750 | static struct luaL_reg funcs[] = { | ||
1751 | {"sendto", table_udpsendto}, | ||
1752 | {"setpeername", table_udpsetpeername}, | ||
1753 | {"setsockname", table_udpsetsockname}, | ||
1754 | {"getpeername", table_getpeername}, | ||
1755 | {"getsockname", table_getsockname}, | ||
1756 | {"poll", table_poll}, | ||
1757 | {"receivefrom", table_udpreceivefrom}, | ||
1758 | {"receive", table_udpreceive}, | ||
1759 | {"send", table_udpsend}, | ||
1760 | {"close", table_close}, | ||
1761 | {"timeout", table_timeout}, | ||
1762 | }; | ||
1763 | unsigned int i; | ||
1764 | p_sock sock; | ||
1765 | lua_newtable(L); lua_settag(L, tags->table); | ||
1766 | lua_pushstring(L, P_SOCK); | ||
1767 | sock = (p_sock) lua_newuserdata(L, sizeof(t_sock)); | ||
1768 | if (!sock) { | ||
1769 | lua_pushnil(L); | ||
1770 | lua_pushstring(L, "out of memory"); | ||
1771 | return NULL; | ||
1772 | } | ||
1773 | lua_settag(L, tags->udp); | ||
1774 | lua_settable(L, -3); | ||
1775 | sock->sock = socket(AF_INET, SOCK_DGRAM, 0); | ||
1776 | if (sock->sock == INVALID_SOCKET) { | ||
1777 | lua_pushnil(L); | ||
1778 | lua_pushstring(L, socket_strerror()); | ||
1779 | return NULL; | ||
1780 | } | ||
1781 | sock->is_connected = 0; | ||
1782 | sock->tm_block = -1; | ||
1783 | sock->tm_return = -1; | ||
1784 | sock->bf_first = sock->bf_last = 0; | ||
1785 | for (i = 0; i < sizeof(funcs)/sizeof(funcs[0]); i++) { | ||
1786 | lua_pushstring(L, funcs[i].name); | ||
1787 | lua_pushusertag(L, sock, tags->udp); | ||
1788 | lua_pushcclosure(L, funcs[i].func, 1); | ||
1789 | lua_settable(L, -3); | ||
1790 | } | ||
1791 | return sock; | ||
1792 | } | ||
1793 | |||
1794 | /*-------------------------------------------------------------------------*\ | ||
1795 | * Passes all resolver information to Lua as a table | ||
1796 | * Input | ||
1797 | * hp: hostent structure returned by resolver | ||
1798 | \*-------------------------------------------------------------------------*/ | ||
1799 | static void push_resolved(lua_State *L, struct hostent *hp) | ||
1800 | { | ||
1801 | char **alias; | ||
1802 | struct in_addr **addr; | ||
1803 | int i, resolved; | ||
1804 | |||
1805 | lua_newtable(L); resolved = lua_gettop(L); | ||
1806 | |||
1807 | lua_pushstring(L, "name"); | ||
1808 | lua_pushstring(L, hp->h_name); | ||
1809 | lua_settable(L, resolved); | ||
1810 | |||
1811 | lua_pushstring(L, "ip"); | ||
1812 | lua_pushstring(L, "alias"); | ||
1813 | |||
1814 | i = 1; | ||
1815 | alias = hp->h_aliases; | ||
1816 | lua_newtable(L); | ||
1817 | while (*alias) { | ||
1818 | lua_pushnumber(L, i); | ||
1819 | lua_pushstring(L, *alias); | ||
1820 | lua_settable(L, -3); | ||
1821 | i++; alias++; | ||
1822 | } | ||
1823 | lua_settable(L, resolved); | ||
1824 | |||
1825 | i = 1; | ||
1826 | lua_newtable(L); | ||
1827 | addr = (struct in_addr **) hp->h_addr_list; | ||
1828 | while (*addr) { | ||
1829 | lua_pushnumber(L, i); | ||
1830 | lua_pushstring(L, inet_ntoa(**addr)); | ||
1831 | lua_settable(L, -3); | ||
1832 | i++; addr++; | ||
1833 | } | ||
1834 | lua_settable(L, resolved); | ||
1835 | } | ||
1836 | |||
1837 | /*-------------------------------------------------------------------------*\ | ||
1202 | * Passes an error code to Lua. The NET_DONE error is translated to nil. | 1838 | * Passes an error code to Lua. The NET_DONE error is translated to nil. |
1203 | * Input | 1839 | * Input |
1204 | * err: error code to be passed to Lua | 1840 | * err: error code to be passed to Lua |
1205 | \*-------------------------------------------------------------------------*/ | 1841 | \*-------------------------------------------------------------------------*/ |
1206 | static void push_error(lua_State *L, int err) | 1842 | static void push_error(lua_State *L, int err) |
1207 | { | 1843 | { |
1208 | switch (err) { | 1844 | switch (err) { |
1209 | case NET_DONE: | 1845 | case NET_DONE: |
1210 | lua_pushnil(L); | 1846 | lua_pushnil(L); |
1211 | break; | 1847 | break; |
1212 | case NET_TIMEOUT: | 1848 | case NET_TIMEOUT: |
1213 | lua_pushstring(L, "timeout"); | 1849 | lua_pushstring(L, "timeout"); |
1214 | break; | 1850 | break; |
1215 | case NET_CLOSED: | 1851 | case NET_CLOSED: |
1216 | lua_pushstring(L, "closed"); | 1852 | lua_pushstring(L, "closed"); |
1217 | break; | 1853 | break; |
1218 | } | 1854 | case NET_REFUSED: |
1855 | lua_pushstring(L, "refused"); | ||
1856 | break; | ||
1857 | } | ||
1219 | } | 1858 | } |
1220 | 1859 | ||
1221 | static p_tags pop_tags(lua_State *L) | 1860 | static p_tags pop_tags(lua_State *L) |
1222 | { | 1861 | { |
1223 | p_tags tags = (p_tags) lua_touserdata(L, -1); | 1862 | p_tags tags = (p_tags) lua_touserdata(L, -1); |
1224 | if (!tags) lua_error(L, "invalid closure! (probably misuse of library)"); | 1863 | if (!tags) lua_error(L, "invalid closure! (probably misuse of library)"); |
1225 | lua_pop(L, 1); | 1864 | lua_pop(L, 1); |
1226 | return tags; | 1865 | return tags; |
1227 | } | 1866 | } |
1228 | 1867 | ||
1229 | static p_sock pop_sock(lua_State *L) | 1868 | static p_sock pop_sock(lua_State *L) |
1230 | { | 1869 | { |
1231 | p_sock sock = (p_sock) lua_touserdata(L, -1); | 1870 | p_sock sock = (p_sock) lua_touserdata(L, -1); |
1232 | if (!sock) lua_error(L, "invalid socket object"); | 1871 | if (!sock) lua_error(L, "invalid socket object"); |
1233 | if (sock->sock < 0) lua_error(L, "operation on closed socket"); | 1872 | if (sock->sock == INVALID_SOCKET) |
1234 | lua_pop(L, 1); | 1873 | lua_error(L, "operation on closed socket"); |
1235 | return sock; | 1874 | lua_pop(L, 1); |
1875 | return sock; | ||
1236 | } | 1876 | } |
1237 | 1877 | ||
1238 | static p_sock get_selfsock(lua_State *L, p_tags tags) | 1878 | static p_sock get_selfsock(lua_State *L, p_tags tags, int *tag) |
1239 | { | 1879 | { |
1240 | p_sock sock; | 1880 | p_sock sock; |
1241 | if (lua_tag(L, 1) != tags->table) lua_error(L, "invalid socket object"); | 1881 | if (lua_tag(L, 1) != tags->table) lua_error(L, "invalid socket object"); |
1242 | lua_pushstring(L, P_SOCK); | 1882 | lua_pushstring(L, P_SOCK); |
1243 | lua_gettable(L, 1); | 1883 | lua_gettable(L, 1); |
1244 | sock = lua_touserdata(L, -1); | 1884 | sock = lua_touserdata(L, -1); |
1245 | if (!sock) lua_error(L, "invalid socket object"); | 1885 | if (!sock) lua_error(L, "invalid socket object"); |
1246 | lua_pop(L, 1); | 1886 | if (tag) *tag = lua_tag(L, -1); |
1247 | return sock; | 1887 | lua_pop(L, 1); |
1888 | return sock; | ||
1248 | } | 1889 | } |
1249 | 1890 | ||
1250 | #ifndef LUASOCKET_NOGLOBALS | 1891 | #ifndef LUASOCKET_NOGLOBALS |
1251 | static p_sock get_selfclientsock(lua_State *L, p_tags tags) | 1892 | static p_sock get_selfudpsock(lua_State *L, p_tags tags) |
1252 | { | 1893 | { |
1253 | p_sock sock; | 1894 | p_sock sock; |
1254 | if (lua_tag(L, 1) != tags->table) lua_error(L, "invalid socket object"); | 1895 | if (lua_tag(L, 1) != tags->table) lua_error(L, "invalid socket object"); |
1255 | lua_pushstring(L, P_SOCK); | 1896 | lua_pushstring(L, P_SOCK); |
1256 | lua_gettable(L, 1); | 1897 | lua_gettable(L, 1); |
1257 | sock = lua_touserdata(L, -1); | 1898 | sock = lua_touserdata(L, -1); |
1258 | if (!sock || lua_tag(L, -1) != tags->client) | 1899 | if (!sock || lua_tag(L, -1) != tags->udp) |
1259 | lua_error(L, "client socket expected"); | 1900 | lua_error(L, "udp socket expected"); |
1260 | lua_pop(L, 1); | 1901 | lua_pop(L, 1); |
1261 | return sock; | 1902 | return sock; |
1262 | } | 1903 | } |
1263 | 1904 | ||
1264 | static p_sock get_selfserversock(lua_State *L, p_tags tags) | 1905 | static p_sock get_selfserversock(lua_State *L, p_tags tags) |
1265 | { | 1906 | { |
1266 | p_sock sock; | 1907 | p_sock sock; |
1267 | if (lua_tag(L, 1) != tags->table) lua_error(L, "invalid socket object"); | 1908 | if (lua_tag(L, 1) != tags->table) lua_error(L, "invalid socket object"); |
1268 | lua_pushstring(L, P_SOCK); | 1909 | lua_pushstring(L, P_SOCK); |
1269 | lua_gettable(L, 1); | 1910 | lua_gettable(L, 1); |
1270 | sock = lua_touserdata(L, -1); | 1911 | sock = lua_touserdata(L, -1); |
1271 | if (!sock || lua_tag(L, -1) != tags->server) | 1912 | if (!sock || lua_tag(L, -1) != tags->server) |
1272 | lua_error(L, "server socket expected"); | 1913 | lua_error(L, "server socket expected"); |
1273 | lua_pop(L, 1); | 1914 | lua_pop(L, 1); |
1274 | return sock; | 1915 | return sock; |
1275 | } | 1916 | } |
1276 | #endif | 1917 | #endif |
1277 | 1918 | ||
@@ -1286,18 +1927,19 @@ static p_sock get_selfserversock(lua_State *L, p_tags tags) | |||
1286 | \*-------------------------------------------------------------------------*/ | 1927 | \*-------------------------------------------------------------------------*/ |
1287 | static int winsock_open(void) | 1928 | static int winsock_open(void) |
1288 | { | 1929 | { |
1289 | WORD wVersionRequested;WSADATA wsaData;int err; | 1930 | WORD wVersionRequested; |
1290 | wVersionRequested = MAKEWORD( 2, 0 ); | 1931 | WSADATA wsaData; |
1291 | err = WSAStartup( wVersionRequested, &wsaData ); | 1932 | int err; |
1292 | if ( err != 0 ) { | 1933 | wVersionRequested = MAKEWORD(2, 0); |
1293 | return 0; | 1934 | err = WSAStartup(wVersionRequested, &wsaData ); |
1294 | } | 1935 | if (err != 0) { |
1295 | if ( LOBYTE( wsaData.wVersion ) != 2 || | 1936 | return 0; |
1296 | HIBYTE( wsaData.wVersion ) != 0 ) { | 1937 | } |
1297 | WSACleanup( ); | 1938 | if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 0) { |
1298 | return 0; | 1939 | WSACleanup(); |
1299 | } | 1940 | return 0; |
1300 | return 1; | 1941 | } |
1942 | return 1; | ||
1301 | } | 1943 | } |
1302 | 1944 | ||
1303 | /*-------------------------------------------------------------------------*\ | 1945 | /*-------------------------------------------------------------------------*\ |
@@ -1305,8 +1947,8 @@ static int winsock_open(void) | |||
1305 | \*-------------------------------------------------------------------------*/ | 1947 | \*-------------------------------------------------------------------------*/ |
1306 | static void set_blocking(p_sock sock) | 1948 | static void set_blocking(p_sock sock) |
1307 | { | 1949 | { |
1308 | u_long argp = 0; | 1950 | u_long argp = 0; |
1309 | ioctlsocket(sock->sock, FIONBIO, &argp); | 1951 | ioctlsocket(sock->sock, FIONBIO, &argp); |
1310 | } | 1952 | } |
1311 | 1953 | ||
1312 | /*-------------------------------------------------------------------------*\ | 1954 | /*-------------------------------------------------------------------------*\ |
@@ -1314,8 +1956,8 @@ static void set_blocking(p_sock sock) | |||
1314 | \*-------------------------------------------------------------------------*/ | 1956 | \*-------------------------------------------------------------------------*/ |
1315 | static void set_nonblocking(p_sock sock) | 1957 | static void set_nonblocking(p_sock sock) |
1316 | { | 1958 | { |
1317 | u_long argp = 1; | 1959 | u_long argp = 1; |
1318 | ioctlsocket(sock->sock, FIONBIO, &argp); | 1960 | ioctlsocket(sock->sock, FIONBIO, &argp); |
1319 | } | 1961 | } |
1320 | 1962 | ||
1321 | /*-------------------------------------------------------------------------*\ | 1963 | /*-------------------------------------------------------------------------*\ |
@@ -1323,27 +1965,27 @@ static void set_nonblocking(p_sock sock) | |||
1323 | \*-------------------------------------------------------------------------*/ | 1965 | \*-------------------------------------------------------------------------*/ |
1324 | static char *host_strerror(void) | 1966 | static char *host_strerror(void) |
1325 | { | 1967 | { |
1326 | switch (WSAGetLastError()) { | 1968 | switch (WSAGetLastError()) { |
1327 | case HOST_NOT_FOUND: return "host not found"; | 1969 | case HOST_NOT_FOUND: return "host not found"; |
1328 | case NO_ADDRESS: return "unable to resolve host name"; | 1970 | case NO_ADDRESS: return "unable to resolve host name"; |
1329 | case NO_RECOVERY: return "name server error"; | 1971 | case NO_RECOVERY: return "name server error"; |
1330 | case TRY_AGAIN: return "name server unavailable, try again later."; | 1972 | case TRY_AGAIN: return "name server unavailable, try again later."; |
1331 | default: return "unknown error"; | 1973 | default: return "unknown error"; |
1332 | } | 1974 | } |
1333 | } | 1975 | } |
1334 | 1976 | ||
1335 | /*-------------------------------------------------------------------------*\ | 1977 | /*-------------------------------------------------------------------------*\ |
1336 | * Returns a string describing the last socket manipulation error. | 1978 | * Returns a string describing the last socket manipulation error. |
1337 | \*-------------------------------------------------------------------------*/ | 1979 | \*-------------------------------------------------------------------------*/ |
1338 | static char *sock_strerror(void) | 1980 | static char *socket_strerror(void) |
1339 | { | 1981 | { |
1340 | switch (WSAGetLastError()) { | 1982 | switch (WSAGetLastError()) { |
1341 | case WSANOTINITIALISED: return "not initialized"; | 1983 | case WSANOTINITIALISED: return "not initialized"; |
1342 | case WSAENETDOWN: return "network is down"; | 1984 | case WSAENETDOWN: return "network is down"; |
1343 | case WSAEMFILE: return "descriptor table is full"; | 1985 | case WSAEMFILE: return "descriptor table is full"; |
1344 | case WSAENOBUFS: return "insufficient buffer space"; | 1986 | case WSAENOBUFS: return "insufficient buffer space"; |
1345 | default: return "unknown error"; | 1987 | default: return "unknown error"; |
1346 | } | 1988 | } |
1347 | } | 1989 | } |
1348 | 1990 | ||
1349 | /*-------------------------------------------------------------------------*\ | 1991 | /*-------------------------------------------------------------------------*\ |
@@ -1351,16 +1993,16 @@ static char *sock_strerror(void) | |||
1351 | \*-------------------------------------------------------------------------*/ | 1993 | \*-------------------------------------------------------------------------*/ |
1352 | static char *bind_strerror(void) | 1994 | static char *bind_strerror(void) |
1353 | { | 1995 | { |
1354 | switch (WSAGetLastError()) { | 1996 | switch (WSAGetLastError()) { |
1355 | case WSANOTINITIALISED: return "not initialized"; | 1997 | case WSANOTINITIALISED: return "not initialized"; |
1356 | case WSAENETDOWN: return "network is down"; | 1998 | case WSAENETDOWN: return "network is down"; |
1357 | case WSAEADDRINUSE: return "address already in use"; | 1999 | case WSAEADDRINUSE: return "address already in use"; |
1358 | case WSAEINVAL: return "socket already bound"; | 2000 | case WSAEINVAL: return "socket already bound"; |
1359 | case WSAENOBUFS: return "too many connections"; | 2001 | case WSAENOBUFS: return "too many connections"; |
1360 | case WSAEFAULT: return "invalid address"; | 2002 | case WSAEFAULT: return "invalid address"; |
1361 | case WSAENOTSOCK: return "not a socket descriptor"; | 2003 | case WSAENOTSOCK: return "not a socket descriptor"; |
1362 | default: return "unknown error"; | 2004 | default: return "unknown error"; |
1363 | } | 2005 | } |
1364 | } | 2006 | } |
1365 | 2007 | ||
1366 | /*-------------------------------------------------------------------------*\ | 2008 | /*-------------------------------------------------------------------------*\ |
@@ -1368,15 +2010,15 @@ static char *bind_strerror(void) | |||
1368 | \*-------------------------------------------------------------------------*/ | 2010 | \*-------------------------------------------------------------------------*/ |
1369 | static char *connect_strerror(void) | 2011 | static char *connect_strerror(void) |
1370 | { | 2012 | { |
1371 | switch (WSAGetLastError()) { | 2013 | switch (WSAGetLastError()) { |
1372 | case WSANOTINITIALISED: return "not initialized"; | 2014 | case WSANOTINITIALISED: return "not initialized"; |
1373 | case WSAENETDOWN: return "network is down"; | 2015 | case WSAENETDOWN: return "network is down"; |
1374 | case WSAEADDRINUSE: return "address already in use"; | 2016 | case WSAEADDRINUSE: return "address already in use"; |
1375 | case WSAEADDRNOTAVAIL: return "address unavailable"; | 2017 | case WSAEADDRNOTAVAIL: return "address unavailable"; |
1376 | case WSAECONNREFUSED: return "connection refused"; | 2018 | case WSAECONNREFUSED: return "connection refused"; |
1377 | case WSAENETUNREACH: return "network is unreachable"; | 2019 | case WSAENETUNREACH: return "network is unreachable"; |
1378 | default: return "unknown error"; | 2020 | default: return "unknown error"; |
1379 | } | 2021 | } |
1380 | } | 2022 | } |
1381 | #else | 2023 | #else |
1382 | 2024 | ||
@@ -1388,9 +2030,9 @@ static char *connect_strerror(void) | |||
1388 | \*-------------------------------------------------------------------------*/ | 2030 | \*-------------------------------------------------------------------------*/ |
1389 | static void set_blocking(p_sock sock) | 2031 | static void set_blocking(p_sock sock) |
1390 | { | 2032 | { |
1391 | int flags = fcntl(sock->sock, F_GETFL, 0); | 2033 | int flags = fcntl(sock->sock, F_GETFL, 0); |
1392 | flags &= (~(O_NONBLOCK)); | 2034 | flags &= (~(O_NONBLOCK)); |
1393 | fcntl(sock->sock, F_SETFL, flags); | 2035 | fcntl(sock->sock, F_SETFL, flags); |
1394 | } | 2036 | } |
1395 | 2037 | ||
1396 | /*-------------------------------------------------------------------------*\ | 2038 | /*-------------------------------------------------------------------------*\ |
@@ -1398,9 +2040,9 @@ static void set_blocking(p_sock sock) | |||
1398 | \*-------------------------------------------------------------------------*/ | 2040 | \*-------------------------------------------------------------------------*/ |
1399 | static void set_nonblocking(p_sock sock) | 2041 | static void set_nonblocking(p_sock sock) |
1400 | { | 2042 | { |
1401 | int flags = fcntl(sock->sock, F_GETFL, 0); | 2043 | int flags = fcntl(sock->sock, F_GETFL, 0); |
1402 | flags |= O_NONBLOCK; | 2044 | flags |= O_NONBLOCK; |
1403 | fcntl(sock->sock, F_SETFL, flags); | 2045 | fcntl(sock->sock, F_SETFL, flags); |
1404 | } | 2046 | } |
1405 | 2047 | ||
1406 | /*-------------------------------------------------------------------------*\ | 2048 | /*-------------------------------------------------------------------------*\ |
@@ -1408,27 +2050,27 @@ static void set_nonblocking(p_sock sock) | |||
1408 | \*-------------------------------------------------------------------------*/ | 2050 | \*-------------------------------------------------------------------------*/ |
1409 | static char *host_strerror(void) | 2051 | static char *host_strerror(void) |
1410 | { | 2052 | { |
1411 | switch (h_errno) { | 2053 | switch (h_errno) { |
1412 | case HOST_NOT_FOUND: return "host not found"; | 2054 | case HOST_NOT_FOUND: return "host not found"; |
1413 | case NO_ADDRESS: return "unable to resolve host name"; | 2055 | case NO_ADDRESS: return "unable to resolve host name"; |
1414 | case NO_RECOVERY: return "name server error"; | 2056 | case NO_RECOVERY: return "name server error"; |
1415 | case TRY_AGAIN: return "name server unavailable, try again later"; | 2057 | case TRY_AGAIN: return "name server unavailable, try again later"; |
1416 | default: return "unknown error"; | 2058 | default: return "unknown error"; |
1417 | } | 2059 | } |
1418 | } | 2060 | } |
1419 | 2061 | ||
1420 | /*-------------------------------------------------------------------------*\ | 2062 | /*-------------------------------------------------------------------------*\ |
1421 | * Returns a string describing the last socket manipulation error. | 2063 | * Returns a string describing the last socket manipulation error. |
1422 | \*-------------------------------------------------------------------------*/ | 2064 | \*-------------------------------------------------------------------------*/ |
1423 | static char *sock_strerror(void) | 2065 | static char *socket_strerror(void) |
1424 | { | 2066 | { |
1425 | switch (errno) { | 2067 | switch (errno) { |
1426 | case EACCES: return "access denied"; | 2068 | case EACCES: return "access denied"; |
1427 | case EMFILE: return "descriptor table is full"; | 2069 | case EMFILE: return "descriptor table is full"; |
1428 | case ENFILE: return "too many open files"; | 2070 | case ENFILE: return "too many open files"; |
1429 | case ENOBUFS: return "insuffucient buffer space"; | 2071 | case ENOBUFS: return "insuffucient buffer space"; |
1430 | default: return "unknown error"; | 2072 | default: return "unknown error"; |
1431 | } | 2073 | } |
1432 | } | 2074 | } |
1433 | 2075 | ||
1434 | /*-------------------------------------------------------------------------*\ | 2076 | /*-------------------------------------------------------------------------*\ |
@@ -1436,16 +2078,16 @@ static char *sock_strerror(void) | |||
1436 | \*-------------------------------------------------------------------------*/ | 2078 | \*-------------------------------------------------------------------------*/ |
1437 | static char *bind_strerror(void) | 2079 | static char *bind_strerror(void) |
1438 | { | 2080 | { |
1439 | switch (errno) { | 2081 | switch (errno) { |
1440 | case EBADF: return "invalid descriptor"; | 2082 | case EBADF: return "invalid descriptor"; |
1441 | case EINVAL: return "socket already bound"; | 2083 | case EINVAL: return "socket already bound"; |
1442 | case EACCES: return "access denied"; | 2084 | case EACCES: return "access denied"; |
1443 | case ENOTSOCK: return "not a socket descriptor"; | 2085 | case ENOTSOCK: return "not a socket descriptor"; |
1444 | case EADDRINUSE: return "address already in use"; | 2086 | case EADDRINUSE: return "address already in use"; |
1445 | case EADDRNOTAVAIL: return "address unavailable"; | 2087 | case EADDRNOTAVAIL: return "address unavailable"; |
1446 | case ENOMEM: return "out of memory"; | 2088 | case ENOMEM: return "out of memory"; |
1447 | default: return "unknown error"; | 2089 | default: return "unknown error"; |
1448 | } | 2090 | } |
1449 | } | 2091 | } |
1450 | 2092 | ||
1451 | /*-------------------------------------------------------------------------*\ | 2093 | /*-------------------------------------------------------------------------*\ |
@@ -1453,16 +2095,43 @@ static char *bind_strerror(void) | |||
1453 | \*-------------------------------------------------------------------------*/ | 2095 | \*-------------------------------------------------------------------------*/ |
1454 | static char *connect_strerror(void) | 2096 | static char *connect_strerror(void) |
1455 | { | 2097 | { |
1456 | switch (errno) { | 2098 | switch (errno) { |
1457 | case EBADF: return "invalid descriptor"; | 2099 | case EBADF: return "invalid descriptor"; |
1458 | case ENOTSOCK: return "not a socket descriptor"; | 2100 | case ENOTSOCK: return "not a socket descriptor"; |
1459 | case EADDRNOTAVAIL: return "address not availabe"; | 2101 | case EADDRNOTAVAIL: return "address not availabe"; |
1460 | case ETIMEDOUT: return "connection timed out"; | 2102 | case ETIMEDOUT: return "connection timed out"; |
1461 | case ECONNREFUSED: return "connection refused"; | 2103 | case ECONNREFUSED: return "connection refused"; |
1462 | case EACCES: return "access denied"; | 2104 | case EACCES: return "access denied"; |
1463 | case ENETUNREACH: return "network is unreachable"; | 2105 | case ENETUNREACH: return "network is unreachable"; |
1464 | case EADDRINUSE: return "address already in use"; | 2106 | case EADDRINUSE: return "address already in use"; |
1465 | default: return "unknown error"; | 2107 | default: return "unknown error"; |
1466 | } | 2108 | } |
2109 | } | ||
2110 | #endif | ||
2111 | |||
2112 | /*-------------------------------------------------------------------------*\ | ||
2113 | * Some systems do not provide this so that we provide our own. It's not | ||
2114 | * marvelously fast, but it works just fine. | ||
2115 | \*-------------------------------------------------------------------------*/ | ||
2116 | #ifdef LUASOCKET_ATON | ||
2117 | static int inet_aton(const char *cp, struct in_addr *inp) | ||
2118 | { | ||
2119 | unsigned int a = 0, b = 0, c = 0, d = 0; | ||
2120 | int n = 0, r; | ||
2121 | unsigned long int addr = 0; | ||
2122 | r = sscanf(cp, "%u.%u.%u.%u%n", &a, &b, &c, &d, &n); | ||
2123 | if (r == 0 || n == 0) return 0; | ||
2124 | cp += n; | ||
2125 | if (*cp) return 0; | ||
2126 | if (a > 255 || b > 255 || c > 255 || d > 255) return 0; | ||
2127 | if (inp) { | ||
2128 | addr += a; addr <<= 8; | ||
2129 | addr += b; addr <<= 8; | ||
2130 | addr += c; addr <<= 8; | ||
2131 | addr += d; | ||
2132 | inp->s_addr = htonl(addr); | ||
2133 | } | ||
2134 | return 1; | ||
1467 | } | 2135 | } |
1468 | #endif | 2136 | #endif |
2137 | |||