aboutsummaryrefslogtreecommitdiff
path: root/src/usocket.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/usocket.c')
-rw-r--r--src/usocket.c119
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/*=========================================================================*\ 5int sock_open(void)
13* Internal function prototypes
14\*=========================================================================*/
15static const char *try_setoption(lua_State *L, p_sock ps);
16static const char *try_setbooloption(lua_State *L, p_sock ps, int name);
17
18/*=========================================================================*\
19* Exported functions.
20\*=========================================================================*/
21int 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
46const char *sock_connect(p_sock ps, SA *addr, size_t addr_len) 30const 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
52const char *sock_bind(p_sock ps, SA *addr, size_t addr_len) 36const 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
63void sock_accept(p_sock ps, p_sock pa, SA *addr, size_t *addr_len, int timeout) 47int 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
76int sock_send(p_sock ps, const char *data, size_t count, size_t *sent, 68int 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
110int sock_sendto(p_sock ps, const char *data, size_t count, size_t *sent, 102int 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
171int sock_recvfrom(p_sock ps, char *data, size_t count, size_t *got, 163int 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\*-------------------------------------------------------------------------*/
202const char *sock_hoststrerror(void) 191const 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\*-------------------------------------------------------------------------*/
216const char *sock_createstrerror(void) 202const 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\*-------------------------------------------------------------------------*/
230const char *sock_bindstrerror(void) 213const 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\*-------------------------------------------------------------------------*/
247const char *sock_connectstrerror(void) 227const 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\*-------------------------------------------------------------------------*/
267void sock_setreuseaddr(p_sock ps) 242void 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\*-------------------------------------------------------------------------*/
276void sock_setblocking(p_sock ps) 248void 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\*-------------------------------------------------------------------------*/
286void sock_setnonblocking(p_sock ps) 255void 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\*-------------------------------------------------------------------------*/
301const 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\*-------------------------------------------------------------------------*/
321static 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\*=========================================================================*/
339static 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}