diff options
Diffstat (limited to 'src/usocket.c')
| -rw-r--r-- | src/usocket.c | 119 |
1 files changed, 16 insertions, 103 deletions
diff --git a/src/usocket.c b/src/usocket.c index b4b8d5a..062a0ff 100644 --- a/src/usocket.c +++ b/src/usocket.c | |||
| @@ -1,24 +1,8 @@ | |||
| 1 | /*=========================================================================*\ | ||
| 2 | * Socket compatibilization module for Unix | ||
| 3 | * | ||
| 4 | * RCS ID: $Id$ | ||
| 5 | \*=========================================================================*/ | ||
| 6 | #include <lua.h> | ||
| 7 | #include <lauxlib.h> | ||
| 8 | #include <string.h> | 1 | #include <string.h> |
| 9 | 2 | ||
| 10 | #include "sock.h" | 3 | #include "socket.h" |
| 11 | 4 | ||
| 12 | /*=========================================================================*\ | 5 | int sock_open(void) |
| 13 | * Internal function prototypes | ||
| 14 | \*=========================================================================*/ | ||
| 15 | static const char *try_setoption(lua_State *L, p_sock ps); | ||
| 16 | static const char *try_setbooloption(lua_State *L, p_sock ps, int name); | ||
| 17 | |||
| 18 | /*=========================================================================*\ | ||
| 19 | * Exported functions. | ||
| 20 | \*=========================================================================*/ | ||
| 21 | int sock_open(lua_State *L) | ||
| 22 | { | 6 | { |
| 23 | /* instals a handler to ignore sigpipe. */ | 7 | /* instals a handler to ignore sigpipe. */ |
| 24 | struct sigaction new; | 8 | struct sigaction new; |
| @@ -43,13 +27,13 @@ const char *sock_create(p_sock ps, int domain, int type, int protocol) | |||
| 43 | return NULL; | 27 | return NULL; |
| 44 | } | 28 | } |
| 45 | 29 | ||
| 46 | const char *sock_connect(p_sock ps, SA *addr, size_t addr_len) | 30 | const char *sock_connect(p_sock ps, SA *addr, socklen_t addr_len) |
| 47 | { | 31 | { |
| 48 | if (connect(*ps, addr, addr_len) < 0) return sock_connectstrerror(); | 32 | if (connect(*ps, addr, addr_len) < 0) return sock_connectstrerror(); |
| 49 | else return NULL; | 33 | else return NULL; |
| 50 | } | 34 | } |
| 51 | 35 | ||
| 52 | const char *sock_bind(p_sock ps, SA *addr, size_t addr_len) | 36 | const char *sock_bind(p_sock ps, SA *addr, socklen_t addr_len) |
| 53 | { | 37 | { |
| 54 | if (bind(*ps, addr, addr_len) < 0) return sock_bindstrerror(); | 38 | if (bind(*ps, addr, addr_len) < 0) return sock_bindstrerror(); |
| 55 | else return NULL; | 39 | else return NULL; |
| @@ -60,17 +44,25 @@ void sock_listen(p_sock ps, int backlog) | |||
| 60 | listen(*ps, backlog); | 44 | listen(*ps, backlog); |
| 61 | } | 45 | } |
| 62 | 46 | ||
| 63 | void sock_accept(p_sock ps, p_sock pa, SA *addr, size_t *addr_len, int timeout) | 47 | int sock_accept(p_sock ps, p_sock pa, SA *addr, socklen_t *addr_len, |
| 48 | int timeout) | ||
| 64 | { | 49 | { |
| 65 | t_sock sock = *ps; | 50 | t_sock sock = *ps; |
| 66 | struct timeval tv; | 51 | struct timeval tv; |
| 52 | SA dummy_addr; | ||
| 53 | socklen_t dummy_len; | ||
| 67 | fd_set fds; | 54 | fd_set fds; |
| 68 | tv.tv_sec = timeout / 1000; | 55 | tv.tv_sec = timeout / 1000; |
| 69 | tv.tv_usec = (timeout % 1000) * 1000; | 56 | tv.tv_usec = (timeout % 1000) * 1000; |
| 70 | FD_ZERO(&fds); | 57 | FD_ZERO(&fds); |
| 71 | FD_SET(sock, &fds); | 58 | FD_SET(sock, &fds); |
| 72 | select(sock+1, &fds, NULL, NULL, timeout >= 0 ? &tv : NULL); | 59 | if (select(sock+1, &fds, NULL, NULL, timeout >= 0 ? &tv : NULL) <= 0) |
| 60 | return IO_TIMEOUT; | ||
| 61 | if (!addr) addr = &dummy_addr; | ||
| 62 | if (!addr_len) addr_len = &dummy_len; | ||
| 73 | *pa = accept(sock, addr, addr_len); | 63 | *pa = accept(sock, addr, addr_len); |
| 64 | if (*pa == SOCK_INVALID) return IO_ERROR; | ||
| 65 | else return IO_DONE; | ||
| 74 | } | 66 | } |
| 75 | 67 | ||
| 76 | int sock_send(p_sock ps, const char *data, size_t count, size_t *sent, | 68 | int sock_send(p_sock ps, const char *data, size_t count, size_t *sent, |
| @@ -108,7 +100,7 @@ int sock_send(p_sock ps, const char *data, size_t count, size_t *sent, | |||
| 108 | } | 100 | } |
| 109 | 101 | ||
| 110 | int sock_sendto(p_sock ps, const char *data, size_t count, size_t *sent, | 102 | int sock_sendto(p_sock ps, const char *data, size_t count, size_t *sent, |
| 111 | SA *addr, size_t addr_len, int timeout) | 103 | SA *addr, socklen_t addr_len, int timeout) |
| 112 | { | 104 | { |
| 113 | t_sock sock = *ps; | 105 | t_sock sock = *ps; |
| 114 | struct timeval tv; | 106 | struct timeval tv; |
| @@ -169,7 +161,7 @@ int sock_recv(p_sock ps, char *data, size_t count, size_t *got, int timeout) | |||
| 169 | } | 161 | } |
| 170 | 162 | ||
| 171 | int sock_recvfrom(p_sock ps, char *data, size_t count, size_t *got, | 163 | int sock_recvfrom(p_sock ps, char *data, size_t count, size_t *got, |
| 172 | SA *addr, size_t *addr_len, int timeout) | 164 | SA *addr, socklen_t *addr_len, int timeout) |
| 173 | { | 165 | { |
| 174 | t_sock sock = *ps; | 166 | t_sock sock = *ps; |
| 175 | struct timeval tv; | 167 | struct timeval tv; |
| @@ -196,9 +188,6 @@ int sock_recvfrom(p_sock ps, char *data, size_t count, size_t *got, | |||
| 196 | } | 188 | } |
| 197 | } | 189 | } |
| 198 | 190 | ||
| 199 | /*-------------------------------------------------------------------------*\ | ||
| 200 | * Returns a string describing the last host manipulation error. | ||
| 201 | \*-------------------------------------------------------------------------*/ | ||
| 202 | const char *sock_hoststrerror(void) | 191 | const char *sock_hoststrerror(void) |
| 203 | { | 192 | { |
| 204 | switch (h_errno) { | 193 | switch (h_errno) { |
| @@ -210,9 +199,6 @@ const char *sock_hoststrerror(void) | |||
| 210 | } | 199 | } |
| 211 | } | 200 | } |
| 212 | 201 | ||
| 213 | /*-------------------------------------------------------------------------*\ | ||
| 214 | * Returns a string describing the last socket manipulation error. | ||
| 215 | \*-------------------------------------------------------------------------*/ | ||
| 216 | const char *sock_createstrerror(void) | 202 | const char *sock_createstrerror(void) |
| 217 | { | 203 | { |
| 218 | switch (errno) { | 204 | switch (errno) { |
| @@ -224,9 +210,6 @@ const char *sock_createstrerror(void) | |||
| 224 | } | 210 | } |
| 225 | } | 211 | } |
| 226 | 212 | ||
| 227 | /*-------------------------------------------------------------------------*\ | ||
| 228 | * Returns a string describing the last bind command error. | ||
| 229 | \*-------------------------------------------------------------------------*/ | ||
| 230 | const char *sock_bindstrerror(void) | 213 | const char *sock_bindstrerror(void) |
| 231 | { | 214 | { |
| 232 | switch (errno) { | 215 | switch (errno) { |
| @@ -241,9 +224,6 @@ const char *sock_bindstrerror(void) | |||
| 241 | } | 224 | } |
| 242 | } | 225 | } |
| 243 | 226 | ||
| 244 | /*-------------------------------------------------------------------------*\ | ||
| 245 | * Returns a string describing the last connect error. | ||
| 246 | \*-------------------------------------------------------------------------*/ | ||
| 247 | const char *sock_connectstrerror(void) | 227 | const char *sock_connectstrerror(void) |
| 248 | { | 228 | { |
| 249 | switch (errno) { | 229 | switch (errno) { |
| @@ -259,20 +239,12 @@ const char *sock_connectstrerror(void) | |||
| 259 | } | 239 | } |
| 260 | } | 240 | } |
| 261 | 241 | ||
| 262 | /*-------------------------------------------------------------------------*\ | ||
| 263 | * Sets the SO_REUSEADDR socket option | ||
| 264 | * Input | ||
| 265 | * sock: socket descriptor | ||
| 266 | \*-------------------------------------------------------------------------*/ | ||
| 267 | void sock_setreuseaddr(p_sock ps) | 242 | void sock_setreuseaddr(p_sock ps) |
| 268 | { | 243 | { |
| 269 | int val = 1; | 244 | int val = 1; |
| 270 | setsockopt(*ps, SOL_SOCKET, SO_REUSEADDR, (char *)&val, sizeof(val)); | 245 | setsockopt(*ps, SOL_SOCKET, SO_REUSEADDR, (char *)&val, sizeof(val)); |
| 271 | } | 246 | } |
| 272 | 247 | ||
| 273 | /*-------------------------------------------------------------------------*\ | ||
| 274 | * Put socket into blocking mode. | ||
| 275 | \*-------------------------------------------------------------------------*/ | ||
| 276 | void sock_setblocking(p_sock ps) | 248 | void sock_setblocking(p_sock ps) |
| 277 | { | 249 | { |
| 278 | int flags = fcntl(*ps, F_GETFL, 0); | 250 | int flags = fcntl(*ps, F_GETFL, 0); |
| @@ -280,68 +252,9 @@ void sock_setblocking(p_sock ps) | |||
| 280 | fcntl(*ps, F_SETFL, flags); | 252 | fcntl(*ps, F_SETFL, flags); |
| 281 | } | 253 | } |
| 282 | 254 | ||
| 283 | /*-------------------------------------------------------------------------*\ | ||
| 284 | * Put socket into non-blocking mode. | ||
| 285 | \*-------------------------------------------------------------------------*/ | ||
| 286 | void sock_setnonblocking(p_sock ps) | 255 | void sock_setnonblocking(p_sock ps) |
| 287 | { | 256 | { |
| 288 | int flags = fcntl(*ps, F_GETFL, 0); | 257 | int flags = fcntl(*ps, F_GETFL, 0); |
| 289 | flags |= O_NONBLOCK; | 258 | flags |= O_NONBLOCK; |
| 290 | fcntl(*ps, F_SETFL, flags); | 259 | fcntl(*ps, F_SETFL, flags); |
| 291 | } | 260 | } |
| 292 | |||
| 293 | /*-------------------------------------------------------------------------*\ | ||
| 294 | * Tries to set extended udp socket options | ||
| 295 | * Input | ||
| 296 | * udp: udp structure | ||
| 297 | * oldtop: top of stack | ||
| 298 | * Returns | ||
| 299 | * NULL if successfull, error message on error | ||
| 300 | \*-------------------------------------------------------------------------*/ | ||
| 301 | const char *sock_trysetoptions(lua_State *L, p_sock ps) | ||
| 302 | { | ||
| 303 | if (!lua_istable(L, 1)) luaL_argerror(L, 1, "invalid options table"); | ||
| 304 | lua_pushnil(L); | ||
| 305 | while (lua_next(L, 1)) { | ||
| 306 | const char *err = try_setoption(L, ps); | ||
| 307 | lua_pop(L, 1); | ||
| 308 | if (err) return err; | ||
| 309 | } | ||
| 310 | return NULL; | ||
| 311 | } | ||
| 312 | |||
| 313 | /*-------------------------------------------------------------------------*\ | ||
| 314 | * Set socket options from a table on top of Lua stack. | ||
| 315 | * Supports SO_KEEPALIVE, SO_DONTROUTE, and SO_BROADCAST options. | ||
| 316 | * Input | ||
| 317 | * sock: socket | ||
| 318 | * Returns | ||
| 319 | * 1 if successful, 0 otherwise | ||
| 320 | \*-------------------------------------------------------------------------*/ | ||
| 321 | static const char *try_setoption(lua_State *L, p_sock ps) | ||
| 322 | { | ||
| 323 | static const char *options[] = { | ||
| 324 | "SO_KEEPALIVE", "SO_DONTROUTE", "SO_BROADCAST", NULL | ||
| 325 | }; | ||
| 326 | const char *option = lua_tostring(L, -2); | ||
| 327 | if (!lua_isstring(L, -2)) return "invalid option"; | ||
| 328 | switch (luaL_findstring(option, options)) { | ||
| 329 | case 0: return try_setbooloption(L, ps, SO_KEEPALIVE); | ||
| 330 | case 1: return try_setbooloption(L, ps, SO_DONTROUTE); | ||
| 331 | case 2: return try_setbooloption(L, ps, SO_BROADCAST); | ||
| 332 | default: return "unsupported option"; | ||
| 333 | } | ||
| 334 | } | ||
| 335 | |||
| 336 | /*=========================================================================*\ | ||
| 337 | * Internal functions. | ||
| 338 | \*=========================================================================*/ | ||
| 339 | static const char *try_setbooloption(lua_State *L, p_sock ps, int name) | ||
| 340 | { | ||
| 341 | int bool, res; | ||
| 342 | if (!lua_isnumber(L, -1)) luaL_error(L, "invalid option value"); | ||
| 343 | bool = (int) lua_tonumber(L, -1); | ||
| 344 | res = setsockopt(*ps, SOL_SOCKET, name, (char *) &bool, sizeof(bool)); | ||
| 345 | if (res < 0) return "error setting option"; | ||
| 346 | else return NULL; | ||
| 347 | } | ||
