aboutsummaryrefslogtreecommitdiff
path: root/src/unix.c
diff options
context:
space:
mode:
authorDiego Nehab <diego@tecgraf.puc-rio.br>2003-05-25 01:54:13 +0000
committerDiego Nehab <diego@tecgraf.puc-rio.br>2003-05-25 01:54:13 +0000
commit0f6c8d50a99997ac7829864b1c93362b50f1bbf3 (patch)
treed0cefe3a05484e65b7b7e79d8cae4a1d2e6d19fb /src/unix.c
parentc1ef3e7103cc652d2004ef1ddc9409b946207f33 (diff)
downloadluasocket-0f6c8d50a99997ac7829864b1c93362b50f1bbf3.tar.gz
luasocket-0f6c8d50a99997ac7829864b1c93362b50f1bbf3.tar.bz2
luasocket-0f6c8d50a99997ac7829864b1c93362b50f1bbf3.zip
Porting to LUA 5.0 final
Diffstat (limited to 'src/unix.c')
-rw-r--r--src/unix.c326
1 files changed, 0 insertions, 326 deletions
diff --git a/src/unix.c b/src/unix.c
deleted file mode 100644
index 23984b0..0000000
--- a/src/unix.c
+++ /dev/null
@@ -1,326 +0,0 @@
1/*=========================================================================*\
2* Network compatibilization module: Unix version
3*
4* RCS ID: $Id$
5\*=========================================================================*/
6#include <lua.h>
7#include <lauxlib.h>
8#include <string.h>
9
10#include "lscompat.h"
11
12/*=========================================================================*\
13* Internal function prototypes
14\*=========================================================================*/
15static cchar *try_setoption(lua_State *L, COMPAT_FD sock);
16static cchar *try_setbooloption(lua_State *L, COMPAT_FD sock, int name);
17
18/*=========================================================================*\
19* Exported functions.
20\*=========================================================================*/
21int compat_open(lua_State *L)
22{
23 /* Instals a handler to ignore sigpipe. */
24 struct sigaction new;
25 memset(&new, 0, sizeof(new));
26 new.sa_handler = SIG_IGN;
27 sigaction(SIGPIPE, &new, NULL);
28 return 1;
29}
30
31COMPAT_FD compat_accept(COMPAT_FD s, struct sockaddr *addr,
32 size_t *len, int deadline)
33{
34 struct timeval tv;
35 fd_set fds;
36 tv.tv_sec = deadline / 1000;
37 tv.tv_usec = (deadline % 1000) * 1000;
38 FD_ZERO(&fds);
39 FD_SET(s, &fds);
40 select(s+1, &fds, NULL, NULL, deadline >= 0 ? &tv : NULL);
41 return accept(s, addr, len);
42}
43
44int compat_send(COMPAT_FD c, cchar *data, size_t count, size_t *sent,
45 int deadline)
46{
47 struct timeval tv;
48 fd_set fds;
49 ssize_t put = 0;
50 int err;
51 int ret;
52 tv.tv_sec = deadline / 1000;
53 tv.tv_usec = (deadline % 1000) * 1000;
54 FD_ZERO(&fds);
55 FD_SET(c, &fds);
56 ret = select(c+1, NULL, &fds, NULL, deadline >= 0 ? &tv : NULL);
57 if (ret > 0) {
58 put = write(c, data, count);
59 if (put <= 0) {
60 err = PRIV_CLOSED;
61#ifdef __CYGWIN__
62 /* this is for CYGWIN, which is like Unix but has Win32 bugs */
63 if (errno == EWOULDBLOCK) err = PRIV_DONE;
64#endif
65 *sent = 0;
66 } else {
67 *sent = put;
68 err = PRIV_DONE;
69 }
70 return err;
71 } else {
72 *sent = 0;
73 return PRIV_TIMEOUT;
74 }
75}
76
77int compat_sendto(COMPAT_FD c, cchar *data, size_t count, size_t *sent,
78 int deadline, SA *addr, size_t len)
79{
80 struct timeval tv;
81 fd_set fds;
82 ssize_t put = 0;
83 int err;
84 int ret;
85 tv.tv_sec = deadline / 1000;
86 tv.tv_usec = (deadline % 1000) * 1000;
87 FD_ZERO(&fds);
88 FD_SET(c, &fds);
89 ret = select(c+1, NULL, &fds, NULL, deadline >= 0 ? &tv : NULL);
90 if (ret > 0) {
91 put = sendto(c, data, count, 0, addr, len);
92 if (put <= 0) {
93 err = PRIV_CLOSED;
94#ifdef __CYGWIN__
95 /* this is for CYGWIN, which is like Unix but has Win32 bugs */
96 if (sent < 0 && errno == EWOULDBLOCK) err = PRIV_DONE;
97#endif
98 *sent = 0;
99 } else {
100 *sent = put;
101 err = PRIV_DONE;
102 }
103 return err;
104 } else {
105 *sent = 0;
106 return PRIV_TIMEOUT;
107 }
108}
109
110int compat_recv(COMPAT_FD c, char *data, size_t count, size_t *got,
111 int deadline)
112{
113 struct timeval tv;
114 fd_set fds;
115 int ret;
116 ssize_t taken = 0;
117 tv.tv_sec = deadline / 1000;
118 tv.tv_usec = (deadline % 1000) * 1000;
119 FD_ZERO(&fds);
120 FD_SET(c, &fds);
121 ret = select(c+1, &fds, NULL, NULL, deadline >= 0 ? &tv : NULL);
122 if (ret > 0) {
123 taken = read(c, data, count);
124 if (taken <= 0) {
125 *got = 0;
126 return PRIV_CLOSED;
127 } else {
128 *got = taken;
129 return PRIV_DONE;
130 }
131 } else {
132 *got = 0;
133 return PRIV_TIMEOUT;
134 }
135}
136
137int compat_recvfrom(COMPAT_FD c, char *data, size_t count, size_t *got,
138 int deadline, SA *addr, size_t *len)
139{
140 struct timeval tv;
141 fd_set fds;
142 int ret;
143 ssize_t taken = 0;
144 tv.tv_sec = deadline / 1000;
145 tv.tv_usec = (deadline % 1000) * 1000;
146 FD_ZERO(&fds);
147 FD_SET(c, &fds);
148 ret = select(c+1, &fds, NULL, NULL, deadline >= 0 ? &tv : NULL);
149 if (ret > 0) {
150 taken = recvfrom(c, data, count, 0, addr, len);
151 if (taken <= 0) {
152 *got = 0;
153 return PRIV_CLOSED;
154 } else {
155 *got = taken;
156 return PRIV_DONE;
157 }
158 } else {
159 *got = 0;
160 return PRIV_TIMEOUT;
161 }
162}
163
164/*-------------------------------------------------------------------------*\
165* Returns a string describing the last host manipulation error.
166\*-------------------------------------------------------------------------*/
167const char *compat_hoststrerror(void)
168{
169 switch (h_errno) {
170 case HOST_NOT_FOUND: return "host not found";
171 case NO_ADDRESS: return "unable to resolve host name";
172 case NO_RECOVERY: return "name server error";
173 case TRY_AGAIN: return "name server unavailable, try again later";
174 default: return "unknown error";
175 }
176}
177
178/*-------------------------------------------------------------------------*\
179* Returns a string describing the last socket manipulation error.
180\*-------------------------------------------------------------------------*/
181const char *compat_socketstrerror(void)
182{
183 switch (errno) {
184 case EACCES: return "access denied";
185 case EMFILE: return "descriptor table is full";
186 case ENFILE: return "too many open files";
187 case ENOBUFS: return "insuffucient buffer space";
188 default: return "unknown error";
189 }
190}
191
192/*-------------------------------------------------------------------------*\
193* Returns a string describing the last bind command error.
194\*-------------------------------------------------------------------------*/
195const char *compat_bindstrerror(void)
196{
197 switch (errno) {
198 case EBADF: return "invalid descriptor";
199 case EINVAL: return "socket already bound";
200 case EACCES: return "access denied";
201 case ENOTSOCK: return "not a socket descriptor";
202 case EADDRINUSE: return "address already in use";
203 case EADDRNOTAVAIL: return "address unavailable";
204 case ENOMEM: return "out of memory";
205 default: return "unknown error";
206 }
207}
208
209/*-------------------------------------------------------------------------*\
210* Returns a string describing the last connect error.
211\*-------------------------------------------------------------------------*/
212const char *compat_connectstrerror(void)
213{
214 switch (errno) {
215 case EBADF: return "invalid descriptor";
216 case ENOTSOCK: return "not a socket descriptor";
217 case EADDRNOTAVAIL: return "address not availabe";
218 case ETIMEDOUT: return "connection timed out";
219 case ECONNREFUSED: return "connection refused";
220 case EACCES: return "access denied";
221 case ENETUNREACH: return "network is unreachable";
222 case EADDRINUSE: return "address already in use";
223 default: return "unknown error";
224 }
225}
226
227/*-------------------------------------------------------------------------*\
228* Sets the SO_REUSEADDR socket option
229* Input
230* sock: socket descriptor
231\*-------------------------------------------------------------------------*/
232void compat_setreuseaddr(COMPAT_FD sock)
233{
234 int val = 1;
235 setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *)&val, sizeof(val));
236}
237
238COMPAT_FD compat_socket(int domain, int type, int protocol)
239{
240 COMPAT_FD sock = socket(domain, type, protocol);
241 if (sock != COMPAT_INVALIDFD) {
242 compat_setnonblocking(sock);
243 compat_setreuseaddr(sock);
244 }
245 return sock;
246}
247
248/*-------------------------------------------------------------------------*\
249* Put socket into blocking mode.
250\*-------------------------------------------------------------------------*/
251void compat_setblocking(COMPAT_FD sock)
252{
253 int flags = fcntl(sock, F_GETFL, 0);
254 flags &= (~(O_NONBLOCK));
255 fcntl(sock, F_SETFL, flags);
256}
257
258/*-------------------------------------------------------------------------*\
259* Put socket into non-blocking mode.
260\*-------------------------------------------------------------------------*/
261void compat_setnonblocking(COMPAT_FD sock)
262{
263 int flags = fcntl(sock, F_GETFL, 0);
264 flags |= O_NONBLOCK;
265 fcntl(sock, F_SETFL, flags);
266}
267
268/*-------------------------------------------------------------------------*\
269* Tries to set extended udp socket options
270* Input
271* udp: udp structure
272* oldtop: top of stack
273* Returns
274* NULL if successfull, error message on error
275\*-------------------------------------------------------------------------*/
276cchar *compat_trysetoptions(lua_State *L, COMPAT_FD sock)
277{
278 if (!lua_istable(L, 1)) luaL_argerror(L, 1, "invalid options table");
279 lua_pushnil(L);
280 while (lua_next(L, 1)) {
281 cchar *err = try_setoption(L, sock);
282 lua_pop(L, 1);
283 if (err) return err;
284 }
285 return NULL;
286}
287
288/*=========================================================================*\
289* Internal functions.
290\*=========================================================================*/
291static cchar *try_setbooloption(lua_State *L, COMPAT_FD sock, int name)
292{
293 int bool, res;
294 if (!lua_isnumber(L, -1)) luaL_error(L, "invalid option value");
295 bool = (int) lua_tonumber(L, -1);
296 res = setsockopt(sock, SOL_SOCKET, name, (char *) &bool, sizeof(bool));
297 if (res < 0) return "error setting option";
298 else return NULL;
299}
300
301
302/*-------------------------------------------------------------------------*\
303* Set socket options from a table on top of Lua stack.
304* Supports SO_KEEPALIVE, SO_DONTROUTE, SO_BROADCAST, and SO_LINGER options.
305* Input
306* L: Lua state to use
307* sock: socket descriptor
308* Returns
309* 1 if successful, 0 otherwise
310\*-------------------------------------------------------------------------*/
311static cchar *try_setoption(lua_State *L, COMPAT_FD sock)
312{
313 static cchar *options[] = {
314 "SO_KEEPALIVE", "SO_DONTROUTE", "SO_BROADCAST", "SO_LINGER", NULL
315 };
316 cchar *option = lua_tostring(L, -2);
317 if (!lua_isstring(L, -2)) return "invalid option";
318 switch (luaL_findstring(option, options)) {
319 case 0: return try_setbooloption(L, sock, SO_KEEPALIVE);
320 case 1: return try_setbooloption(L, sock, SO_DONTROUTE);
321 case 2: return try_setbooloption(L, sock, SO_BROADCAST);
322 case 3: return "SO_LINGER is deprecated";
323 default: return "unsupported option";
324 }
325}
326