aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--luasocket.vcproj4
-rw-r--r--mime.vcproj4
-rw-r--r--samples/forward.lua138
-rw-r--r--src/socket.h2
-rw-r--r--src/tcp.c6
-rw-r--r--src/usocket.c26
-rw-r--r--src/wsocket.c26
7 files changed, 106 insertions, 100 deletions
diff --git a/luasocket.vcproj b/luasocket.vcproj
index 14cbebf..71486d6 100644
--- a/luasocket.vcproj
+++ b/luasocket.vcproj
@@ -33,7 +33,7 @@
33 <Tool 33 <Tool
34 Name="VCLinkerTool" 34 Name="VCLinkerTool"
35 AdditionalDependencies="ws2_32.lib" 35 AdditionalDependencies="ws2_32.lib"
36 OutputFile="$(OutDir)/lsocket.dll" 36 OutputFile="$(OutDir)/csocket.dll"
37 LinkIncremental="2" 37 LinkIncremental="2"
38 GenerateDebugInformation="TRUE" 38 GenerateDebugInformation="TRUE"
39 ProgramDatabaseFile="$(OutDir)/luasocket.pdb" 39 ProgramDatabaseFile="$(OutDir)/luasocket.pdb"
@@ -81,7 +81,7 @@
81 <Tool 81 <Tool
82 Name="VCLinkerTool" 82 Name="VCLinkerTool"
83 AdditionalDependencies="ws2_32.lib" 83 AdditionalDependencies="ws2_32.lib"
84 OutputFile="$(OutDir)/lsocket.dll" 84 OutputFile="$(OutDir)/csocket.dll"
85 LinkIncremental="1" 85 LinkIncremental="1"
86 GenerateDebugInformation="TRUE" 86 GenerateDebugInformation="TRUE"
87 SubSystem="2" 87 SubSystem="2"
diff --git a/mime.vcproj b/mime.vcproj
index 9e73f7b..43d289a 100644
--- a/mime.vcproj
+++ b/mime.vcproj
@@ -32,7 +32,7 @@
32 Name="VCCustomBuildTool"/> 32 Name="VCCustomBuildTool"/>
33 <Tool 33 <Tool
34 Name="VCLinkerTool" 34 Name="VCLinkerTool"
35 OutputFile="$(OutDir)/lmime.dll" 35 OutputFile="$(OutDir)/cmime.dll"
36 LinkIncremental="2" 36 LinkIncremental="2"
37 GenerateDebugInformation="TRUE" 37 GenerateDebugInformation="TRUE"
38 ProgramDatabaseFile="$(OutDir)/mime.pdb" 38 ProgramDatabaseFile="$(OutDir)/mime.pdb"
@@ -79,7 +79,7 @@
79 Name="VCCustomBuildTool"/> 79 Name="VCCustomBuildTool"/>
80 <Tool 80 <Tool
81 Name="VCLinkerTool" 81 Name="VCLinkerTool"
82 OutputFile="$(OutDir)/lmime.dll" 82 OutputFile="$(OutDir)/cmime.dll"
83 LinkIncremental="1" 83 LinkIncremental="1"
84 GenerateDebugInformation="TRUE" 84 GenerateDebugInformation="TRUE"
85 SubSystem="2" 85 SubSystem="2"
diff --git a/samples/forward.lua b/samples/forward.lua
index c3f0605..46f51c8 100644
--- a/samples/forward.lua
+++ b/samples/forward.lua
@@ -35,6 +35,13 @@ local sending = newset()
35-- context for connections and servers 35-- context for connections and servers
36local context = {} 36local context = {}
37 37
38function wait(who, what)
39 if what == "input" then receiving:insert(who)
40 else sending:insert(who) end
41 context[who].last = socket.gettime()
42 coroutine.yield()
43end
44
38-- initializes the forward server 45-- initializes the forward server
39function init() 46function init()
40 if table.getn(arg) < 1 then 47 if table.getn(arg) < 1 then
@@ -63,145 +70,142 @@ function init()
63end 70end
64 71
65-- starts a connection in a non-blocking way 72-- starts a connection in a non-blocking way
66function nbkcon(host, port) 73function connect(who, host, port)
67 local peer, err = socket.tcp() 74 who:settimeout(0.1)
68 if not peer then return nil, err end 75print("trying to connect peer", who, host, port)
69 peer:settimeout(0) 76 local ret, err = who:connect(host, port)
70 local ret, err = peer:connect(host, port) 77 if not ret and err == "timeout" then
71 if ret then return peer end 78print("got timeout, will wait", who)
72 if err ~= "timeout" then 79 wait(who, "output")
73 peer:close() 80 ret, err = who:connected()
74 return nil, err 81print("connection results arrived", who, ret, err)
82 end
83 if not ret then
84print("connection failed", who)
85 kick(who)
86 kick(context[who].peer)
87 else
88 return forward(who)
75 end 89 end
76 return peer
77end 90end
78 91
79-- gets rid of a client 92-- gets rid of a client and its peer
80function kick(who) 93function kick(who)
81 if context[who] then 94 if who and context[who] then
82 sending:remove(who) 95 sending:remove(who)
83 receiving:remove(who) 96 receiving:remove(who)
97 local peer = context[who].peer
84 context[who] = nil 98 context[who] = nil
85 who:close() 99 who:close()
86 end 100 end
87end 101end
88 102
89-- decides what to do with a thread based on coroutine return
90function route(who, status, what)
91 if status and what then
92 if what == "receiving" then receiving:insert(who) end
93 if what == "sending" then sending:insert(who) end
94 else kick(who) end
95end
96
97-- loops accepting connections and creating new threads to deal with them 103-- loops accepting connections and creating new threads to deal with them
98function accept(server) 104function accept(server)
99 while true do 105 while true do
100 -- accept a new connection and start a new coroutine to deal with it 106 -- accept a new connection and start a new coroutine to deal with it
101 local client = server:accept() 107 local client = server:accept()
108print("accepted ", client)
102 if client then 109 if client then
103 -- start a new connection, non-blockingly, to the forwarding address 110 -- create contexts for client and peer.
104 local ohost = context[server].ohost 111 local peer, err = socket.tcp()
105 local oport = context[server].oport
106 local peer = nbkcon(ohost, oport)
107 if peer then 112 if peer then
108 context[client] = { 113 context[client] = {
109 last = socket.gettime(), 114 last = socket.gettime(),
115 -- client goes straight to forwarding loop
110 thread = coroutine.create(forward), 116 thread = coroutine.create(forward),
111 peer = peer, 117 peer = peer,
112 } 118 }
113 -- make sure peer will be tested for writing in the next select
114 -- round, which means the connection attempt has finished
115 sending:insert(peer)
116 context[peer] = { 119 context[peer] = {
120 last = socket.gettime(),
117 peer = client, 121 peer = client,
118 thread = coroutine.create(chkcon), 122 -- peer first tries to connect to forwarding address
123 thread = coroutine.create(connect),
119 last = socket.gettime() 124 last = socket.gettime()
120 } 125 }
121 -- put both in non-blocking mode 126 -- resume peer and client so they can do their thing
122 client:settimeout(0) 127 local ohost = context[server].ohost
123 peer:settimeout(0) 128 local oport = context[server].oport
129 coroutine.resume(context[peer].thread, peer, ohost, oport)
130 coroutine.resume(context[client].thread, client)
124 else 131 else
125 -- otherwise just dump the client 132 print(err)
126 client:close() 133 client:close()
127 end 134 end
128 end 135 end
129 -- tell scheduler we are done for now 136 -- tell scheduler we are done for now
130 coroutine.yield("receiving") 137 wait(server, "input")
131 end 138 end
132end 139end
133 140
134-- forwards all data arriving to the appropriate peer 141-- forwards all data arriving to the appropriate peer
135function forward(who) 142function forward(who)
143print("starting to foward", who)
144 who:settimeout(0)
136 while true do 145 while true do
146 -- wait until we have something to read
147 wait(who, "input")
137 -- try to read as much as possible 148 -- try to read as much as possible
138 local data, rec_err, partial = who:receive("*a") 149 local data, rec_err, partial = who:receive("*a")
139 -- if we had an error other than timeout, abort 150 -- if we had an error other than timeout, abort
140 if rec_err and rec_err ~= "timeout" then return error(rec_err) end 151 if rec_err and rec_err ~= "timeout" then return kick(who) end
141 -- if we got a timeout, we probably have partial results to send 152 -- if we got a timeout, we probably have partial results to send
142 data = data or partial 153 data = data or partial
143 -- renew our timestamp so scheduler sees we are active
144 context[who].last = socket.gettime()
145 -- forward what we got right away 154 -- forward what we got right away
146 local peer = context[who].peer 155 local peer = context[who].peer
147 while true do 156 while true do
148 -- tell scheduler we need to wait until we can send something 157 -- tell scheduler we need to wait until we can send something
149 coroutine.yield("sending") 158 wait(who, "output")
150 local ret, snd_err 159 local ret, snd_err
151 local start = 0 160 local start = 0
152 ret, snd_err, start = peer:send(data, start+1) 161 ret, snd_err, start = peer:send(data, start+1)
153 if ret then break 162 if ret then break
154 elseif snd_err ~= "timeout" then return error(snd_err) end 163 elseif snd_err ~= "timeout" then return kick(who) end
155 -- renew our timestamp so scheduler sees we are active
156 context[who].last = socket.gettime()
157 end 164 end
158 -- if we are done receiving, we are done with this side of the 165 -- if we are done receiving, we are done
159 -- connection 166 if not rec_err then return kick(who) end
160 if not rec_err then return nil end
161 -- otherwise tell schedule we have to wait for more data to arrive
162 coroutine.yield("receiving")
163 end 167 end
164end 168end
165 169
166-- checks if a connection completed successfully and if it did, starts
167-- forwarding all data
168function chkcon(who)
169 local ret, err = who:connected()
170 if ret then
171 receiving:insert(context[who].peer)
172 context[who].last = socket.gettime()
173 coroutine.yield("receiving")
174 return forward(who)
175 else return error(err) end
176end
177
178-- loop waiting until something happens, restarting the thread to deal with 170-- loop waiting until something happens, restarting the thread to deal with
179-- what happened, and routing it to wait until something else happens 171-- what happened, and routing it to wait until something else happens
180function go() 172function go()
181 while true do 173 while true do
174print("will select for reading")
175for i,v in ipairs(receiving) do
176 print(i, v)
177end
178print("will select for sending")
179for i,v in ipairs(sending) do
180 print(i, v)
181end
182 -- check which sockets are interesting and act on them 182 -- check which sockets are interesting and act on them
183 readable, writable = socket.select(receiving, sending, 3) 183 readable, writable = socket.select(receiving, sending, 3)
184 -- for all readable connections, resume its thread and route it 184print("was readable")
185for i,v in ipairs(readable) do
186 print(i, v)
187end
188print("was writable")
189for i,v in ipairs(writable) do
190 print(i, v)
191end
192 -- for all readable connections, resume its thread
185 for _, who in ipairs(readable) do 193 for _, who in ipairs(readable) do
186 receiving:remove(who) 194 receiving:remove(who)
187 if context[who] then 195 coroutine.resume(context[who].thread, who)
188 route(who, coroutine.resume(context[who].thread, who))
189 end
190 end 196 end
191 -- for all writable connections, do the same 197 -- for all writable connections, do the same
192 for _, who in ipairs(writable) do 198 for _, who in ipairs(writable) do
193 sending:remove(who) 199 sending:remove(who)
194 if context[who] then 200 coroutine.resume(context[who].thread, who)
195 route(who, coroutine.resume(context[who].thread, who))
196 end
197 end 201 end
198 -- put all inactive threads in death row 202 -- put all inactive threads in death row
199 local now = socket.gettime() 203 local now = socket.gettime()
200 local deathrow 204 local deathrow
201 for who, data in pairs(context) do 205 for who, data in pairs(context) do
202 if data.last then 206 if data.peer then
203 if now - data.last > TIMEOUT then 207 if now - data.last > TIMEOUT then
204 -- only create table if someone is doomed 208 -- only create table if at least one is doomed
205 deathrow = deathrow or {} 209 deathrow = deathrow or {}
206 deathrow[who] = true 210 deathrow[who] = true
207 end 211 end
diff --git a/src/socket.h b/src/socket.h
index 639229d..4443bcc 100644
--- a/src/socket.h
+++ b/src/socket.h
@@ -49,7 +49,7 @@ int sock_recvfrom(p_sock ps, char *data, size_t count,
49void sock_setnonblocking(p_sock ps); 49void sock_setnonblocking(p_sock ps);
50void sock_setblocking(p_sock ps); 50void sock_setblocking(p_sock ps);
51 51
52int sock_waitfd(int fd, int sw, p_tm tm); 52int sock_waitfd(p_sock ps, int sw, p_tm tm);
53int sock_select(int n, fd_set *rfds, fd_set *wfds, fd_set *efds, p_tm tm); 53int sock_select(int n, fd_set *rfds, fd_set *wfds, fd_set *efds, p_tm tm);
54 54
55int sock_connect(p_sock ps, SA *addr, socklen_t addr_len, p_tm tm); 55int sock_connect(p_sock ps, SA *addr, socklen_t addr_len, p_tm tm);
diff --git a/src/tcp.c b/src/tcp.c
index 162d5af..7ff3054 100644
--- a/src/tcp.c
+++ b/src/tcp.c
@@ -228,8 +228,10 @@ static int meth_connect(lua_State *L)
228 228
229static int meth_connected(lua_State *L) 229static int meth_connected(lua_State *L)
230{ 230{
231 p_tcp tcp = (p_tcp) aux_checkclass(L, "tcp{master}", 1); 231 p_tcp tcp;
232 int err = sock_connected(&tcp->sock, &tcp->tm); 232 int err;
233 tcp = (p_tcp) aux_checkclass(L, "tcp{master}", 1);
234 err = sock_connected(&tcp->sock, &tcp->tm);
233 if (err != IO_DONE) { 235 if (err != IO_DONE) {
234 lua_pushnil(L); 236 lua_pushnil(L);
235 lua_pushstring(L, sock_strerror(err)); 237 lua_pushstring(L, sock_strerror(err));
diff --git a/src/usocket.c b/src/usocket.c
index 3428a0c..3e151bf 100644
--- a/src/usocket.c
+++ b/src/usocket.c
@@ -22,10 +22,10 @@
22#define WAITFD_R POLLIN 22#define WAITFD_R POLLIN
23#define WAITFD_W POLLOUT 23#define WAITFD_W POLLOUT
24#define WAITFD_C (POLLIN|POLLOUT) 24#define WAITFD_C (POLLIN|POLLOUT)
25int sock_waitfd(int fd, int sw, p_tm tm) { 25int sock_waitfd(p_sock ps, int sw, p_tm tm) {
26 int ret; 26 int ret;
27 struct pollfd pfd; 27 struct pollfd pfd;
28 pfd.fd = fd; 28 pfd.fd = *ps;
29 pfd.events = sw; 29 pfd.events = sw;
30 pfd.revents = 0; 30 pfd.revents = 0;
31 if (tm_iszero(tm)) return IO_TIMEOUT; /* optimize timeout == 0 case */ 31 if (tm_iszero(tm)) return IO_TIMEOUT; /* optimize timeout == 0 case */
@@ -44,7 +44,7 @@ int sock_waitfd(int fd, int sw, p_tm tm) {
44#define WAITFD_W 2 44#define WAITFD_W 2
45#define WAITFD_C (WAITFD_R|WAITFD_W) 45#define WAITFD_C (WAITFD_R|WAITFD_W)
46 46
47int sock_waitfd(int fd, int sw, p_tm tm) { 47int sock_waitfd(p_sock ps, int sw, p_tm tm) {
48 int ret; 48 int ret;
49 fd_set rfds, wfds, *rp, *wp; 49 fd_set rfds, wfds, *rp, *wp;
50 struct timeval tv, *tp; 50 struct timeval tv, *tp;
@@ -53,8 +53,8 @@ int sock_waitfd(int fd, int sw, p_tm tm) {
53 do { 53 do {
54 /* must set bits within loop, because select may have modifed them */ 54 /* must set bits within loop, because select may have modifed them */
55 rp = wp = NULL; 55 rp = wp = NULL;
56 if (sw & WAITFD_R) { FD_ZERO(&rfds); FD_SET(fd, &rfds); rp = &rfds; } 56 if (sw & WAITFD_R) { FD_ZERO(&rfds); FD_SET(*ps, &rfds); rp = &rfds; }
57 if (sw & WAITFD_W) { FD_ZERO(&wfds); FD_SET(fd, &wfds); wp = &wfds; } 57 if (sw & WAITFD_W) { FD_ZERO(&wfds); FD_SET(*ps, &wfds); wp = &wfds; }
58 t = tm_getretry(tm); 58 t = tm_getretry(tm);
59 tp = NULL; 59 tp = NULL;
60 if (t >= 0.0) { 60 if (t >= 0.0) {
@@ -62,11 +62,11 @@ int sock_waitfd(int fd, int sw, p_tm tm) {
62 tv.tv_usec = (int)((t-tv.tv_sec)*1.0e6); 62 tv.tv_usec = (int)((t-tv.tv_sec)*1.0e6);
63 tp = &tv; 63 tp = &tv;
64 } 64 }
65 ret = select(fd+1, rp, wp, NULL, tp); 65 ret = select(*ps+1, rp, wp, NULL, tp);
66 } while (ret == -1 && errno == EINTR); 66 } while (ret == -1 && errno == EINTR);
67 if (ret == -1) return errno; 67 if (ret == -1) return errno;
68 if (ret == 0) return IO_TIMEOUT; 68 if (ret == 0) return IO_TIMEOUT;
69 if (sw == WAITFD_C && FD_ISSET(fd, &rfds)) return IO_CLOSED; 69 if (sw == WAITFD_C && FD_ISSET(*ps, &rfds)) return IO_CLOSED;
70 return IO_DONE; 70 return IO_DONE;
71} 71}
72#endif 72#endif
@@ -177,7 +177,7 @@ int sock_connect(p_sock ps, SA *addr, socklen_t len, p_tm tm) {
177\*-------------------------------------------------------------------------*/ 177\*-------------------------------------------------------------------------*/
178int sock_connected(p_sock ps, p_tm tm) { 178int sock_connected(p_sock ps, p_tm tm) {
179 int err; 179 int err;
180 if ((err = sock_waitfd(*ps, WAITFD_C, tm) == IO_CLOSED)) { 180 if ((err = sock_waitfd(ps, WAITFD_C, tm) == IO_CLOSED)) {
181 if (recv(*ps, (char *) &err, 0, 0) == 0) return IO_DONE; 181 if (recv(*ps, (char *) &err, 0, 0) == 0) return IO_DONE;
182 else return errno; 182 else return errno;
183 } else return err; 183 } else return err;
@@ -198,7 +198,7 @@ int sock_accept(p_sock ps, p_sock pa, SA *addr, socklen_t *len, p_tm tm) {
198 err = errno; 198 err = errno;
199 if (err == EINTR) continue; 199 if (err == EINTR) continue;
200 if (err != EAGAIN && err != ECONNABORTED) return err; 200 if (err != EAGAIN && err != ECONNABORTED) return err;
201 if ((err = sock_waitfd(*ps, WAITFD_R, tm)) != IO_DONE) return err; 201 if ((err = sock_waitfd(ps, WAITFD_R, tm)) != IO_DONE) return err;
202 } 202 }
203 /* can't reach here */ 203 /* can't reach here */
204 return IO_UNKNOWN; 204 return IO_UNKNOWN;
@@ -230,7 +230,7 @@ int sock_send(p_sock ps, const char *data, size_t count, size_t *sent, p_tm tm)
230 /* if failed fatal reason, report error */ 230 /* if failed fatal reason, report error */
231 if (err != EAGAIN) return err; 231 if (err != EAGAIN) return err;
232 /* wait until we can send something or we timeout */ 232 /* wait until we can send something or we timeout */
233 if ((err = sock_waitfd(*ps, WAITFD_W, tm)) != IO_DONE) return err; 233 if ((err = sock_waitfd(ps, WAITFD_W, tm)) != IO_DONE) return err;
234 } 234 }
235 /* can't reach here */ 235 /* can't reach here */
236 return IO_UNKNOWN; 236 return IO_UNKNOWN;
@@ -255,7 +255,7 @@ int sock_sendto(p_sock ps, const char *data, size_t count, size_t *sent,
255 if (put == 0 || err == EPIPE) return IO_CLOSED; 255 if (put == 0 || err == EPIPE) return IO_CLOSED;
256 if (err == EINTR) continue; 256 if (err == EINTR) continue;
257 if (err != EAGAIN) return err; 257 if (err != EAGAIN) return err;
258 if ((err = sock_waitfd(*ps, WAITFD_W, tm)) != IO_DONE) return err; 258 if ((err = sock_waitfd(ps, WAITFD_W, tm)) != IO_DONE) return err;
259 } 259 }
260 return IO_UNKNOWN; 260 return IO_UNKNOWN;
261} 261}
@@ -277,7 +277,7 @@ int sock_recv(p_sock ps, char *data, size_t count, size_t *got, p_tm tm) {
277 if (taken == 0) return IO_CLOSED; 277 if (taken == 0) return IO_CLOSED;
278 if (err == EINTR) continue; 278 if (err == EINTR) continue;
279 if (err != EAGAIN) return err; 279 if (err != EAGAIN) return err;
280 if ((err = sock_waitfd(*ps, WAITFD_R, tm)) != IO_DONE) return err; 280 if ((err = sock_waitfd(ps, WAITFD_R, tm)) != IO_DONE) return err;
281 } 281 }
282 return IO_UNKNOWN; 282 return IO_UNKNOWN;
283} 283}
@@ -300,7 +300,7 @@ int sock_recvfrom(p_sock ps, char *data, size_t count, size_t *got,
300 if (taken == 0) return IO_CLOSED; 300 if (taken == 0) return IO_CLOSED;
301 if (err == EINTR) continue; 301 if (err == EINTR) continue;
302 if (err != EAGAIN) return err; 302 if (err != EAGAIN) return err;
303 if ((err = sock_waitfd(*ps, WAITFD_R, tm)) != IO_DONE) return err; 303 if ((err = sock_waitfd(ps, WAITFD_R, tm)) != IO_DONE) return err;
304 } 304 }
305 return IO_UNKNOWN; 305 return IO_UNKNOWN;
306} 306}
diff --git a/src/wsocket.c b/src/wsocket.c
index c0686cd..8b00fa5 100644
--- a/src/wsocket.c
+++ b/src/wsocket.c
@@ -45,15 +45,15 @@ int sock_close(void) {
45#define WAITFD_E 4 45#define WAITFD_E 4
46#define WAITFD_C (WAITFD_E|WAITFD_W) 46#define WAITFD_C (WAITFD_E|WAITFD_W)
47 47
48int sock_waitfd(t_sock fd, int sw, p_tm tm) { 48int sock_waitfd(p_sock ps, int sw, p_tm tm) {
49 int ret; 49 int ret;
50 fd_set rfds, wfds, efds, *rp = NULL, *wp = NULL, *ep = NULL; 50 fd_set rfds, wfds, efds, *rp = NULL, *wp = NULL, *ep = NULL;
51 struct timeval tv, *tp = NULL; 51 struct timeval tv, *tp = NULL;
52 double t; 52 double t;
53 if (tm_iszero(tm)) return IO_TIMEOUT; /* optimize timeout == 0 case */ 53 if (tm_iszero(tm)) return IO_TIMEOUT; /* optimize timeout == 0 case */
54 if (sw & WAITFD_R) { FD_ZERO(&rfds); FD_SET(fd, &rfds); rp = &rfds; } 54 if (sw & WAITFD_R) { FD_ZERO(&rfds); FD_SET(*ps, &rfds); rp = &rfds; }
55 if (sw & WAITFD_W) { FD_ZERO(&wfds); FD_SET(fd, &wfds); wp = &wfds; } 55 if (sw & WAITFD_W) { FD_ZERO(&wfds); FD_SET(*ps, &wfds); wp = &wfds; }
56 if (sw & WAITFD_C) { FD_ZERO(&efds); FD_SET(fd, &efds); ep = &efds; } 56 if (sw & WAITFD_C) { FD_ZERO(&efds); FD_SET(*ps, &efds); ep = &efds; }
57 if ((t = tm_get(tm)) >= 0.0) { 57 if ((t = tm_get(tm)) >= 0.0) {
58 tv.tv_sec = (int) t; 58 tv.tv_sec = (int) t;
59 tv.tv_usec = (int) ((t-tv.tv_sec)*1.0e6); 59 tv.tv_usec = (int) ((t-tv.tv_sec)*1.0e6);
@@ -62,7 +62,7 @@ int sock_waitfd(t_sock fd, int sw, p_tm tm) {
62 ret = select(0, rp, wp, ep, tp); 62 ret = select(0, rp, wp, ep, tp);
63 if (ret == -1) return WSAGetLastError(); 63 if (ret == -1) return WSAGetLastError();
64 if (ret == 0) return IO_TIMEOUT; 64 if (ret == 0) return IO_TIMEOUT;
65 if (sw == WAITFD_C && FD_ISSET(fd, &efds)) return IO_CLOSED; 65 if (sw == WAITFD_C && FD_ISSET(*ps, &efds)) return IO_CLOSED;
66 return IO_DONE; 66 return IO_DONE;
67} 67}
68 68
@@ -127,15 +127,15 @@ int sock_connect(p_sock ps, SA *addr, socklen_t len, p_tm tm) {
127/*-------------------------------------------------------------------------*\ 127/*-------------------------------------------------------------------------*\
128* Check if socket is connected 128* Check if socket is connected
129\*-------------------------------------------------------------------------*/ 129\*-------------------------------------------------------------------------*/
130int sock_connected(p_sock ps) { 130int sock_connected(p_sock ps, p_tm tm) {
131 int err; 131 int err;
132 if ((err = sock_waitfd(*ps, WAITFD_C, tm)) == IO_CLOSED) { 132 if ((err = sock_waitfd(ps, WAITFD_C, tm)) == IO_CLOSED) {
133 int len = sizeof(err); 133 int len = sizeof(err);
134 /* give windows time to set the error (yes, disgusting) */ 134 /* give windows time to set the error (yes, disgusting) */
135 Sleep(0); 135 Sleep(0);
136 /* find out why we failed */ 136 /* find out why we failed */
137 getsockopt(*ps, SOL_SOCKET, SO_ERROR, (char *)&err, &len); 137 getsockopt(*ps, SOL_SOCKET, SO_ERROR, (char *)&err, &len);
138 /* we KNOW there was an error. if why is 0, we will return 138 /* we KNOW there was an error. if 'why' is 0, we will return
139 * "unknown error", but it's not really our fault */ 139 * "unknown error", but it's not really our fault */
140 return err > 0? err: IO_UNKNOWN; 140 return err > 0? err: IO_UNKNOWN;
141 } else return err; 141 } else return err;
@@ -181,7 +181,7 @@ int sock_accept(p_sock ps, p_sock pa, SA *addr, socklen_t *len, p_tm tm) {
181 /* if we failed because there was no connectoin, keep trying */ 181 /* if we failed because there was no connectoin, keep trying */
182 if (err != WSAEWOULDBLOCK && err != WSAECONNABORTED) return err; 182 if (err != WSAEWOULDBLOCK && err != WSAECONNABORTED) return err;
183 /* call select to avoid busy wait */ 183 /* call select to avoid busy wait */
184 if ((err = sock_waitfd(*ps, WAITFD_R, tm)) != IO_DONE) return err; 184 if ((err = sock_waitfd(ps, WAITFD_R, tm)) != IO_DONE) return err;
185 } 185 }
186 /* can't reach here */ 186 /* can't reach here */
187 return IO_UNKNOWN; 187 return IO_UNKNOWN;
@@ -213,7 +213,7 @@ int sock_send(p_sock ps, const char *data, size_t count, size_t *sent, p_tm tm)
213 /* we can only proceed if there was no serious error */ 213 /* we can only proceed if there was no serious error */
214 if (err != WSAEWOULDBLOCK) return err; 214 if (err != WSAEWOULDBLOCK) return err;
215 /* avoid busy wait */ 215 /* avoid busy wait */
216 if ((err = sock_waitfd(*ps, WAITFD_W, tm)) != IO_DONE) return err; 216 if ((err = sock_waitfd(ps, WAITFD_W, tm)) != IO_DONE) return err;
217 } 217 }
218 /* can't reach here */ 218 /* can't reach here */
219 return IO_UNKNOWN; 219 return IO_UNKNOWN;
@@ -236,7 +236,7 @@ int sock_sendto(p_sock ps, const char *data, size_t count, size_t *sent,
236 } 236 }
237 err = WSAGetLastError(); 237 err = WSAGetLastError();
238 if (err != WSAEWOULDBLOCK) return err; 238 if (err != WSAEWOULDBLOCK) return err;
239 if ((err = sock_waitfd(*ps, WAITFD_W, tm)) != IO_DONE) return err; 239 if ((err = sock_waitfd(ps, WAITFD_W, tm)) != IO_DONE) return err;
240 } 240 }
241 return IO_UNKNOWN; 241 return IO_UNKNOWN;
242} 242}
@@ -257,7 +257,7 @@ int sock_recv(p_sock ps, char *data, size_t count, size_t *got, p_tm tm) {
257 if (taken == 0) return IO_CLOSED; 257 if (taken == 0) return IO_CLOSED;
258 err = WSAGetLastError(); 258 err = WSAGetLastError();
259 if (err != WSAEWOULDBLOCK) return err; 259 if (err != WSAEWOULDBLOCK) return err;
260 if ((err = sock_waitfd(*ps, WAITFD_R, tm)) != IO_DONE) return err; 260 if ((err = sock_waitfd(ps, WAITFD_R, tm)) != IO_DONE) return err;
261 } 261 }
262 return IO_UNKNOWN; 262 return IO_UNKNOWN;
263} 263}
@@ -279,7 +279,7 @@ int sock_recvfrom(p_sock ps, char *data, size_t count, size_t *got,
279 if (taken == 0) return IO_CLOSED; 279 if (taken == 0) return IO_CLOSED;
280 err = WSAGetLastError(); 280 err = WSAGetLastError();
281 if (err != WSAEWOULDBLOCK) return err; 281 if (err != WSAEWOULDBLOCK) return err;
282 if ((err = sock_waitfd(*ps, WAITFD_R, tm)) != IO_DONE) return err; 282 if ((err = sock_waitfd(ps, WAITFD_R, tm)) != IO_DONE) return err;
283 } 283 }
284 return IO_UNKNOWN; 284 return IO_UNKNOWN;
285} 285}