diff options
| author | Diego Nehab <diego@tecgraf.puc-rio.br> | 2001-01-15 04:16:35 +0000 |
|---|---|---|
| committer | Diego Nehab <diego@tecgraf.puc-rio.br> | 2001-01-15 04:16:35 +0000 |
| commit | 84baa83864b4832844151aef694465ddf96c28f3 (patch) | |
| tree | 6d9f528b6f1b90b6660467cca329b6dc6ebff299 | |
| parent | b40d2ba005034c36c6b7f4439e6d6df1ef08d5e4 (diff) | |
| download | luasocket-84baa83864b4832844151aef694465ddf96c28f3.tar.gz luasocket-84baa83864b4832844151aef694465ddf96c28f3.tar.bz2 luasocket-84baa83864b4832844151aef694465ddf96c28f3.zip | |
The actuall bind to the Lua language has been rewritten with
generalized use of closure values. Sockets are now real tables,
where each method receives a p_sock structure as a closure.
Global version of methods are now optional, and call the table
versions.
Included the toip function that converts from host name to ip address.
new implementation of '*a' was broken as has been fixed.
The windows code has been tested and is working.
| -rw-r--r-- | src/luasocket.c | 899 |
1 files changed, 442 insertions, 457 deletions
diff --git a/src/luasocket.c b/src/luasocket.c index 4f03ad2..e6f423c 100644 --- a/src/luasocket.c +++ b/src/luasocket.c | |||
| @@ -104,17 +104,10 @@ | |||
| 104 | #define TM_SEND 2 | 104 | #define TM_SEND 2 |
| 105 | 105 | ||
| 106 | /*-------------------------------------------------------------------------*\ | 106 | /*-------------------------------------------------------------------------*\ |
| 107 | * As far as a Lua script is concerned, there are two kind of objects | 107 | * Each socket is represented by a table with the supported methods and |
| 108 | * representing a socket. A client socket is an object created by the | 108 | * the p_sock structure as fields. |
| 109 | * function connect, and implementing the methods send, receive, timeout | ||
| 110 | * and close. A server socket is an object created by the function bind, | ||
| 111 | * and implementing the methods listen, accept and close. Lua tag values | ||
| 112 | * for these objects are created in the lua_socketlibopen function, and | ||
| 113 | * passed as closure values (last argumnents to every library function) | ||
| 114 | # because we can't have any global variables. | ||
| 115 | \*-------------------------------------------------------------------------*/ | 109 | \*-------------------------------------------------------------------------*/ |
| 116 | #define CLIENT_TAG -2 | 110 | #define P_SOCK "(p_sock)sock" |
| 117 | #define SERVER_TAG -1 | ||
| 118 | 111 | ||
| 119 | /*-------------------------------------------------------------------------*\ | 112 | /*-------------------------------------------------------------------------*\ |
| 120 | * Both socket types are stored in the same structure to simplify | 113 | * Both socket types are stored in the same structure to simplify |
| @@ -126,20 +119,28 @@ typedef struct t_sock { | |||
| 126 | SOCKET sock; | 119 | SOCKET sock; |
| 127 | /* start time of the current operation */ | 120 | /* start time of the current operation */ |
| 128 | int tm_start; | 121 | int tm_start; |
| 129 | #ifdef _DEBUG | ||
| 130 | /* end time of current operation, for debug purposes */ | ||
| 131 | int tm_end; | ||
| 132 | #endif | ||
| 133 | /* return and blocking timeout values (-1 if no limit) */ | 122 | /* return and blocking timeout values (-1 if no limit) */ |
| 134 | int tm_return, tm_block; | 123 | int tm_return, tm_block; |
| 135 | /* buffered I/O storage */ | 124 | /* buffered I/O storage */ |
| 136 | unsigned char bf_buffer[LUASOCKET_BUFFERSIZE]; | 125 | unsigned char bf_buffer[LUASOCKET_BUFFERSIZE]; |
| 137 | /* first and last red bytes not yet passed to application */ | 126 | /* first and last red bytes not yet passed to application */ |
| 138 | int bf_first, bf_last; | 127 | int bf_first, bf_last; |
| 128 | #ifdef _DEBUG | ||
| 129 | /* end time of current operation, for debug purposes */ | ||
| 130 | int tm_end; | ||
| 131 | #endif | ||
| 139 | } t_sock; | 132 | } t_sock; |
| 140 | typedef t_sock *p_sock; | 133 | typedef t_sock *p_sock; |
| 141 | 134 | ||
| 142 | /*-------------------------------------------------------------------------*\ | 135 | /*-------------------------------------------------------------------------*\ |
| 136 | * Tags passed as closure values to global LuaSocket API functions | ||
| 137 | \*-------------------------------------------------------------------------*/ | ||
| 138 | typedef struct t_tags { | ||
| 139 | int client, server, table; | ||
| 140 | } t_tags; | ||
| 141 | typedef t_tags *p_tags; | ||
| 142 | |||
| 143 | /*-------------------------------------------------------------------------*\ | ||
| 143 | * Macros and internal declarations | 144 | * Macros and internal declarations |
| 144 | \*-------------------------------------------------------------------------*/ | 145 | \*-------------------------------------------------------------------------*/ |
| 145 | /* min and max macros */ | 146 | /* min and max macros */ |
| @@ -154,14 +155,24 @@ typedef t_sock *p_sock; | |||
| 154 | * Internal function prototypes | 155 | * Internal function prototypes |
| 155 | \*=========================================================================*/ | 156 | \*=========================================================================*/ |
| 156 | /* luasocket API functions */ | 157 | /* luasocket API functions */ |
| 157 | static int net_connect(lua_State *L); | 158 | static int global_connect(lua_State *L); |
| 158 | static int net_bind(lua_State *L); | 159 | static int global_bind(lua_State *L); |
| 159 | static int net_listen(lua_State *L); | 160 | static int table_listen(lua_State *L); |
| 160 | static int net_accept(lua_State *L); | 161 | static int table_accept(lua_State *L); |
| 161 | static int net_send(lua_State *L); | 162 | static int table_send(lua_State *L); |
| 162 | static int net_receive(lua_State *L); | 163 | static int table_receive(lua_State *L); |
| 163 | static int net_timeout(lua_State *L); | 164 | static int table_timeout(lua_State *L); |
| 164 | static int net_close(lua_State *L); | 165 | static int table_close(lua_State *L); |
| 166 | #ifndef LUASOCKET_NOGLOBALS | ||
| 167 | static int global_listen(lua_State *L); | ||
| 168 | static int global_accept(lua_State *L); | ||
| 169 | static int global_send(lua_State *L); | ||
| 170 | static int global_receive(lua_State *L); | ||
| 171 | static int global_timeout(lua_State *L); | ||
| 172 | static int global_close(lua_State *L); | ||
| 173 | static p_sock get_selfclientsock(lua_State *L, p_tags tags); | ||
| 174 | static p_sock get_selfserversock(lua_State *L, p_tags tags); | ||
| 175 | #endif | ||
| 165 | 176 | ||
| 166 | /* buffered I/O management */ | 177 | /* buffered I/O management */ |
| 167 | static const unsigned char *bf_receive(p_sock sock, int *length); | 178 | static const unsigned char *bf_receive(p_sock sock, int *length); |
| @@ -181,18 +192,14 @@ static int receive_dosline(lua_State *L, p_sock sock); | |||
| 181 | static int receive_unixline(lua_State *L, p_sock sock); | 192 | static int receive_unixline(lua_State *L, p_sock sock); |
| 182 | static int receive_all(lua_State *L, p_sock sock); | 193 | static int receive_all(lua_State *L, p_sock sock); |
| 183 | 194 | ||
| 184 | /* fallbacks */ | 195 | /* parameter manipulation functions */ |
| 185 | static int server_gettable(lua_State *L); | 196 | static p_tags pop_tags(lua_State *L); |
| 186 | static int client_gettable(lua_State *L); | 197 | static p_sock pop_sock(lua_State *L); |
| 187 | static int sock_gc(lua_State *L); | 198 | static p_sock get_selfsock(lua_State *L, p_tags tags); |
| 188 | 199 | static int gc_sock(lua_State *L); | |
| 189 | /* argument checking routines */ | 200 | static p_sock push_servertable(lua_State *L, p_tags tags); |
| 190 | static p_sock check_client(lua_State *L, int numArg, int client_tag); | 201 | static p_sock push_clienttable(lua_State *L, p_tags tags); |
| 191 | static p_sock check_server(lua_State *L, int numArg, int server_tag); | 202 | static void push_error(lua_State *L, int err); |
| 192 | static p_sock check_sock(lua_State *L, int numArg, int server_tag, | ||
| 193 | int client_tag); | ||
| 194 | static void pop_tags(lua_State *L, int *client_tag, int *server_tag); | ||
| 195 | static void push_tags(lua_State *L, int client_tag, int server_tag); | ||
| 196 | 203 | ||
| 197 | /* error code translations functions */ | 204 | /* error code translations functions */ |
| 198 | static char *host_strerror(void); | 205 | static char *host_strerror(void); |
| @@ -200,20 +207,17 @@ static char *bind_strerror(void); | |||
| 200 | static char *sock_strerror(void); | 207 | static char *sock_strerror(void); |
| 201 | static char *connect_strerror(void); | 208 | static char *connect_strerror(void); |
| 202 | 209 | ||
| 203 | static void push_error(lua_State *L, int err); | 210 | /* auxiliary functions */ |
| 204 | static void push_client(lua_State *L, p_sock sock, int client_tag); | ||
| 205 | static void push_server(lua_State *L, p_sock sock, int server_tag); | ||
| 206 | |||
| 207 | /* plataform specific functions */ | ||
| 208 | static void set_blocking(p_sock sock); | 211 | static void set_blocking(p_sock sock); |
| 209 | static void set_nonblocking(p_sock sock); | 212 | static void set_nonblocking(p_sock sock); |
| 210 | 213 | static int create_tcpsocket(p_sock sock); | |
| 211 | /* auxiliary functions */ | ||
| 212 | static p_sock create_sock(void); | ||
| 213 | static p_sock create_tcpsock(void); | ||
| 214 | static int fill_sockaddr(struct sockaddr_in *server, const char *hostname, | 214 | static int fill_sockaddr(struct sockaddr_in *server, const char *hostname, |
| 215 | unsigned short port); | 215 | unsigned short port); |
| 216 | 216 | ||
| 217 | #ifdef WIN32 | ||
| 218 | static int winsock_open(void); | ||
| 219 | #endif | ||
| 220 | |||
| 217 | /*=========================================================================*\ | 221 | /*=========================================================================*\ |
| 218 | * Test support functions | 222 | * Test support functions |
| 219 | \*=========================================================================*/ | 223 | \*=========================================================================*/ |
| @@ -221,8 +225,8 @@ static int fill_sockaddr(struct sockaddr_in *server, const char *hostname, | |||
| 221 | /*-------------------------------------------------------------------------*\ | 225 | /*-------------------------------------------------------------------------*\ |
| 222 | * Returns the time the system has been up, in secconds. | 226 | * Returns the time the system has been up, in secconds. |
| 223 | \*-------------------------------------------------------------------------*/ | 227 | \*-------------------------------------------------------------------------*/ |
| 224 | static int net_time(lua_State *L); | 228 | static int global_time(lua_State *L); |
| 225 | static int net_time(lua_State *L) | 229 | static int global_time(lua_State *L) |
| 226 | { | 230 | { |
| 227 | lua_pushnumber(L, tm_gettime()/1000.0); | 231 | lua_pushnumber(L, tm_gettime()/1000.0); |
| 228 | return 1; | 232 | return 1; |
| @@ -231,8 +235,8 @@ static int net_time(lua_State *L) | |||
| 231 | /*-------------------------------------------------------------------------*\ | 235 | /*-------------------------------------------------------------------------*\ |
| 232 | * Causes a Lua script to sleep for the specified number of secconds | 236 | * Causes a Lua script to sleep for the specified number of secconds |
| 233 | \*-------------------------------------------------------------------------*/ | 237 | \*-------------------------------------------------------------------------*/ |
| 234 | static int net_sleep(lua_State *L); | 238 | static int global_sleep(lua_State *L); |
| 235 | static int net_sleep(lua_State *L) | 239 | static int global_sleep(lua_State *L) |
| 236 | { | 240 | { |
| 237 | int sec = (int) luaL_check_number(L, 1); | 241 | int sec = (int) luaL_check_number(L, 1); |
| 238 | #ifdef WIN32 | 242 | #ifdef WIN32 |
| @@ -253,65 +257,87 @@ static int net_sleep(lua_State *L) | |||
| 253 | * Creates a client socket and returns it to the Lua script. The timeout | 257 | * Creates a client socket and returns it to the Lua script. The timeout |
| 254 | * values are initialized as -1 so that the socket will block at any | 258 | * values are initialized as -1 so that the socket will block at any |
| 255 | * IO operation. | 259 | * IO operation. |
| 256 | * Input | 260 | * Lua Input |
| 257 | * host: host name or ip address to connect to | 261 | * host: host name or ip address to connect to |
| 258 | * port: port number on host | 262 | * port: port number on host |
| 259 | * Returns | 263 | * Lua Returns |
| 260 | * On success: client socket | 264 | * On success: client socket |
| 261 | * On error: nil, followed by an error message | 265 | * On error: nil, followed by an error message |
| 262 | \*-------------------------------------------------------------------------*/ | 266 | \*-------------------------------------------------------------------------*/ |
| 263 | static int net_connect(lua_State *L) | 267 | static int global_connect(lua_State *L) |
| 264 | { | 268 | { |
| 269 | p_tags tags = pop_tags(L); | ||
| 265 | const char *hostname = luaL_check_string(L, 1); | 270 | const char *hostname = luaL_check_string(L, 1); |
| 266 | unsigned short port = (unsigned short) luaL_check_number(L, 2); | 271 | unsigned short port = (unsigned short) luaL_check_number(L, 2); |
| 267 | int client_tag, server_tag; | ||
| 268 | struct sockaddr_in server; | 272 | struct sockaddr_in server; |
| 269 | p_sock sock; | 273 | p_sock sock = push_clienttable(L, tags); |
| 270 | pop_tags(L, &client_tag, &server_tag); | ||
| 271 | sock = create_tcpsock(); | ||
| 272 | if (!sock) { | 274 | if (!sock) { |
| 273 | lua_pushnil(L); | 275 | lua_pushnil(L); |
| 276 | lua_pushstring(L, "out of memory"); | ||
| 277 | return 2; | ||
| 278 | } | ||
| 279 | if (!create_tcpsocket(sock)) { | ||
| 280 | lua_pushnil(L); | ||
| 274 | lua_pushstring(L, sock_strerror()); | 281 | lua_pushstring(L, sock_strerror()); |
| 275 | return 2; | 282 | return 2; |
| 276 | } | 283 | } |
| 277 | /* fills the sockaddr structure with the information needed to | 284 | /* fills the sockaddr structure with the information needed to |
| 278 | ** connect our socket with the remote host */ | 285 | ** connect our socket with the remote host */ |
| 279 | if (!fill_sockaddr(&server, hostname, port)) { | 286 | if (!fill_sockaddr(&server, hostname, port)) { |
| 280 | free(sock); | ||
| 281 | lua_pushnil(L); | 287 | lua_pushnil(L); |
| 282 | lua_pushstring(L, host_strerror()); | 288 | lua_pushstring(L, host_strerror()); |
| 283 | return 2; | 289 | return 2; |
| 284 | } | 290 | } |
| 285 | if (connect(sock->sock,(struct sockaddr *)&server,sizeof(server)) < 0) { | 291 | if (connect(sock->sock, (struct sockaddr *)&server, sizeof(server)) < 0) { |
| 286 | /* no connection? we close the socket to free the descriptor */ | 292 | /* no connection? we close the socket to free the descriptor */ |
| 287 | closesocket(sock->sock); | 293 | closesocket(sock->sock); |
| 288 | lua_pushnil(L); | 294 | lua_pushnil(L); |
| 289 | lua_pushstring(L, connect_strerror()); | 295 | lua_pushstring(L, connect_strerror()); |
| 290 | return 2; | 296 | return 2; |
| 291 | } | 297 | } |
| 298 | /* all operations on client sockets are non-blocking */ | ||
| 292 | set_nonblocking(sock); | 299 | set_nonblocking(sock); |
| 293 | push_client(L, sock, client_tag); | ||
| 294 | lua_pushnil(L); | 300 | lua_pushnil(L); |
| 295 | return 2; | 301 | return 2; |
| 296 | } | 302 | } |
| 297 | 303 | ||
| 298 | /*-------------------------------------------------------------------------*\ | 304 | /*-------------------------------------------------------------------------*\ |
| 305 | * Converts from ip number to host name | ||
| 306 | * Lua Input | ||
| 307 | * ip: ip number | ||
| 308 | * Lua Returns | ||
| 309 | * On success: domain name | ||
| 310 | * On error: nil, followed by an error message | ||
| 311 | \*-------------------------------------------------------------------------*/ | ||
| 312 | static int global_toip(lua_State *L) | ||
| 313 | { | ||
| 314 | struct hostent *host; | ||
| 315 | struct in_addr addr; | ||
| 316 | pop_tags(L); | ||
| 317 | host = gethostbyname(luaL_check_string(L, 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 | } | ||
| 327 | |||
| 328 | /*-------------------------------------------------------------------------*\ | ||
| 299 | * Specifies the number of connections that can be queued on a server | 329 | * Specifies the number of connections that can be queued on a server |
| 300 | * socket. | 330 | * socket. |
| 301 | * Input | 331 | * Lua Input |
| 302 | * sock: server socket created by the bind function | 332 | * sock: server socket created by the bind function |
| 303 | * Returns | 333 | * Lua Returns |
| 304 | * On success: nil | 334 | * On success: nil |
| 305 | * On error: an error message | 335 | * On error: an error message |
| 306 | \*-------------------------------------------------------------------------*/ | 336 | \*-------------------------------------------------------------------------*/ |
| 307 | static int net_listen(lua_State *L) | 337 | static int table_listen(lua_State *L) |
| 308 | { | 338 | { |
| 309 | p_sock sock; | 339 | p_sock sock = pop_sock(L); |
| 310 | int client_tag, server_tag; | 340 | unsigned int backlog = (unsigned int) luaL_check_number(L, 2); |
| 311 | unsigned int backlog; | ||
| 312 | pop_tags(L, &client_tag, &server_tag); | ||
| 313 | sock = check_server(L, 1, server_tag); | ||
| 314 | backlog = (unsigned int) luaL_check_number(L, 2); | ||
| 315 | if (listen(sock->sock, backlog) < 0) { | 341 | if (listen(sock->sock, backlog) < 0) { |
| 316 | lua_pushstring(L, "listen error"); | 342 | lua_pushstring(L, "listen error"); |
| 317 | return 1; | 343 | return 1; |
| @@ -324,39 +350,25 @@ static int net_listen(lua_State *L) | |||
| 324 | /*-------------------------------------------------------------------------*\ | 350 | /*-------------------------------------------------------------------------*\ |
| 325 | * Returns a client socket attempting to connect to a server socket. | 351 | * Returns a client socket attempting to connect to a server socket. |
| 326 | * The function blocks until a client shows up. | 352 | * The function blocks until a client shows up. |
| 327 | * Input | 353 | * Lua Input |
| 328 | * sock: server socket created by the bind function | 354 | * sock: server socket created by the bind function |
| 329 | * Returns | 355 | * Lua Returns |
| 330 | * On success: client socket attempting connection | 356 | * On success: client socket attempting connection |
| 331 | * On error: nil followed by an error message | 357 | * On error: nil followed by an error message |
| 332 | \*-------------------------------------------------------------------------*/ | 358 | \*-------------------------------------------------------------------------*/ |
| 333 | static int net_accept(lua_State *L) | 359 | static int table_accept(lua_State *L) |
| 334 | { | 360 | { |
| 335 | struct sockaddr_in client_addr; | 361 | struct sockaddr_in client_addr; |
| 336 | int client_tag, server_tag; | ||
| 337 | p_sock server; | ||
| 338 | int client_sock = -1; | ||
| 339 | size_t client_len = sizeof(client_addr); | 362 | size_t client_len = sizeof(client_addr); |
| 340 | p_sock client; | 363 | p_sock server = pop_sock(L); |
| 341 | pop_tags(L, &client_tag, &server_tag); | 364 | p_tags tags = pop_tags(L); |
| 342 | server = check_server(L, 1, server_tag); | 365 | p_sock client = push_clienttable(L, tags); |
| 343 | /* waits for a connection */ | 366 | SOCKET accepted = accept(server->sock, (struct sockaddr *) &client_addr, |
| 344 | client_sock = accept(server->sock, (struct sockaddr *) &client_addr, | ||
| 345 | &client_len); | 367 | &client_len); |
| 346 | /* we create and return a client socket object, passing the received | 368 | client->sock = accepted; |
| 347 | ** socket to Lua, as a client socket */ | 369 | set_nonblocking(client); |
| 348 | client = create_sock(); | 370 | lua_pushnil(L); |
| 349 | if (!client) { | 371 | return 2; |
| 350 | lua_pushnil(L); | ||
| 351 | lua_pushstring(L, "out of memory"); | ||
| 352 | return 2; | ||
| 353 | } else { | ||
| 354 | client->sock = client_sock; | ||
| 355 | set_nonblocking(client); | ||
| 356 | push_client(L, client, client_tag); | ||
| 357 | lua_pushnil(L); | ||
| 358 | return 2; | ||
| 359 | } | ||
| 360 | } | 372 | } |
| 361 | 373 | ||
| 362 | /*-------------------------------------------------------------------------*\ | 374 | /*-------------------------------------------------------------------------*\ |
| @@ -370,16 +382,15 @@ static int net_accept(lua_State *L) | |||
| 370 | * On success: server socket bound to address, the ip address and port bound | 382 | * On success: server socket bound to address, the ip address and port bound |
| 371 | * On error: nil, followed by an error message | 383 | * On error: nil, followed by an error message |
| 372 | \*-------------------------------------------------------------------------*/ | 384 | \*-------------------------------------------------------------------------*/ |
| 373 | static int net_bind(lua_State *L) | 385 | static int global_bind(lua_State *L) |
| 374 | { | 386 | { |
| 387 | p_tags tags = pop_tags(L); | ||
| 375 | const char *hostname = luaL_check_string(L, 1); | 388 | const char *hostname = luaL_check_string(L, 1); |
| 376 | unsigned short port = (unsigned short) luaL_check_number(L, 2); | 389 | unsigned short port = (unsigned short) luaL_check_number(L, 2); |
| 377 | unsigned int backlog = (unsigned int) luaL_opt_number(L, 3, 1.0); | 390 | unsigned int backlog = (unsigned int) luaL_opt_number(L, 3, 1.0); |
| 378 | struct sockaddr_in server; | 391 | struct sockaddr_in server; |
| 379 | size_t server_size = sizeof(server); | 392 | size_t server_size = sizeof(server); |
| 380 | int client_tag, server_tag; | 393 | p_sock sock = push_servertable(L, tags); |
| 381 | p_sock sock = create_tcpsock(); | ||
| 382 | pop_tags(L, &client_tag, &server_tag); | ||
| 383 | if (!sock) { | 394 | if (!sock) { |
| 384 | lua_pushnil(L); | 395 | lua_pushnil(L); |
| 385 | lua_pushstring(L, sock_strerror()); | 396 | lua_pushstring(L, sock_strerror()); |
| @@ -406,8 +417,6 @@ static int net_bind(lua_State *L) | |||
| 406 | } | 417 | } |
| 407 | /* pass the created socket to Lua, as a server socket */ | 418 | /* pass the created socket to Lua, as a server socket */ |
| 408 | else { | 419 | else { |
| 409 | /* pass server */ | ||
| 410 | push_server(L, sock, server_tag); | ||
| 411 | /* get used address and port */ | 420 | /* get used address and port */ |
| 412 | getsockname(sock->sock, (struct sockaddr *)&server, &server_size); | 421 | getsockname(sock->sock, (struct sockaddr *)&server, &server_size); |
| 413 | /* pass ip number */ | 422 | /* pass ip number */ |
| @@ -421,26 +430,19 @@ static int net_bind(lua_State *L) | |||
| 421 | 430 | ||
| 422 | /*-------------------------------------------------------------------------*\ | 431 | /*-------------------------------------------------------------------------*\ |
| 423 | * Sets timeout values for IO operations on a client socket | 432 | * Sets timeout values for IO operations on a client socket |
| 424 | * Input | 433 | * Lua Input |
| 425 | * sock: client socket created by the connect function | 434 | * sock: client socket created by the connect function |
| 426 | * time: time out value in seconds | 435 | * time: time out value in seconds |
| 427 | * mode: optional timeout mode. "block" specifies the upper bound on | 436 | * mode: optional timeout mode. "block" specifies the upper bound on |
| 428 | * the time any IO operation on sock can cause the program to block. | 437 | * the time any IO operation on sock can cause the program to block. |
| 429 | * "return" specifies the upper bound on the time elapsed before the | 438 | * "return" specifies the upper bound on the time elapsed before the |
| 430 | * function returns control to the script. "block" is the default. | 439 | * function returns control to the script. "block" is the default. |
| 431 | * Returns | ||
| 432 | * no return value | ||
| 433 | \*-------------------------------------------------------------------------*/ | 440 | \*-------------------------------------------------------------------------*/ |
| 434 | static int net_timeout(lua_State *L) | 441 | static int table_timeout(lua_State *L) |
| 435 | { | 442 | { |
| 436 | int client_tag, server_tag; | 443 | p_sock sock = pop_sock(L); |
| 437 | p_sock sock; | 444 | int ms = (int) (luaL_check_number(L, 2)*1000.0); |
| 438 | int ms; | 445 | const char *mode = luaL_opt_string(L, 3, "b"); |
| 439 | const char *mode; | ||
| 440 | pop_tags(L, &client_tag, &server_tag); | ||
| 441 | sock = check_client(L, 1, client_tag); | ||
| 442 | ms = (int) (luaL_check_number(L, 2)*1000.0); | ||
| 443 | mode = luaL_opt_string(L, 3, "b"); | ||
| 444 | switch (*mode) { | 446 | switch (*mode) { |
| 445 | case 'b': | 447 | case 'b': |
| 446 | sock->tm_block = ms; | 448 | sock->tm_block = ms; |
| @@ -457,34 +459,30 @@ static int net_timeout(lua_State *L) | |||
| 457 | 459 | ||
| 458 | /*-------------------------------------------------------------------------*\ | 460 | /*-------------------------------------------------------------------------*\ |
| 459 | * Send data through a socket | 461 | * Send data through a socket |
| 460 | * Input: sock, a_1 [, a_2, a_3 ... a_n] | 462 | * Lua Input: sock, a_1 [, a_2, a_3 ... a_n] |
| 461 | * sock: client socket created by the connect function | 463 | * sock: client socket created by the connect function |
| 462 | * a_i: strings to be sent. The strings will be sent on the order they | 464 | * a_i: strings to be sent. The strings will be sent on the order they |
| 463 | * appear as parameters | 465 | * appear as parameters |
| 464 | * Returns | 466 | * Lua Returns |
| 465 | * On success: nil, followed by the total number of bytes sent | 467 | * On success: nil, followed by the total number of bytes sent |
| 466 | * On error: NET_TIMEOUT if the connection timedout, or NET_CLOSED if | 468 | * On error: NET_TIMEOUT if the connection timedout, or NET_CLOSED if |
| 467 | * the connection has been closed, followed by the total number of | 469 | * the connection has been closed, followed by the total number of |
| 468 | * bytes sent | 470 | * bytes sent |
| 469 | \*-------------------------------------------------------------------------*/ | 471 | \*-------------------------------------------------------------------------*/ |
| 470 | static int net_send(lua_State *L) | 472 | static int table_send(lua_State *L) |
| 471 | { | 473 | { |
| 472 | p_sock sock; | ||
| 473 | const char *data; | ||
| 474 | int wanted; | ||
| 475 | long total = 0; | ||
| 476 | int arg; | 474 | int arg; |
| 475 | p_sock sock = pop_sock(L); | ||
| 476 | int top = lua_gettop(L); | ||
| 477 | int total = 0; | ||
| 477 | int err = NET_DONE; | 478 | int err = NET_DONE; |
| 478 | int top; | ||
| 479 | int client_tag, server_tag; | ||
| 480 | pop_tags(L, &client_tag, &server_tag); | ||
| 481 | top = lua_gettop(L); | ||
| 482 | sock = check_client(L, 1, client_tag); | ||
| 483 | tm_markstart(sock); | 479 | tm_markstart(sock); |
| 484 | for (arg = 2; arg <= top; arg++) { | 480 | for (arg = 2; arg <= top; arg++) { /* skip self table */ |
| 485 | data = luaL_opt_lstr(L, arg, NULL, &wanted); | 481 | int sent, wanted; |
| 482 | const char *data = luaL_opt_lstr(L, arg, NULL, &wanted); | ||
| 486 | if (!data || err != NET_DONE) break; | 483 | if (!data || err != NET_DONE) break; |
| 487 | total += send_raw(sock, data, wanted, &err); | 484 | err = send_raw(sock, data, wanted, &sent); |
| 485 | total += sent; | ||
| 488 | } | 486 | } |
| 489 | push_error(L, err); | 487 | push_error(L, err); |
| 490 | lua_pushnumber(L, (double) total); | 488 | lua_pushnumber(L, (double) total); |
| @@ -497,7 +495,7 @@ static int net_send(lua_State *L) | |||
| 497 | 495 | ||
| 498 | /*-------------------------------------------------------------------------*\ | 496 | /*-------------------------------------------------------------------------*\ |
| 499 | * Receive data from a socket | 497 | * Receive data from a socket |
| 500 | * Input: sock [pat_1, pat_2 ... pat_n] | 498 | * Lua Input: sock [pat_1, pat_2 ... pat_n] |
| 501 | * sock: client socket created by the connect function | 499 | * sock: client socket created by the connect function |
| 502 | * pat_i: may be one of the following | 500 | * pat_i: may be one of the following |
| 503 | * "*l": reads a text line, defined as a string of caracters terminates | 501 | * "*l": reads a text line, defined as a string of caracters terminates |
| @@ -506,24 +504,21 @@ static int net_send(lua_State *L) | |||
| 506 | * "*lu": reads a text line, terminanted by a CR character only. (Unix mode) | 504 | * "*lu": reads a text line, terminanted by a CR character only. (Unix mode) |
| 507 | * "*a": reads until connection closed | 505 | * "*a": reads until connection closed |
| 508 | * number: reads 'number' characters from the socket | 506 | * number: reads 'number' characters from the socket |
| 509 | * Returns | 507 | * Lua Returns |
| 510 | * On success: one string for each pattern | 508 | * On success: one string for each pattern |
| 511 | * On error: all strings for which there was no error, followed by one | 509 | * On error: all strings for which there was no error, followed by one |
| 512 | * nil value for the remaining strings, followed by an error code | 510 | * nil value for the remaining strings, followed by an error code |
| 513 | \*-------------------------------------------------------------------------*/ | 511 | \*-------------------------------------------------------------------------*/ |
| 514 | static int net_receive(lua_State *L) | 512 | static int table_receive(lua_State *L) |
| 515 | { | 513 | { |
| 516 | static const char *const modenames[] = {"*l", "*lu", "*a", NULL}; | 514 | static const char *const modenames[] = {"*l", "*lu", "*a", NULL}; |
| 517 | int err = NET_DONE, arg = 2; | ||
| 518 | const char *mode; | 515 | const char *mode; |
| 519 | int client_tag, server_tag; | 516 | int err = NET_DONE; |
| 520 | int top; | 517 | int arg; |
| 521 | p_sock sock; | 518 | p_sock sock = pop_sock(L); |
| 522 | pop_tags(L, &client_tag, &server_tag); | 519 | int top = lua_gettop(L); |
| 523 | sock = check_client(L, 1, client_tag); | ||
| 524 | tm_markstart(sock); | 520 | tm_markstart(sock); |
| 525 | /* push default pattern */ | 521 | /* push default pattern if need be */ |
| 526 | top = lua_gettop(L); | ||
| 527 | if (top < 2) { | 522 | if (top < 2) { |
| 528 | lua_pushstring(L, "*l"); | 523 | lua_pushstring(L, "*l"); |
| 529 | top++; | 524 | top++; |
| @@ -536,7 +531,7 @@ static int net_receive(lua_State *L) | |||
| 536 | continue; | 531 | continue; |
| 537 | } | 532 | } |
| 538 | if (lua_isnumber(L, arg)) { | 533 | if (lua_isnumber(L, arg)) { |
| 539 | long size = (long) lua_tonumber(L, arg); | 534 | int size = (int) lua_tonumber(L, arg); |
| 540 | err = receive_raw(L, sock, size); | 535 | err = receive_raw(L, sock, size); |
| 541 | } else { | 536 | } else { |
| 542 | mode = luaL_opt_string(L, arg, NULL); | 537 | mode = luaL_opt_string(L, arg, NULL); |
| @@ -572,104 +567,30 @@ static int net_receive(lua_State *L) | |||
| 572 | 567 | ||
| 573 | /*-------------------------------------------------------------------------*\ | 568 | /*-------------------------------------------------------------------------*\ |
| 574 | * Closes a socket. | 569 | * Closes a socket. |
| 575 | * Input | 570 | * Lua Input |
| 576 | * sock: socket to be closed | 571 | * sock: socket to be closed |
| 577 | \*-------------------------------------------------------------------------*/ | 572 | \*-------------------------------------------------------------------------*/ |
| 578 | static int net_close(lua_State *L) | 573 | static int table_close(lua_State *L) |
| 579 | { | 574 | { |
| 580 | int client_tag, server_tag; | 575 | /* close socket and set value to -1 so that pop_socket can later |
| 581 | p_sock sock; | 576 | ** detect the use of a closed socket */ |
| 582 | pop_tags(L, &client_tag, &server_tag); | 577 | p_sock sock = pop_sock(L); |
| 583 | sock = check_sock(L, 1, client_tag, server_tag); | ||
| 584 | closesocket(sock->sock); | 578 | closesocket(sock->sock); |
| 585 | /* set value to -1 so that we can later detect the use of a | ||
| 586 | ** closed socket */ | ||
| 587 | sock->sock = -1; | 579 | sock->sock = -1; |
| 588 | return 0; | 580 | return 0; |
| 589 | } | 581 | } |
| 590 | 582 | ||
| 591 | /*-------------------------------------------------------------------------*\ | 583 | /*-------------------------------------------------------------------------*\ |
| 592 | * Gettable fallback for the client socket. This function provides the | ||
| 593 | * alternative interface client:receive, client:send etc for the client | ||
| 594 | * socket methods. | ||
| 595 | \*-------------------------------------------------------------------------*/ | ||
| 596 | static int client_gettable(lua_State *L) | ||
| 597 | { | ||
| 598 | static const char *const net_api[] = | ||
| 599 | {"receive","send","timeout","close", "connect", NULL}; | ||
| 600 | const char *idx = luaL_check_string(L, 2); | ||
| 601 | int server_tag, client_tag; | ||
| 602 | pop_tags(L, &client_tag, &server_tag); | ||
| 603 | switch (luaL_findstring(idx, net_api)) { | ||
| 604 | case 0: | ||
| 605 | push_tags(L, client_tag, server_tag); | ||
| 606 | lua_pushcclosure(L, net_receive, 2); | ||
| 607 | break; | ||
| 608 | case 1: | ||
| 609 | push_tags(L, client_tag, server_tag); | ||
| 610 | lua_pushcclosure(L, net_send, 2); | ||
| 611 | break; | ||
| 612 | case 2: | ||
| 613 | push_tags(L, client_tag, server_tag); | ||
| 614 | lua_pushcclosure(L, net_timeout, 2); | ||
| 615 | break; | ||
| 616 | case 3: | ||
| 617 | push_tags(L, client_tag, server_tag); | ||
| 618 | lua_pushcclosure(L, net_close, 2); | ||
| 619 | break; | ||
| 620 | default: | ||
| 621 | lua_pushnil(L); | ||
| 622 | break; | ||
| 623 | } | ||
| 624 | return 1; | ||
| 625 | } | ||
| 626 | |||
| 627 | /*-------------------------------------------------------------------------*\ | ||
| 628 | * Gettable fallback for the server socket. This function provides the | ||
| 629 | * alternative interface server:listen, server:accept etc for the server | ||
| 630 | * socket methods. | ||
| 631 | \*-------------------------------------------------------------------------*/ | ||
| 632 | static int server_gettable(lua_State *L) | ||
| 633 | { | ||
| 634 | static const char *const net_api[] = {"listen","accept","close", NULL}; | ||
| 635 | const char *idx = luaL_check_string(L, 2); | ||
| 636 | int server_tag, client_tag; | ||
| 637 | pop_tags(L, &client_tag, &server_tag); | ||
| 638 | switch (luaL_findstring(idx, net_api)) { | ||
| 639 | case 0: | ||
| 640 | push_tags(L, client_tag, server_tag); | ||
| 641 | lua_pushcclosure(L, net_listen, 2); | ||
| 642 | break; | ||
| 643 | case 1: | ||
| 644 | push_tags(L, client_tag, server_tag); | ||
| 645 | lua_pushcclosure(L, net_accept, 2); | ||
| 646 | break; | ||
| 647 | case 2: | ||
| 648 | push_tags(L, client_tag, server_tag); | ||
| 649 | lua_pushcclosure(L, net_close, 2); | ||
| 650 | break; | ||
| 651 | default: | ||
| 652 | lua_pushnil(L); | ||
| 653 | break; | ||
| 654 | } | ||
| 655 | return 1; | ||
| 656 | } | ||
| 657 | |||
| 658 | /*-------------------------------------------------------------------------*\ | ||
| 659 | * Garbage collection fallback for the socket objects. This function | 584 | * Garbage collection fallback for the socket objects. This function |
| 660 | * makes sure that all collected sockets are closed and that the memory | 585 | * makes sure that all collected sockets are closed. |
| 661 | * used by the C structure t_sock is properly released. | ||
| 662 | \*-------------------------------------------------------------------------*/ | 586 | \*-------------------------------------------------------------------------*/ |
| 663 | static int sock_gc(lua_State *L) | 587 | static int gc_sock(lua_State *L) |
| 664 | { | 588 | { |
| 665 | int server_tag, client_tag; | 589 | p_tags tags = pop_tags(L); |
| 666 | p_sock sock; | 590 | p_sock sock = get_selfsock(L, tags); |
| 667 | pop_tags(L, &client_tag, &server_tag); | 591 | /* sock might have been closed */ |
| 668 | sock = check_sock(L, 1, client_tag, server_tag); | 592 | if (sock->sock >= 0) closesocket(sock->sock); |
| 669 | if (sock->sock >= 0) | 593 | return 0; |
| 670 | closesocket(sock->sock); | ||
| 671 | free(sock); | ||
| 672 | return 1; | ||
| 673 | } | 594 | } |
| 674 | 595 | ||
| 675 | /*=========================================================================*\ | 596 | /*=========================================================================*\ |
| @@ -692,34 +613,16 @@ static void handle_sigpipe(void) | |||
| 692 | #endif | 613 | #endif |
| 693 | 614 | ||
| 694 | /*-------------------------------------------------------------------------*\ | 615 | /*-------------------------------------------------------------------------*\ |
| 695 | * Creates a t_sock structure with default values. | ||
| 696 | \*-------------------------------------------------------------------------*/ | ||
| 697 | static p_sock create_sock(void) | ||
| 698 | { | ||
| 699 | p_sock sock = (p_sock) malloc(sizeof(t_sock)); | ||
| 700 | if (!sock) return NULL; | ||
| 701 | sock->sock = -1; | ||
| 702 | sock->tm_block = -1; | ||
| 703 | sock->tm_return = -1; | ||
| 704 | sock->bf_first = sock->bf_last = 0; | ||
| 705 | return sock; | ||
| 706 | } | ||
| 707 | |||
| 708 | /*-------------------------------------------------------------------------*\ | ||
| 709 | * Creates a TCP/IP socket. | 616 | * Creates a TCP/IP socket. |
| 617 | * Input | ||
| 618 | * sock: structure to receive new socket | ||
| 710 | * Returns | 619 | * Returns |
| 711 | * A pointer to a t_sock structure or NULL in case of error | 620 | * 1 if successfull, 0 in case or error |
| 712 | \*-------------------------------------------------------------------------*/ | 621 | \*-------------------------------------------------------------------------*/ |
| 713 | static p_sock create_tcpsock(void) | 622 | static int create_tcpsocket(p_sock sock) |
| 714 | { | 623 | { |
| 715 | p_sock sock = create_sock(); | ||
| 716 | if (!sock) | ||
| 717 | return NULL; | ||
| 718 | sock->sock = socket(AF_INET, SOCK_STREAM, 0); | 624 | sock->sock = socket(AF_INET, SOCK_STREAM, 0); |
| 719 | if (sock->sock < 0) { | 625 | if (sock->sock < 0) return 0; |
| 720 | free(sock); | ||
| 721 | sock = NULL; | ||
| 722 | } | ||
| 723 | #ifdef _DEBUG | 626 | #ifdef _DEBUG |
| 724 | /* this allow us to re-bind onto an address even if there is still | 627 | /* this allow us to re-bind onto an address even if there is still |
| 725 | ** a TIME_WAIT condition. debugging is much more confortable, because | 628 | ** a TIME_WAIT condition. debugging is much more confortable, because |
| @@ -733,7 +636,7 @@ static p_sock create_tcpsock(void) | |||
| 733 | sizeof(val)); | 636 | sizeof(val)); |
| 734 | } | 637 | } |
| 735 | #endif | 638 | #endif |
| 736 | return sock; | 639 | return 1; |
| 737 | } | 640 | } |
| 738 | 641 | ||
| 739 | /*-------------------------------------------------------------------------*\ | 642 | /*-------------------------------------------------------------------------*\ |
| @@ -756,10 +659,8 @@ static int fill_sockaddr(struct sockaddr_in *address, const char *hostname, | |||
| 756 | /* BSD says we could have used gethostbyname even if the hostname is | 659 | /* BSD says we could have used gethostbyname even if the hostname is |
| 757 | ** in ip address form, but WinSock2 says we can't. Therefore we | 660 | ** in ip address form, but WinSock2 says we can't. Therefore we |
| 758 | ** choose a method that works on both plataforms */ | 661 | ** choose a method that works on both plataforms */ |
| 759 | if (addr == INADDR_NONE) | 662 | if (addr == INADDR_NONE) host = gethostbyname(hostname); |
| 760 | host = gethostbyname(hostname); | 663 | else host = gethostbyaddr((char * ) &addr, sizeof(unsigned long), |
| 761 | else | ||
| 762 | host = gethostbyaddr((char * ) &addr, sizeof(unsigned long), | ||
| 763 | AF_INET); | 664 | AF_INET); |
| 764 | if (!host) | 665 | if (!host) |
| 765 | return 0; | 666 | return 0; |
| @@ -773,6 +674,87 @@ static int fill_sockaddr(struct sockaddr_in *address, const char *hostname, | |||
| 773 | } | 674 | } |
| 774 | 675 | ||
| 775 | /*-------------------------------------------------------------------------*\ | 676 | /*-------------------------------------------------------------------------*\ |
| 677 | * Creates a t_sock structure with default values for a client sock. | ||
| 678 | * Pushes the Lua table with sock fields and appropriate methods | ||
| 679 | * Input | ||
| 680 | * tags: tags structure | ||
| 681 | * Returns | ||
| 682 | * pointer to allocated t_sock structure, NULL in case of error | ||
| 683 | \*-------------------------------------------------------------------------*/ | ||
| 684 | static p_sock push_clienttable(lua_State *L, p_tags tags) | ||
| 685 | { | ||
| 686 | static struct luaL_reg funcs[] = { | ||
| 687 | {"send", table_send}, | ||
| 688 | {"receive", table_receive}, | ||
| 689 | {"close", table_close}, | ||
| 690 | {"timeout", table_timeout}, | ||
| 691 | }; | ||
| 692 | int i; | ||
| 693 | p_sock sock; | ||
| 694 | lua_newtable(L); lua_settag(L, tags->table); | ||
| 695 | lua_pushstring(L, P_SOCK); | ||
| 696 | sock = (p_sock) lua_newuserdata(L, sizeof(t_sock)); | ||
| 697 | if (!sock) lua_error(L, "out of memory"); | ||
| 698 | lua_settag(L, tags->client); | ||
| 699 | lua_settable(L, -3); | ||
| 700 | sock->sock = -1; | ||
| 701 | sock->tm_block = -1; | ||
| 702 | sock->tm_return = -1; | ||
| 703 | sock->bf_first = sock->bf_last = 0; | ||
| 704 | for (i = 0; i < sizeof(funcs)/sizeof(funcs[0]); i++) { | ||
| 705 | lua_pushstring(L, funcs[i].name); | ||
| 706 | lua_pushusertag(L, sock, tags->client); | ||
| 707 | lua_pushcclosure(L, funcs[i].func, 1); | ||
| 708 | lua_settable(L, -3); | ||
| 709 | } | ||
| 710 | return sock; | ||
| 711 | } | ||
| 712 | |||
| 713 | /*-------------------------------------------------------------------------*\ | ||
| 714 | * Creates a t_sock structure with default values for a server sock. | ||
| 715 | * Pushes the Lua table with sock fields and appropriate methods | ||
| 716 | * Input | ||
| 717 | * tags: tags structure | ||
| 718 | * Returns | ||
| 719 | * pointer to allocated t_sock structure, NULL in case of error | ||
| 720 | \*-------------------------------------------------------------------------*/ | ||
| 721 | static p_sock push_servertable(lua_State *L, p_tags tags) | ||
| 722 | { | ||
| 723 | static struct luaL_reg funcs[] = { | ||
| 724 | {"listen", table_listen}, | ||
| 725 | {"close", table_close}, | ||
| 726 | }; | ||
| 727 | int i; | ||
| 728 | p_sock sock; | ||
| 729 | lua_newtable(L); lua_settag(L, tags->table); | ||
| 730 | lua_pushstring(L, P_SOCK); | ||
| 731 | sock = (p_sock) lua_newuserdata(L, sizeof(t_sock)); | ||
| 732 | if (!sock) lua_error(L, "out of memory"); | ||
| 733 | lua_settag(L, tags->server); | ||
| 734 | lua_settable(L, -3); | ||
| 735 | if (!create_tcpsocket(sock)) return NULL; | ||
| 736 | sock->tm_block = -1; | ||
| 737 | sock->tm_return = -1; | ||
| 738 | sock->bf_first = sock->bf_last = 0; | ||
| 739 | for (i = 0; i < sizeof(funcs)/sizeof(funcs[0]); i++) { | ||
| 740 | lua_pushstring(L, funcs[i].name); | ||
| 741 | lua_pushusertag(L, sock, tags->client); | ||
| 742 | lua_pushcclosure(L, funcs[i].func, 1); | ||
| 743 | lua_settable(L, -3); | ||
| 744 | } | ||
| 745 | /* the accept method is different, it needs the tags closure too */ | ||
| 746 | lua_pushstring(L, "accept"); | ||
| 747 | lua_pushuserdata(L, tags); | ||
| 748 | lua_pushusertag(L, sock, tags->client); | ||
| 749 | lua_pushcclosure(L, table_accept, 2); | ||
| 750 | lua_settable(L, -3); | ||
| 751 | return sock; | ||
| 752 | } | ||
| 753 | |||
| 754 | /*=========================================================================*\ | ||
| 755 | * Timeout management functions | ||
| 756 | \*=========================================================================*/ | ||
| 757 | /*-------------------------------------------------------------------------*\ | ||
| 776 | * Determines how much time we have left for the current io operation | 758 | * Determines how much time we have left for the current io operation |
| 777 | * an IO write operation. | 759 | * an IO write operation. |
| 778 | * Input | 760 | * Input |
| @@ -827,7 +809,7 @@ static int tm_timedout(p_sock sock, int mode) | |||
| 827 | /* see if we can read or write or if we timedout */ | 809 | /* see if we can read or write or if we timedout */ |
| 828 | ret = select(sock->sock+1, preadfds, pwritefds, NULL, ptm); | 810 | ret = select(sock->sock+1, preadfds, pwritefds, NULL, ptm); |
| 829 | #ifdef _DEBUG | 811 | #ifdef _DEBUG |
| 830 | /* store end time for this operation before calling select */ | 812 | /* store end time for this operation next call to OS */ |
| 831 | sock->tm_end = tm_gettime(); | 813 | sock->tm_end = tm_gettime(); |
| 832 | #endif | 814 | #endif |
| 833 | return ret <= 0; | 815 | return ret <= 0; |
| @@ -847,6 +829,24 @@ static void tm_markstart(p_sock sock) | |||
| 847 | } | 829 | } |
| 848 | 830 | ||
| 849 | /*-------------------------------------------------------------------------*\ | 831 | /*-------------------------------------------------------------------------*\ |
| 832 | * Gets time in ms, relative to system startup. | ||
| 833 | * Returns | ||
| 834 | * time in ms. | ||
| 835 | \*-------------------------------------------------------------------------*/ | ||
| 836 | static int tm_gettime(void) | ||
| 837 | { | ||
| 838 | #ifdef _WIN32 | ||
| 839 | return GetTickCount(); | ||
| 840 | #else | ||
| 841 | struct tms t; | ||
| 842 | return (times(&t)*1000)/CLK_TCK; | ||
| 843 | #endif | ||
| 844 | } | ||
| 845 | |||
| 846 | /*=========================================================================*\ | ||
| 847 | * Buffered I/O management functions | ||
| 848 | \*=========================================================================*/ | ||
| 849 | /*-------------------------------------------------------------------------*\ | ||
| 850 | * Determines of there is any data in the read buffer | 850 | * Determines of there is any data in the read buffer |
| 851 | * Input | 851 | * Input |
| 852 | * sock: socket structure being used in operation | 852 | * sock: socket structure being used in operation |
| @@ -892,21 +892,9 @@ static const unsigned char *bf_receive(p_sock sock, int *length) | |||
| 892 | return sock->bf_buffer + sock->bf_first; | 892 | return sock->bf_buffer + sock->bf_first; |
| 893 | } | 893 | } |
| 894 | 894 | ||
| 895 | /*-------------------------------------------------------------------------*\ | 895 | /*=========================================================================*\ |
| 896 | * Gets time in ms, relative to system startup. | 896 | * These are the function that are called for each I/O pattern |
| 897 | * Returns | 897 | \*=========================================================================*/ |
| 898 | * time in ms. | ||
| 899 | \*-------------------------------------------------------------------------*/ | ||
| 900 | static int tm_gettime(void) | ||
| 901 | { | ||
| 902 | #ifdef _WIN32 | ||
| 903 | return GetTickCount(); | ||
| 904 | #else | ||
| 905 | struct tms t; | ||
| 906 | return (times(&t)*1000)/CLK_TCK; | ||
| 907 | #endif | ||
| 908 | } | ||
| 909 | |||
| 910 | /*-------------------------------------------------------------------------*\ | 898 | /*-------------------------------------------------------------------------*\ |
| 911 | * Sends a raw block of data through a socket. The operations are all | 899 | * Sends a raw block of data through a socket. The operations are all |
| 912 | * non-blocking and the function respects the timeout values in sock. | 900 | * non-blocking and the function respects the timeout values in sock. |
| @@ -915,29 +903,32 @@ static int tm_gettime(void) | |||
| 915 | * data: buffer to be sent | 903 | * data: buffer to be sent |
| 916 | * wanted: number of bytes in buffer | 904 | * wanted: number of bytes in buffer |
| 917 | * Output | 905 | * Output |
| 918 | * err: operation error code. NET_DONE, NET_TIMEOUT or NET_CLOSED | 906 | * total: Number of bytes written |
| 919 | * Returns | 907 | * Returns |
| 920 | * Number of bytes written | 908 | * operation error code. NET_DONE, NET_TIMEOUT or NET_CLOSED |
| 921 | \*-------------------------------------------------------------------------*/ | 909 | \*-------------------------------------------------------------------------*/ |
| 922 | static int send_raw(p_sock sock, const char *data, int wanted, int *err) | 910 | static int send_raw(p_sock sock, const char *data, int wanted, int *total) |
| 923 | { | 911 | { |
| 924 | int put = 0, total = 0; | 912 | int put = 0; |
| 913 | *total = 0; | ||
| 925 | while (wanted > 0) { | 914 | while (wanted > 0) { |
| 926 | if (tm_timedout(sock, TM_SEND)) { | 915 | if (tm_timedout(sock, TM_SEND)) return NET_TIMEOUT; |
| 927 | *err = NET_TIMEOUT; | ||
| 928 | return total; | ||
| 929 | } | ||
| 930 | put = send(sock->sock, data, wanted, 0); | 916 | put = send(sock->sock, data, wanted, 0); |
| 931 | if (put <= 0) { | 917 | if (put <= 0) { |
| 932 | *err = NET_CLOSED; | 918 | #ifdef WIN32 |
| 933 | return total; | 919 | /* a bug in WinSock forces us to do a busy wait until we manage |
| 920 | ** to write, because select returns immediately even though it | ||
| 921 | ** should have blocked us */ | ||
| 922 | if (WSAGetLastError() == WSAEWOULDBLOCK) | ||
| 923 | continue; | ||
| 924 | #endif | ||
| 925 | return NET_CLOSED; | ||
| 934 | } | 926 | } |
| 935 | wanted -= put; | 927 | wanted -= put; |
| 936 | data += put; | 928 | data += put; |
| 937 | total += put; | 929 | *total += put; |
| 938 | } | 930 | } |
| 939 | *err = NET_DONE; | 931 | return NET_DONE; |
| 940 | return total; | ||
| 941 | } | 932 | } |
| 942 | 933 | ||
| 943 | /*-------------------------------------------------------------------------*\ | 934 | /*-------------------------------------------------------------------------*\ |
| @@ -989,16 +980,16 @@ static int receive_all(lua_State *L, p_sock sock) | |||
| 989 | luaL_buffinit(L, &b); | 980 | luaL_buffinit(L, &b); |
| 990 | for ( ;; ) { | 981 | for ( ;; ) { |
| 991 | if (bf_isempty(sock) && tm_timedout(sock, TM_RECEIVE)) { | 982 | if (bf_isempty(sock) && tm_timedout(sock, TM_RECEIVE)) { |
| 992 | buffer = bf_receive(sock, &got); | ||
| 993 | if (got <= 0) { | ||
| 994 | luaL_pushresult(&b); | ||
| 995 | return NET_DONE; | ||
| 996 | } | ||
| 997 | luaL_addlstring(&b, buffer, got); | ||
| 998 | } else { | ||
| 999 | luaL_pushresult(&b); | 983 | luaL_pushresult(&b); |
| 1000 | return NET_TIMEOUT; | 984 | return NET_TIMEOUT; |
| 985 | } | ||
| 986 | buffer = bf_receive(sock, &got); | ||
| 987 | if (got <= 0) { | ||
| 988 | luaL_pushresult(&b); | ||
| 989 | return NET_DONE; | ||
| 1001 | } | 990 | } |
| 991 | luaL_addlstring(&b, buffer, got); | ||
| 992 | bf_skip(sock, got); | ||
| 1002 | } | 993 | } |
| 1003 | } | 994 | } |
| 1004 | 995 | ||
| @@ -1088,18 +1079,125 @@ static int receive_unixline(lua_State *L, p_sock sock) | |||
| 1088 | } | 1079 | } |
| 1089 | } | 1080 | } |
| 1090 | 1081 | ||
| 1082 | /*=========================================================================*\ | ||
| 1083 | * Module exported functions | ||
| 1084 | \*=========================================================================*/ | ||
| 1091 | /*-------------------------------------------------------------------------*\ | 1085 | /*-------------------------------------------------------------------------*\ |
| 1092 | * Pops tags from closures | 1086 | * Initializes the library interface with Lua and the socket library. |
| 1093 | * Input | 1087 | * Defines the symbols exported to Lua. |
| 1094 | * L: lua environment | ||
| 1095 | \*-------------------------------------------------------------------------*/ | 1088 | \*-------------------------------------------------------------------------*/ |
| 1096 | static void pop_tags(lua_State *L, int *client_tag, int *server_tag) | 1089 | void lua_socketlibopen(lua_State *L) |
| 1097 | { | 1090 | { |
| 1098 | *client_tag = (int) lua_tonumber(L, CLIENT_TAG); | 1091 | static struct luaL_reg funcs[] = { |
| 1099 | *server_tag = (int) lua_tonumber(L, SERVER_TAG); | 1092 | {"connect", global_connect}, |
| 1100 | lua_pop(L, 2); | 1093 | {"bind", global_bind}, |
| 1094 | {"toip", global_toip}, | ||
| 1095 | }; | ||
| 1096 | int i; | ||
| 1097 | /* declare new Lua tags for used userdata values */ | ||
| 1098 | p_tags tags = (p_tags) lua_newuserdata(L, sizeof(t_tags)); | ||
| 1099 | if (!tags) lua_error(L, "out of memory"); | ||
| 1100 | tags->client = lua_newtag(L); | ||
| 1101 | tags->server = lua_newtag(L); | ||
| 1102 | tags->table = lua_newtag(L); | ||
| 1103 | /* global functions exported */ | ||
| 1104 | for (i = 0; i < sizeof(funcs)/sizeof(funcs[0]); i++) { | ||
| 1105 | lua_pushuserdata(L, tags); | ||
| 1106 | lua_pushcclosure(L, funcs[i].func, 1); | ||
| 1107 | lua_setglobal(L, funcs[i].name); | ||
| 1108 | } | ||
| 1109 | /* socket garbage collection */ | ||
| 1110 | lua_pushuserdata(L, tags); | ||
| 1111 | lua_pushcclosure(L, gc_sock, 1); | ||
| 1112 | lua_settagmethod(L, tags->table, "gc"); | ||
| 1113 | |||
| 1114 | #ifndef LUASOCKET_NOGLOBALS | ||
| 1115 | /* global version of socket table functions */ | ||
| 1116 | { static struct luaL_reg opt_funcs[] = { | ||
| 1117 | {"send", global_send}, | ||
| 1118 | {"receive", global_receive}, | ||
| 1119 | {"accept", global_accept}, | ||
| 1120 | {"close", global_close}, | ||
| 1121 | {"timeout", global_timeout}, | ||
| 1122 | {"listen", global_listen}, | ||
| 1123 | }; | ||
| 1124 | for (i = 0; i < sizeof(opt_funcs)/sizeof(opt_funcs[0]); i++) { | ||
| 1125 | lua_pushuserdata(L, tags); | ||
| 1126 | lua_pushcclosure(L, opt_funcs[i].func, 1); | ||
| 1127 | lua_setglobal(L, opt_funcs[i].name); | ||
| 1128 | } | ||
| 1129 | } | ||
| 1130 | #endif | ||
| 1131 | #ifdef WIN32 | ||
| 1132 | /* WinSock needs special initialization */ | ||
| 1133 | winsock_open(); | ||
| 1134 | #else | ||
| 1135 | /* avoid getting killed by a SIGPIPE signal thrown by send */ | ||
| 1136 | handle_sigpipe(); | ||
| 1137 | #endif | ||
| 1138 | #ifdef _DEBUG | ||
| 1139 | /* test support functions */ | ||
| 1140 | lua_pushcfunction(L, global_sleep); lua_setglobal(L, "sleep"); | ||
| 1141 | lua_pushcfunction(L, global_time); lua_setglobal(L, "time"); | ||
| 1142 | #endif | ||
| 1143 | /* avoid stupid compiler warnings */ | ||
| 1144 | (void) set_blocking; | ||
| 1145 | } | ||
| 1146 | |||
| 1147 | /*=========================================================================*\ | ||
| 1148 | * Optional global version of socket table methods | ||
| 1149 | \*=========================================================================*/ | ||
| 1150 | #ifndef LUASOCKET_NOGLOBALS | ||
| 1151 | int global_accept(lua_State *L) | ||
| 1152 | { | ||
| 1153 | p_tags tags = pop_tags(L); | ||
| 1154 | p_sock sock = get_selfserversock(L, tags); | ||
| 1155 | lua_pushuserdata(L, tags); | ||
| 1156 | lua_pushusertag(L, sock, tags->server); | ||
| 1157 | return table_accept(L); | ||
| 1101 | } | 1158 | } |
| 1102 | 1159 | ||
| 1160 | int global_listen(lua_State *L) | ||
| 1161 | { | ||
| 1162 | p_tags tags = pop_tags(L); | ||
| 1163 | p_sock sock = get_selfserversock(L, tags); | ||
| 1164 | lua_pushusertag(L, sock, tags->server); | ||
| 1165 | return table_listen(L); | ||
| 1166 | } | ||
| 1167 | |||
| 1168 | int global_send(lua_State *L) | ||
| 1169 | { | ||
| 1170 | p_tags tags = pop_tags(L); | ||
| 1171 | p_sock sock = get_selfclientsock(L, tags); | ||
| 1172 | lua_pushusertag(L, sock, tags->client); | ||
| 1173 | return table_send(L); | ||
| 1174 | } | ||
| 1175 | |||
| 1176 | int global_receive(lua_State *L) | ||
| 1177 | { | ||
| 1178 | p_tags tags = pop_tags(L); | ||
| 1179 | p_sock sock = get_selfclientsock(L, tags); | ||
| 1180 | lua_pushusertag(L, sock, tags->client); | ||
| 1181 | return table_receive(L); | ||
| 1182 | } | ||
| 1183 | |||
| 1184 | int global_timeout(lua_State *L) | ||
| 1185 | { | ||
| 1186 | p_tags tags = pop_tags(L); | ||
| 1187 | p_sock sock = get_selfclientsock(L, tags); | ||
| 1188 | lua_pushusertag(L, sock, tags->client); | ||
| 1189 | return table_timeout(L); | ||
| 1190 | } | ||
| 1191 | |||
| 1192 | int global_close(lua_State *L) | ||
| 1193 | { | ||
| 1194 | return gc_sock(L); | ||
| 1195 | } | ||
| 1196 | #endif | ||
| 1197 | |||
| 1198 | /*=========================================================================*\ | ||
| 1199 | * Parameter manipulation functions | ||
| 1200 | \*=========================================================================*/ | ||
| 1103 | /*-------------------------------------------------------------------------*\ | 1201 | /*-------------------------------------------------------------------------*\ |
| 1104 | * Passes an error code to Lua. The NET_DONE error is translated to nil. | 1202 | * Passes an error code to Lua. The NET_DONE error is translated to nil. |
| 1105 | * Input | 1203 | * Input |
| @@ -1120,43 +1218,63 @@ static void push_error(lua_State *L, int err) | |||
| 1120 | } | 1218 | } |
| 1121 | } | 1219 | } |
| 1122 | 1220 | ||
| 1123 | /*-------------------------------------------------------------------------*\ | 1221 | static p_tags pop_tags(lua_State *L) |
| 1124 | * Passes socket tags to lua in correct order | ||
| 1125 | * Input: | ||
| 1126 | * client_tag, server_tag | ||
| 1127 | \*-------------------------------------------------------------------------*/ | ||
| 1128 | static void push_tags(lua_State *L, int client_tag, int server_tag) | ||
| 1129 | { | 1222 | { |
| 1130 | lua_pushnumber(L, client_tag); | 1223 | p_tags tags = (p_tags) lua_touserdata(L, -1); |
| 1131 | lua_pushnumber(L, server_tag); | 1224 | if (!tags) lua_error(L, "invalid closure! (probably misuse of library)"); |
| 1225 | lua_pop(L, 1); | ||
| 1226 | return tags; | ||
| 1132 | } | 1227 | } |
| 1133 | 1228 | ||
| 1134 | /*-------------------------------------------------------------------------*\ | 1229 | static p_sock pop_sock(lua_State *L) |
| 1135 | * Passes a client socket to Lua. | ||
| 1136 | * Must be called from a closure receiving the socket tags as its | ||
| 1137 | * parameters. | ||
| 1138 | * Input | ||
| 1139 | * L: lua environment | ||
| 1140 | * sock: pointer to socket structure to be used | ||
| 1141 | \*-------------------------------------------------------------------------*/ | ||
| 1142 | static void push_client(lua_State *L, p_sock sock, int client_tag) | ||
| 1143 | { | 1230 | { |
| 1144 | lua_pushusertag(L, (void *) sock, client_tag); | 1231 | p_sock sock = (p_sock) lua_touserdata(L, -1); |
| 1232 | if (!sock) lua_error(L, "invalid socket object"); | ||
| 1233 | if (sock->sock < 0) lua_error(L, "operation on closed socket"); | ||
| 1234 | lua_pop(L, 1); | ||
| 1235 | return sock; | ||
| 1145 | } | 1236 | } |
| 1146 | 1237 | ||
| 1147 | /*-------------------------------------------------------------------------*\ | 1238 | static p_sock get_selfsock(lua_State *L, p_tags tags) |
| 1148 | * Passes a server socket to Lua. | ||
| 1149 | * Must be called from a closure receiving the socket tags as its | ||
| 1150 | * parameters. | ||
| 1151 | * Input | ||
| 1152 | * L: lua environment | ||
| 1153 | * sock: pointer to socket structure to be used | ||
| 1154 | \*-------------------------------------------------------------------------*/ | ||
| 1155 | static void push_server(lua_State *L, p_sock sock, int server_tag) | ||
| 1156 | { | 1239 | { |
| 1157 | lua_pushusertag(L, (void *) sock, server_tag); | 1240 | p_sock sock; |
| 1241 | if (lua_tag(L, 1) != tags->table) lua_error(L, "invalid socket object"); | ||
| 1242 | lua_pushstring(L, P_SOCK); | ||
| 1243 | lua_gettable(L, 1); | ||
| 1244 | sock = lua_touserdata(L, -1); | ||
| 1245 | if (!sock) lua_error(L, "invalid socket object"); | ||
| 1246 | lua_pop(L, 1); | ||
| 1247 | return sock; | ||
| 1158 | } | 1248 | } |
| 1159 | 1249 | ||
| 1250 | #ifndef LUASOCKET_NOGLOBALS | ||
| 1251 | static p_sock get_selfclientsock(lua_State *L, p_tags tags) | ||
| 1252 | { | ||
| 1253 | p_sock sock; | ||
| 1254 | if (lua_tag(L, 1) != tags->table) lua_error(L, "invalid socket object"); | ||
| 1255 | lua_pushstring(L, P_SOCK); | ||
| 1256 | lua_gettable(L, 1); | ||
| 1257 | sock = lua_touserdata(L, -1); | ||
| 1258 | if (!sock || lua_tag(L, -1) != tags->client) | ||
| 1259 | lua_error(L, "client socket expected"); | ||
| 1260 | lua_pop(L, 1); | ||
| 1261 | return sock; | ||
| 1262 | } | ||
| 1263 | |||
| 1264 | static p_sock get_selfserversock(lua_State *L, p_tags tags) | ||
| 1265 | { | ||
| 1266 | p_sock sock; | ||
| 1267 | if (lua_tag(L, 1) != tags->table) lua_error(L, "invalid socket object"); | ||
| 1268 | lua_pushstring(L, P_SOCK); | ||
| 1269 | lua_gettable(L, 1); | ||
| 1270 | sock = lua_touserdata(L, -1); | ||
| 1271 | if (!sock || lua_tag(L, -1) != tags->server) | ||
| 1272 | lua_error(L, "server socket expected"); | ||
| 1273 | lua_pop(L, 1); | ||
| 1274 | return sock; | ||
| 1275 | } | ||
| 1276 | #endif | ||
| 1277 | |||
| 1160 | /*=========================================================================*\ | 1278 | /*=========================================================================*\ |
| 1161 | * WinSock2 specific functions. | 1279 | * WinSock2 specific functions. |
| 1162 | \*=========================================================================*/ | 1280 | \*=========================================================================*/ |
| @@ -1166,7 +1284,7 @@ static void push_server(lua_State *L, p_sock sock, int server_tag) | |||
| 1166 | * Returns | 1284 | * Returns |
| 1167 | * 1 in case of success. 0 in case of error. | 1285 | * 1 in case of success. 0 in case of error. |
| 1168 | \*-------------------------------------------------------------------------*/ | 1286 | \*-------------------------------------------------------------------------*/ |
| 1169 | static int wsock_open(void) | 1287 | static int winsock_open(void) |
| 1170 | { | 1288 | { |
| 1171 | WORD wVersionRequested;WSADATA wsaData;int err; | 1289 | WORD wVersionRequested;WSADATA wsaData;int err; |
| 1172 | wVersionRequested = MAKEWORD( 2, 0 ); | 1290 | wVersionRequested = MAKEWORD( 2, 0 ); |
| @@ -1181,7 +1299,6 @@ static int wsock_open(void) | |||
| 1181 | } | 1299 | } |
| 1182 | return 1; | 1300 | return 1; |
| 1183 | } | 1301 | } |
| 1184 | |||
| 1185 | 1302 | ||
| 1186 | /*-------------------------------------------------------------------------*\ | 1303 | /*-------------------------------------------------------------------------*\ |
| 1187 | * Put socket into blocking mode. | 1304 | * Put socket into blocking mode. |
| @@ -1189,10 +1306,7 @@ static int wsock_open(void) | |||
| 1189 | static void set_blocking(p_sock sock) | 1306 | static void set_blocking(p_sock sock) |
| 1190 | { | 1307 | { |
| 1191 | u_long argp = 0; | 1308 | u_long argp = 0; |
| 1192 | if (!sock->blocking) { | 1309 | ioctlsocket(sock->sock, FIONBIO, &argp); |
| 1193 | ioctlsocket(sock->sock, FIONBIO, &argp); | ||
| 1194 | sock->blocking = 1; | ||
| 1195 | } | ||
| 1196 | } | 1310 | } |
| 1197 | 1311 | ||
| 1198 | /*-------------------------------------------------------------------------*\ | 1312 | /*-------------------------------------------------------------------------*\ |
| @@ -1201,10 +1315,7 @@ static void set_blocking(p_sock sock) | |||
| 1201 | static void set_nonblocking(p_sock sock) | 1315 | static void set_nonblocking(p_sock sock) |
| 1202 | { | 1316 | { |
| 1203 | u_long argp = 1; | 1317 | u_long argp = 1; |
| 1204 | if (sock->blocking) { | 1318 | ioctlsocket(sock->sock, FIONBIO, &argp); |
| 1205 | ioctlsocket(sock->sock, FIONBIO, &argp); | ||
| 1206 | sock->blocking = 0; | ||
| 1207 | } | ||
| 1208 | } | 1319 | } |
| 1209 | 1320 | ||
| 1210 | /*-------------------------------------------------------------------------*\ | 1321 | /*-------------------------------------------------------------------------*\ |
| @@ -1354,130 +1465,4 @@ static char *connect_strerror(void) | |||
| 1354 | default: return "unknown error"; | 1465 | default: return "unknown error"; |
| 1355 | } | 1466 | } |
| 1356 | } | 1467 | } |
| 1357 | |||
| 1358 | #endif | ||
| 1359 | |||
| 1360 | /*=========================================================================*\ | ||
| 1361 | * Module exported functions | ||
| 1362 | \*=========================================================================*/ | ||
| 1363 | /*-------------------------------------------------------------------------*\ | ||
| 1364 | * Initializes the library interface with Lua and the socket library. | ||
| 1365 | * Defines the symbols exported to Lua. | ||
| 1366 | \*-------------------------------------------------------------------------*/ | ||
| 1367 | void lua_socketlibopen(lua_State *L) | ||
| 1368 | { | ||
| 1369 | int client_tag, server_tag; | ||
| 1370 | static struct luaL_reg funcs[] = { | ||
| 1371 | {"connect", net_connect}, | ||
| 1372 | {"bind", net_bind}, | ||
| 1373 | {"listen", net_listen}, | ||
| 1374 | {"accept", net_accept}, | ||
| 1375 | {"close", net_close}, | ||
| 1376 | {"send", net_send}, | ||
| 1377 | {"receive", net_receive}, | ||
| 1378 | {"timeout", net_timeout} | ||
| 1379 | }; | ||
| 1380 | int i; | ||
| 1381 | |||
| 1382 | #ifdef WIN32 | ||
| 1383 | wsock_open(); | ||
| 1384 | #endif | ||
| 1385 | /* declare new Lua tags for used userdata values */ | ||
| 1386 | client_tag = lua_newtag(L); | ||
| 1387 | server_tag = lua_newtag(L); | ||
| 1388 | /* Lua exported functions */ | ||
| 1389 | for (i = 0; i < sizeof(funcs)/sizeof(funcs[0]); i++) { | ||
| 1390 | push_tags(L, client_tag, server_tag); | ||
| 1391 | lua_pushcclosure(L, funcs[i].func, 2); | ||
| 1392 | lua_setglobal(L, funcs[i].name); | ||
| 1393 | } | ||
| 1394 | /* fallbacks */ | ||
| 1395 | push_tags(L, client_tag, server_tag); | ||
| 1396 | lua_pushcclosure(L, client_gettable, 2); | ||
| 1397 | lua_settagmethod(L, client_tag, "gettable"); | ||
| 1398 | |||
| 1399 | push_tags(L, client_tag, server_tag); | ||
| 1400 | lua_pushcclosure(L, server_gettable, 2); | ||
| 1401 | lua_settagmethod(L, server_tag, "gettable"); | ||
| 1402 | |||
| 1403 | push_tags(L, client_tag, server_tag); | ||
| 1404 | lua_pushcclosure(L, sock_gc, 2); | ||
| 1405 | lua_settagmethod(L, client_tag, "gc"); | ||
| 1406 | |||
| 1407 | push_tags(L, client_tag, server_tag); | ||
| 1408 | lua_pushcclosure(L, sock_gc, 2); | ||
| 1409 | lua_settagmethod(L, server_tag, "gc"); | ||
| 1410 | |||
| 1411 | /* avoid stupid compiler warnings */ | ||
| 1412 | (void) set_blocking; | ||
| 1413 | |||
| 1414 | #ifndef WIN32 | ||
| 1415 | /* avoid getting killed by a SIGPIPE signal */ | ||
| 1416 | handle_sigpipe(); | ||
| 1417 | #endif | ||
| 1418 | |||
| 1419 | #ifdef _DEBUG | ||
| 1420 | /* test support functions */ | ||
| 1421 | lua_pushcfunction(L, net_sleep); lua_setglobal(L, "sleep"); | ||
| 1422 | lua_pushcfunction(L, net_time); lua_setglobal(L, "time"); | ||
| 1423 | #endif | 1468 | #endif |
| 1424 | } | ||
| 1425 | |||
| 1426 | /*=========================================================================*\ | ||
| 1427 | * Lua2c and c2lua stack auxiliary functions | ||
| 1428 | \*=========================================================================*/ | ||
| 1429 | /*-------------------------------------------------------------------------*\ | ||
| 1430 | * Checks if argument is a client socket, printing an error message in | ||
| 1431 | * case of error | ||
| 1432 | * Input | ||
| 1433 | * numArg: argument position in lua2c stack | ||
| 1434 | * Returns | ||
| 1435 | * pointer to client socket, or doesn't return in case of error | ||
| 1436 | \*-------------------------------------------------------------------------*/ | ||
| 1437 | static p_sock check_client(lua_State *L, int numArg, int client_tag) | ||
| 1438 | { | ||
| 1439 | p_sock sock; | ||
| 1440 | luaL_arg_check(L, lua_tag(L, numArg) == client_tag, | ||
| 1441 | numArg, "client socket expected"); | ||
| 1442 | sock = (p_sock) lua_touserdata(L, numArg); | ||
| 1443 | if (sock->sock < 0) | ||
| 1444 | lua_error(L, "operation on closed socket"); | ||
| 1445 | return sock; | ||
| 1446 | } | ||
| 1447 | |||
| 1448 | /*-------------------------------------------------------------------------*\ | ||
| 1449 | * Checks if argument is a server socket, printing an error message in | ||
| 1450 | * case of error | ||
| 1451 | * Input | ||
| 1452 | * numArg: argument position in lua2c stack | ||
| 1453 | * Returns | ||
| 1454 | * pointer to server socket, or doesn't return in case of error | ||
| 1455 | \*-------------------------------------------------------------------------*/ | ||
| 1456 | static p_sock check_server(lua_State *L, int numArg, int server_tag) | ||
| 1457 | { | ||
| 1458 | p_sock sock; | ||
| 1459 | luaL_arg_check(L, lua_tag(L, numArg) == server_tag, | ||
| 1460 | numArg, "server socket expected"); | ||
| 1461 | sock = (p_sock) lua_touserdata(L, numArg); | ||
| 1462 | if (sock->sock < 0) | ||
| 1463 | lua_error(L, "operation on closed socket"); | ||
| 1464 | return sock; | ||
| 1465 | } | ||
| 1466 | |||
| 1467 | /*-------------------------------------------------------------------------*\ | ||
| 1468 | * Checks if argument is a socket, printing an error message in | ||
| 1469 | * case of error | ||
| 1470 | * Input | ||
| 1471 | * numArg: argument position in lua2c stack | ||
| 1472 | * Returns | ||
| 1473 | * pointer to socket, or doesn't return in case of error | ||
| 1474 | \*-------------------------------------------------------------------------*/ | ||
| 1475 | static p_sock check_sock(lua_State *L, int numArg, int client_tag, | ||
| 1476 | int server_tag) | ||
| 1477 | { | ||
| 1478 | p_sock sock; | ||
| 1479 | luaL_arg_check(L, (lua_tag(L, numArg) == client_tag) || | ||
| 1480 | (lua_tag(L, numArg) == server_tag), numArg, "socket expected"); | ||
| 1481 | sock = lua_touserdata(L, numArg); | ||
| 1482 | return sock; | ||
| 1483 | } | ||
