7 #include "wvfdstream.h"
12 #include <sys/socket.h>
14 inline bool isselectable(
int fd)
21 #define getsockopt(a,b,c,d,e) getsockopt(a,b,c,(char *)d, e)
22 #define SHUT_RD SD_RECEIVE
23 #define SHUT_WR SD_SEND
24 #define ENOBUFS WSAENOBUFS
26 #define EAGAIN WSAEWOULDBLOCK
31 #define errno GetLastError()
34 static inline bool isselectable(
int s)
38 return ((HANDLE)_get_osfhandle(s) == INVALID_HANDLE_VALUE)
55 : rfd(_rwfd), wfd(_rwfd)
62 : rfd(_rfd), wfd(_wfd)
74 static int _cloexec(
int fd,
bool close_on_exec)
76 #ifndef _WIN32 // there is no exec() in win32, so this is meaningless there
77 return fcntl(fd, F_SETFD, close_on_exec ? FD_CLOEXEC : 0);
84 static int _nonblock(
int fd,
bool nonblock)
87 int flag = fcntl(fd, F_GETFL);
88 return fcntl(fd, F_SETFL,
89 (flag & ~O_NONBLOCK) | (nonblock ? O_NONBLOCK : 0));
91 u_long arg = nonblock ? 1 : 0;
92 return ioctlsocket(fd, FIONBIO, &arg);
101 _nonblock(rfd, nonblock);
102 if (
wfd >= 0 && rfd !=
wfd)
103 _nonblock(
wfd, nonblock);
111 _cloexec(rfd, close_on_exec);
112 if (
wfd >= 0 && rfd !=
wfd)
113 _cloexec(
wfd, close_on_exec);
142 assert(!count || buf);
143 if (!count || !buf || !
isok())
return 0;
150 if (in < 0 && (errno==EINTR || errno==EAGAIN || errno==ENOBUFS))
153 seterr(in < 0 ? errno : 0);
164 assert(!count || buf);
165 if (!buf || !count || !
isok())
return 0;
174 if (out < 0 && (err == ENOBUFS || err==EAGAIN))
177 seterr(out < 0 ? err : 0);
188 if (stop_write && !shutdown_write && !outbuf.
used())
190 shutdown_write =
true;
196 ::shutdown(
wfd, SHUT_WR);
206 ::shutdown(
rfd, SHUT_RD);
219 fprintf(stderr,
"%d/%d wr:%d ww:%d wx:%d inh:%d\n",
rfd,
wfd,
220 si.wants.readable, si.wants.writable, si.wants.isexception,
223 if (si.wants.readable && (
rfd >= 0))
225 if (isselectable(
rfd))
226 FD_SET(
rfd, &si.read);
233 if ((si.wants.writable || outbuf.
used() || autoclose_time) && (
wfd >= 0))
235 if (isselectable(
wfd))
236 FD_SET(
wfd, &si.write);
241 if (si.wants.isexception)
243 if (
rfd >= 0 && isselectable(
rfd)) FD_SET(
rfd, &si.except);
244 if (
wfd >= 0 && isselectable(
wfd)) FD_SET(
wfd, &si.except);
259 size_t outbuf_used = outbuf.
used();
260 if (
wfd >= 0 && (outbuf_used || autoclose_time)
270 bool rforce = si.wants.readable && !isselectable(
rfd),
271 wforce = si.wants.writable && !isselectable(
wfd);
273 (
rfd >= 0 && (rforce || FD_ISSET(
rfd, &si.read)))
274 || (
wfd >= 0 && (wforce || FD_ISSET(
wfd, &si.write)))
275 || (
rfd >= 0 && (FD_ISSET(
rfd, &si.except)))
276 || (
wfd >= 0 && (FD_ISSET(
wfd, &si.except)));
289 return val || result;