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 | } | ||