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