aboutsummaryrefslogtreecommitdiff
path: root/src/wsocket.c
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 /src/wsocket.c
parent58bdb658aaa1c30a8f3bed46eef880d308fae582 (diff)
downloadluasocket-f330540576031528f0daac231c61d4dd06e8ba1e.tar.gz
luasocket-f330540576031528f0daac231c61d4dd06e8ba1e.tar.bz2
luasocket-f330540576031528f0daac231c61d4dd06e8ba1e.zip
Compiles and runs on linux and windows, using DLLs!
Diffstat (limited to 'src/wsocket.c')
-rw-r--r--src/wsocket.c261
1 files changed, 261 insertions, 0 deletions
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}