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