12#include <sys/socket.h>
14inline 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()
34static inline bool isselectable(
int s)
38 return ((HANDLE)_get_osfhandle(s) == INVALID_HANDLE_VALUE)
55 : rfd(_rwfd), wfd(_rwfd)
62 : rfd(_rfd), wfd(_wfd)
74static int _cloexec(
int fd,
bool close_on_exec)
77 return fcntl(fd, F_SETFD, close_on_exec ? FD_CLOEXEC : 0);
84static 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);
103 _nonblock(
wfd, nonblock);
111 _cloexec(
rfd, close_on_exec);
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;
The basic interface which is included by all other XPLC interfaces and objects.
size_t used() const
Returns the number of elements in the buffer currently available for reading.
A WvFastString acts exactly like a WvString, but can take (const char *) strings without needing to a...
int num() const
Return a stdc++ string with the contents of this string.
Base class for streams built on Unix file descriptors.
bool shutdown_read
Have we actually shut down the read/write sides?
virtual void maybe_autoclose()
Auto-close the stream if the time is right.
WvFdStream(int rwfd=-1)
Creates a WvStream from an existing file descriptor.
int getrfd() const
Returns the Unix file descriptor for reading from this stream.
virtual size_t uread(void *buf, size_t count)
unbuffered I/O functions; these ignore the buffer, which is handled by read().
virtual bool isok() const
return true if the stream is actually usable right now
int getwfd() const
Returns the Unix file descriptor for writing to this stream.
void set_nonblock(bool nonblock)
Make the fds on this stream blocking or non-blocking.
virtual void close()
Closes the file descriptors.
virtual ~WvFdStream()
Destroys the stream and invokes close().
void set_close_on_exec(bool close_on_exec)
Make the fds on this stream close-on-exec or not.
virtual bool post_select(SelectInfo &si)
post_select() is called after select(), and returns true if this object is now ready.
int rfd
The file descriptor for reading.
virtual void pre_select(SelectInfo &si)
pre_select() sets up for eventually calling select().
virtual size_t uwrite(const void *buf, size_t count)
unbuffered I/O functions; these ignore the buffer, which is handled by write().
int wfd
The file descriptor for writing.
A type-safe version of WvMonikerBase that lets you provide create functions for object types other th...
virtual bool post_select(SelectInfo &si)
post_select() is called after select(), and returns true if this object is now ready.
virtual bool isok() const
return true if the stream is actually usable right now
bool stop_read
True if noread()/nowrite()/close() have been called, respectively.
virtual size_t write(const void *buf, size_t count)
Write data to the stream.
virtual bool should_flush()
Returns true if we want to flush the output buffer right now.
virtual void pre_select(SelectInfo &si)
pre_select() sets up for eventually calling select().
bool select(time_t msec_timeout)
Return true if any of the requested features are true on the stream.
WvStream * read_requires_writable
If this is set, select() doesn't return true for read unless the given stream also returns true for w...
virtual void maybe_autoclose()
Auto-close the stream if the time is right.
virtual size_t read(void *buf, size_t count)
read a data block on the stream.
virtual void close()
Close the stream if it is open; isok() becomes false from now on.
virtual void seterr(int _errnum)
Override seterr() from WvError so that it auto-closes the stream.
WvStream * write_requires_readable
If this is set, select() doesn't return true for write unless the given stream also returns true for ...
the data structure used by pre_select()/post_select() and internally by select().