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 /src | |
| 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. :-)
Diffstat (limited to 'src')
| -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 | |||
