aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDiego Nehab <diego@tecgraf.puc-rio.br>2003-06-11 01:42:18 +0000
committerDiego Nehab <diego@tecgraf.puc-rio.br>2003-06-11 01:42:18 +0000
commitf330540576031528f0daac231c61d4dd06e8ba1e (patch)
tree8f9cd79ac7d4ec937413bbae8a90e8782c1afe18
parent58bdb658aaa1c30a8f3bed46eef880d308fae582 (diff)
downloadluasocket-f330540576031528f0daac231c61d4dd06e8ba1e.tar.gz
luasocket-f330540576031528f0daac231c61d4dd06e8ba1e.tar.bz2
luasocket-f330540576031528f0daac231c61d4dd06e8ba1e.zip
Compiles and runs on linux and windows, using DLLs!
-rw-r--r--src/inet.c19
-rw-r--r--src/inet.h4
-rw-r--r--src/tcp.c7
-rw-r--r--src/udp.c10
-rw-r--r--src/usocket.h6
-rw-r--r--src/wsocket.c261
-rw-r--r--src/wsocket.h22
7 files changed, 309 insertions, 20 deletions
diff --git a/src/inet.c b/src/inet.c
index 60106f2..b7f3ae5 100644
--- a/src/inet.c
+++ b/src/inet.c
@@ -19,10 +19,6 @@ static int inet_global_tohostname(lua_State *L);
19 19
20static void inet_pushresolved(lua_State *L, struct hostent *hp); 20static void inet_pushresolved(lua_State *L, struct hostent *hp);
21 21
22#ifdef INET_ATON
23static int inet_aton(const char *cp, struct in_addr *inp);
24#endif
25
26static luaL_reg func[] = { 22static luaL_reg func[] = {
27 { "toip", inet_global_toip }, 23 { "toip", inet_global_toip },
28 { "tohostname", inet_global_tohostname }, 24 { "tohostname", inet_global_tohostname },
@@ -196,9 +192,11 @@ static void inet_pushresolved(lua_State *L, struct hostent *hp)
196* Returns 192* Returns
197* NULL in case of success, error message otherwise 193* NULL in case of success, error message otherwise
198\*-------------------------------------------------------------------------*/ 194\*-------------------------------------------------------------------------*/
199const char *inet_tryconnect(p_sock ps, const char *address, ushort port) 195const char *inet_tryconnect(p_sock ps, const char *address,
196 unsigned short port)
200{ 197{
201 struct sockaddr_in remote; 198 struct sockaddr_in remote;
199 const char *err;
202 memset(&remote, 0, sizeof(remote)); 200 memset(&remote, 0, sizeof(remote));
203 remote.sin_family = AF_INET; 201 remote.sin_family = AF_INET;
204 remote.sin_port = htons(port); 202 remote.sin_port = htons(port);
@@ -213,7 +211,7 @@ const char *inet_tryconnect(p_sock ps, const char *address, ushort port)
213 } 211 }
214 } else remote.sin_family = AF_UNSPEC; 212 } else remote.sin_family = AF_UNSPEC;
215 sock_setblocking(ps); 213 sock_setblocking(ps);
216 const char *err = sock_connect(ps, (SA *) &remote, sizeof(remote)); 214 err = sock_connect(ps, (SA *) &remote, sizeof(remote));
217 if (err) { 215 if (err) {
218 sock_destroy(ps); 216 sock_destroy(ps);
219 *ps = SOCK_INVALID; 217 *ps = SOCK_INVALID;
@@ -233,10 +231,11 @@ const char *inet_tryconnect(p_sock ps, const char *address, ushort port)
233* Returns 231* Returns
234* NULL in case of success, error message otherwise 232* NULL in case of success, error message otherwise
235\*-------------------------------------------------------------------------*/ 233\*-------------------------------------------------------------------------*/
236const char *inet_trybind(p_sock ps, const char *address, ushort port, 234const char *inet_trybind(p_sock ps, const char *address, unsigned short port,
237 int backlog) 235 int backlog)
238{ 236{
239 struct sockaddr_in local; 237 struct sockaddr_in local;
238 const char *err;
240 memset(&local, 0, sizeof(local)); 239 memset(&local, 0, sizeof(local));
241 /* address is either wildcard or a valid ip address */ 240 /* address is either wildcard or a valid ip address */
242 local.sin_addr.s_addr = htonl(INADDR_ANY); 241 local.sin_addr.s_addr = htonl(INADDR_ANY);
@@ -251,7 +250,7 @@ const char *inet_trybind(p_sock ps, const char *address, ushort port,
251 memcpy(&local.sin_addr, *addr, sizeof(struct in_addr)); 250 memcpy(&local.sin_addr, *addr, sizeof(struct in_addr));
252 } 251 }
253 sock_setblocking(ps); 252 sock_setblocking(ps);
254 const char *err = sock_bind(ps, (SA *) &local, sizeof(local)); 253 err = sock_bind(ps, (SA *) &local, sizeof(local));
255 if (err) { 254 if (err) {
256 sock_destroy(ps); 255 sock_destroy(ps);
257 *ps = SOCK_INVALID; 256 *ps = SOCK_INVALID;
@@ -279,8 +278,8 @@ const char *inet_trycreate(p_sock ps, int type)
279* Some systems do not provide this so that we provide our own. It's not 278* Some systems do not provide this so that we provide our own. It's not
280* marvelously fast, but it works just fine. 279* marvelously fast, but it works just fine.
281\*-------------------------------------------------------------------------*/ 280\*-------------------------------------------------------------------------*/
282#ifdef COMPAT_INETATON 281#ifdef INET_ATON
283static int inet_aton(const char *cp, struct in_addr *inp) 282int inet_aton(const char *cp, struct in_addr *inp)
284{ 283{
285 unsigned int a = 0, b = 0, c = 0, d = 0; 284 unsigned int a = 0, b = 0, c = 0, d = 0;
286 int n = 0, r; 285 int n = 0, r;
diff --git a/src/inet.h b/src/inet.h
index b8d8f19..60be9e4 100644
--- a/src/inet.h
+++ b/src/inet.h
@@ -23,4 +23,8 @@ const char *inet_trycreate(p_sock ps, int type);
23int inet_meth_getpeername(lua_State *L, p_sock ps); 23int inet_meth_getpeername(lua_State *L, p_sock ps);
24int inet_meth_getsockname(lua_State *L, p_sock ps); 24int inet_meth_getsockname(lua_State *L, p_sock ps);
25 25
26#ifdef INET_ATON
27int inet_aton(const char *cp, struct in_addr *inp);
28#endif
29
26#endif /* INET_H_ */ 30#endif /* INET_H_ */
diff --git a/src/tcp.c b/src/tcp.c
index 74857c9..dc7683d 100644
--- a/src/tcp.c
+++ b/src/tcp.c
@@ -154,7 +154,7 @@ static int meth_connect(lua_State *L)
154{ 154{
155 p_tcp tcp = (p_tcp) aux_checkclass(L, "tcp{master}", 1); 155 p_tcp tcp = (p_tcp) aux_checkclass(L, "tcp{master}", 1);
156 const char *address = luaL_checkstring(L, 2); 156 const char *address = luaL_checkstring(L, 2);
157 unsigned short port = (ushort) luaL_checknumber(L, 3); 157 unsigned short port = (unsigned short) luaL_checknumber(L, 3);
158 const char *err = inet_tryconnect(&tcp->sock, address, port); 158 const char *err = inet_tryconnect(&tcp->sock, address, port);
159 if (err) { 159 if (err) {
160 lua_pushnil(L); 160 lua_pushnil(L);
@@ -174,7 +174,7 @@ static int meth_bind(lua_State *L)
174{ 174{
175 p_tcp tcp = (p_tcp) aux_checkclass(L, "tcp{master}", 1); 175 p_tcp tcp = (p_tcp) aux_checkclass(L, "tcp{master}", 1);
176 const char *address = luaL_checkstring(L, 2); 176 const char *address = luaL_checkstring(L, 2);
177 unsigned short port = (ushort) luaL_checknumber(L, 3); 177 unsigned short port = (unsigned short) luaL_checknumber(L, 3);
178 int backlog = (int) luaL_optnumber(L, 4, 1); 178 int backlog = (int) luaL_optnumber(L, 4, 1);
179 const char *err = inet_trybind(&tcp->sock, address, port, backlog); 179 const char *err = inet_trybind(&tcp->sock, address, port, backlog);
180 if (err) { 180 if (err) {
@@ -227,12 +227,13 @@ static int meth_accept(lua_State *L)
227\*-------------------------------------------------------------------------*/ 227\*-------------------------------------------------------------------------*/
228int global_create(lua_State *L) 228int global_create(lua_State *L)
229{ 229{
230 const char *err;
230 /* allocate tcp object */ 231 /* allocate tcp object */
231 p_tcp tcp = (p_tcp) lua_newuserdata(L, sizeof(t_tcp)); 232 p_tcp tcp = (p_tcp) lua_newuserdata(L, sizeof(t_tcp));
232 /* set its type as master object */ 233 /* set its type as master object */
233 aux_setclass(L, "tcp{master}", -1); 234 aux_setclass(L, "tcp{master}", -1);
234 /* try to allocate a system socket */ 235 /* try to allocate a system socket */
235 const char *err = inet_trycreate(&tcp->sock, SOCK_STREAM); 236 err = inet_trycreate(&tcp->sock, SOCK_STREAM);
236 if (err) { /* get rid of object on stack and push error */ 237 if (err) { /* get rid of object on stack and push error */
237 lua_pop(L, 1); 238 lua_pop(L, 1);
238 lua_pushnil(L); 239 lua_pushnil(L);
diff --git a/src/udp.c b/src/udp.c
index bcf515b..79831e7 100644
--- a/src/udp.c
+++ b/src/udp.c
@@ -104,7 +104,7 @@ static int meth_sendto(lua_State *L)
104 size_t count, sent = 0; 104 size_t count, sent = 0;
105 const char *data = luaL_checklstring(L, 2, &count); 105 const char *data = luaL_checklstring(L, 2, &count);
106 const char *ip = luaL_checkstring(L, 3); 106 const char *ip = luaL_checkstring(L, 3);
107 ushort port = (ushort) luaL_checknumber(L, 4); 107 unsigned short port = (unsigned short) luaL_checknumber(L, 4);
108 p_tm tm = &udp->tm; 108 p_tm tm = &udp->tm;
109 struct sockaddr_in addr; 109 struct sockaddr_in addr;
110 int err; 110 int err;
@@ -220,7 +220,8 @@ static int meth_setpeername(lua_State *L)
220 const char *address = luaL_checkstring(L, 2); 220 const char *address = luaL_checkstring(L, 2);
221 int connecting = strcmp(address, "*"); 221 int connecting = strcmp(address, "*");
222 unsigned short port = connecting ? 222 unsigned short port = connecting ?
223 (ushort) luaL_checknumber(L, 3) : (ushort) luaL_optnumber(L, 3, 0); 223 (unsigned short) luaL_checknumber(L, 3) :
224 (unsigned short) luaL_optnumber(L, 3, 0);
224 const char *err = inet_tryconnect(&udp->sock, address, port); 225 const char *err = inet_tryconnect(&udp->sock, address, port);
225 if (err) { 226 if (err) {
226 lua_pushnil(L); 227 lua_pushnil(L);
@@ -251,7 +252,7 @@ static int meth_setsockname(lua_State *L)
251{ 252{
252 p_udp udp = (p_udp) aux_checkclass(L, "udp{master}", 1); 253 p_udp udp = (p_udp) aux_checkclass(L, "udp{master}", 1);
253 const char *address = luaL_checkstring(L, 2); 254 const char *address = luaL_checkstring(L, 2);
254 unsigned short port = (ushort) luaL_checknumber(L, 3); 255 unsigned short port = (unsigned short) luaL_checknumber(L, 3);
255 const char *err = inet_trybind(&udp->sock, address, port, -1); 256 const char *err = inet_trybind(&udp->sock, address, port, -1);
256 if (err) { 257 if (err) {
257 lua_pushnil(L); 258 lua_pushnil(L);
@@ -270,12 +271,13 @@ static int meth_setsockname(lua_State *L)
270\*-------------------------------------------------------------------------*/ 271\*-------------------------------------------------------------------------*/
271int global_create(lua_State *L) 272int global_create(lua_State *L)
272{ 273{
274 const char *err;
273 /* allocate udp object */ 275 /* allocate udp object */
274 p_udp udp = (p_udp) lua_newuserdata(L, sizeof(t_udp)); 276 p_udp udp = (p_udp) lua_newuserdata(L, sizeof(t_udp));
275 /* set its type as master object */ 277 /* set its type as master object */
276 aux_setclass(L, "udp{unconnected}", -1); 278 aux_setclass(L, "udp{unconnected}", -1);
277 /* try to allocate a system socket */ 279 /* try to allocate a system socket */
278 const char *err = inet_trycreate(&udp->sock, SOCK_DGRAM); 280 err = inet_trycreate(&udp->sock, SOCK_DGRAM);
279 if (err) { 281 if (err) {
280 /* get rid of object on stack and push error */ 282 /* get rid of object on stack and push error */
281 lua_pop(L, 1); 283 lua_pop(L, 1);
diff --git a/src/usocket.h b/src/usocket.h
index 9e4b75a..034ae74 100644
--- a/src/usocket.h
+++ b/src/usocket.h
@@ -3,8 +3,8 @@
3* 3*
4* RCS ID: $Id$ 4* RCS ID: $Id$
5\*=========================================================================*/ 5\*=========================================================================*/
6#ifndef UNIX_H 6#ifndef USOCKET_H
7#define UNIX_H 7#define USOCKET_H
8 8
9/*=========================================================================*\ 9/*=========================================================================*\
10* BSD include files 10* BSD include files
@@ -41,4 +41,4 @@ typedef t_sock *p_sock;
41 41
42#define SOCK_INVALID (-1) 42#define SOCK_INVALID (-1)
43 43
44#endif /* UNIX_H */ 44#endif /* USOCKET_H */
diff --git a/src/wsocket.c b/src/wsocket.c
new file mode 100644
index 0000000..56e65ec
--- /dev/null
+++ b/src/wsocket.c
@@ -0,0 +1,261 @@
1#include <string.h>
2
3#include "socket.h"
4
5int sock_open(void)
6{
7 WORD wVersionRequested;
8 WSADATA wsaData;
9 int err;
10 wVersionRequested = MAKEWORD(2, 0);
11 err = WSAStartup(wVersionRequested, &wsaData );
12 if (err != 0) return 0;
13 if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 0) {
14 WSACleanup();
15 return 0;
16 }
17 return 1;
18}
19
20void sock_destroy(p_sock ps)
21{
22 closesocket(*ps);
23}
24
25const char *sock_create(p_sock ps, int domain, int type, int protocol)
26{
27 t_sock sock = socket(domain, type, protocol);
28 if (sock == SOCK_INVALID) return sock_createstrerror();
29 *ps = sock;
30 sock_setnonblocking(ps);
31 sock_setreuseaddr(ps);
32 return NULL;
33}
34
35const char *sock_connect(p_sock ps, SA *addr, socklen_t addr_len)
36{
37 if (connect(*ps, addr, addr_len) < 0) return sock_connectstrerror();
38 else return NULL;
39}
40
41const char *sock_bind(p_sock ps, SA *addr, socklen_t addr_len)
42{
43 if (bind(*ps, addr, addr_len) < 0) return sock_bindstrerror();
44 else return NULL;
45}
46
47void sock_listen(p_sock ps, int backlog)
48{
49 listen(*ps, backlog);
50}
51
52int sock_accept(p_sock ps, p_sock pa, SA *addr, socklen_t *addr_len,
53 int timeout)
54{
55 t_sock sock = *ps;
56 struct timeval tv;
57 SA dummy_addr;
58 socklen_t dummy_len;
59 fd_set fds;
60 tv.tv_sec = timeout / 1000;
61 tv.tv_usec = (timeout % 1000) * 1000;
62 FD_ZERO(&fds);
63 FD_SET(sock, &fds);
64 if (select(sock+1, &fds, NULL, NULL, timeout >= 0 ? &tv : NULL) <= 0)
65 return IO_TIMEOUT;
66 if (!addr) addr = &dummy_addr;
67 if (!addr_len) addr_len = &dummy_len;
68 *pa = accept(sock, addr, addr_len);
69 if (*pa == SOCK_INVALID) return IO_ERROR;
70 else return IO_DONE;
71}
72
73int sock_send(p_sock ps, const char *data, size_t count, size_t *sent,
74 int timeout)
75{
76 t_sock sock = *ps;
77 struct timeval tv;
78 fd_set fds;
79 ssize_t put = 0;
80 int err;
81 int ret;
82 tv.tv_sec = timeout / 1000;
83 tv.tv_usec = (timeout % 1000) * 1000;
84 FD_ZERO(&fds);
85 FD_SET(sock, &fds);
86 ret = select(sock+1, NULL, &fds, NULL, timeout >= 0 ? &tv : NULL);
87 if (ret > 0) {
88 put = send(sock, data, count, 0);
89 if (put <= 0) {
90 /* a bug in WinSock forces us to do a busy wait until we manage
91 ** to write, because select returns immediately even though it
92 ** should have blocked us until we could write... */
93 if (WSAGetLastError() == WSAEWOULDBLOCK) err = IO_DONE;
94 else err = IO_CLOSED;
95 *sent = 0;
96 } else {
97 *sent = put;
98 err = IO_DONE;
99 }
100 return err;
101 } else {
102 *sent = 0;
103 return IO_TIMEOUT;
104 }
105}
106
107int sock_sendto(p_sock ps, const char *data, size_t count, size_t *sent,
108 SA *addr, socklen_t addr_len, int timeout)
109{
110 t_sock sock = *ps;
111 struct timeval tv;
112 fd_set fds;
113 ssize_t put = 0;
114 int err;
115 int ret;
116 tv.tv_sec = timeout / 1000;
117 tv.tv_usec = (timeout % 1000) * 1000;
118 FD_ZERO(&fds);
119 FD_SET(sock, &fds);
120 ret = select(sock+1, NULL, &fds, NULL, timeout >= 0 ? &tv : NULL);
121 if (ret > 0) {
122 put = sendto(sock, data, count, 0, addr, addr_len);
123 if (put <= 0) {
124 /* a bug in WinSock forces us to do a busy wait until we manage
125 ** to write, because select returns immediately even though it
126 ** should have blocked us until we could write... */
127 if (WSAGetLastError() == WSAEWOULDBLOCK) err = IO_DONE;
128 else err = IO_CLOSED;
129 *sent = 0;
130 } else {
131 *sent = put;
132 err = IO_DONE;
133 }
134 return err;
135 } else {
136 *sent = 0;
137 return IO_TIMEOUT;
138 }
139}
140
141int sock_recv(p_sock ps, char *data, size_t count, size_t *got, int timeout)
142{
143 t_sock sock = *ps;
144 struct timeval tv;
145 fd_set fds;
146 int ret;
147 ssize_t taken = 0;
148 tv.tv_sec = timeout / 1000;
149 tv.tv_usec = (timeout % 1000) * 1000;
150 FD_ZERO(&fds);
151 FD_SET(sock, &fds);
152 ret = select(sock+1, &fds, NULL, NULL, timeout >= 0 ? &tv : NULL);
153 if (ret > 0) {
154 taken = recv(sock, data, count, 0);
155 if (taken <= 0) {
156 *got = 0;
157 return IO_CLOSED;
158 } else {
159 *got = taken;
160 return IO_DONE;
161 }
162 } else {
163 *got = 0;
164 return IO_TIMEOUT;
165 }
166}
167
168int sock_recvfrom(p_sock ps, char *data, size_t count, size_t *got,
169 SA *addr, socklen_t *addr_len, int timeout)
170{
171 t_sock sock = *ps;
172 struct timeval tv;
173 fd_set fds;
174 int ret;
175 ssize_t taken = 0;
176 tv.tv_sec = timeout / 1000;
177 tv.tv_usec = (timeout % 1000) * 1000;
178 FD_ZERO(&fds);
179 FD_SET(sock, &fds);
180 ret = select(sock+1, &fds, NULL, NULL, timeout >= 0 ? &tv : NULL);
181 if (ret > 0) {
182 taken = recvfrom(sock, data, count, 0, addr, addr_len);
183 if (taken <= 0) {
184 *got = 0;
185 return IO_CLOSED;
186 } else {
187 *got = taken;
188 return IO_DONE;
189 }
190 } else {
191 *got = 0;
192 return IO_TIMEOUT;
193 }
194}
195
196const char *sock_hoststrerror(void)
197{
198 switch (WSAGetLastError()) {
199 case HOST_NOT_FOUND: return "host not found";
200 case NO_ADDRESS: return "unable to resolve host name";
201 case NO_RECOVERY: return "name server error";
202 case TRY_AGAIN: return "name server unavailable, try again later.";
203 default: return "unknown error";
204 }
205}
206
207const char *sock_createstrerror(void)
208{
209 switch (WSAGetLastError()) {
210 case WSANOTINITIALISED: return "not initialized";
211 case WSAENETDOWN: return "network is down";
212 case WSAEMFILE: return "descriptor table is full";
213 case WSAENOBUFS: return "insufficient buffer space";
214 default: return "unknown error";
215 }
216}
217
218const char *sock_bindstrerror(void)
219{
220 switch (WSAGetLastError()) {
221 case WSANOTINITIALISED: return "not initialized";
222 case WSAENETDOWN: return "network is down";
223 case WSAEADDRINUSE: return "address already in use";
224 case WSAEINVAL: return "socket already bound";
225 case WSAENOBUFS: return "too many connections";
226 case WSAEFAULT: return "invalid address";
227 case WSAENOTSOCK: return "not a socket descriptor";
228 default: return "unknown error";
229 }
230}
231
232const char *sock_connectstrerror(void)
233{
234 switch (WSAGetLastError()) {
235 case WSANOTINITIALISED: return "not initialized";
236 case WSAENETDOWN: return "network is down";
237 case WSAEADDRINUSE: return "address already in use";
238 case WSAEADDRNOTAVAIL: return "address unavailable";
239 case WSAECONNREFUSED: return "connection refused";
240 case WSAENETUNREACH: return "network is unreachable";
241 default: return "unknown error";
242 }
243}
244
245void sock_setreuseaddr(p_sock ps)
246{
247 int val = 1;
248 setsockopt(*ps, SOL_SOCKET, SO_REUSEADDR, (char *)&val, sizeof(val));
249}
250
251void sock_setblocking(p_sock ps)
252{
253 u_long argp = 0;
254 ioctlsocket(*ps, FIONBIO, &argp);
255}
256
257void sock_setnonblocking(p_sock ps)
258{
259 u_long argp = 1;
260 ioctlsocket(*ps, FIONBIO, &argp);
261}
diff --git a/src/wsocket.h b/src/wsocket.h
new file mode 100644
index 0000000..ceecae7
--- /dev/null
+++ b/src/wsocket.h
@@ -0,0 +1,22 @@
1/*=========================================================================*\
2* Socket compatibilization module for Win32
3*
4* RCS ID: $Id$
5\*=========================================================================*/
6#ifndef WSOCKET_H
7#define WSOCKET_H
8
9/*=========================================================================*\
10* WinSock2 include files
11\*=========================================================================*/
12#include <winsock2.h>
13#include <winbase.h>
14
15typedef int socklen_t;
16typedef int ssize_t;
17typedef SOCKET t_sock;
18typedef t_sock *p_sock;
19
20#define SOCK_INVALID (INVALID_SOCKET)
21
22#endif /* WSOCKET_H */