diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/lib.h | 1 | ||||
-rw-r--r-- | lib/net.c | 37 |
2 files changed, 38 insertions, 0 deletions
@@ -281,6 +281,7 @@ void xsetsockopt(int fd, int level, int opt, void *val, socklen_t len); int xconnect(char *host, char *port, int family, int socktype, int protocol, int flags); int xpoll(struct pollfd *fds, int nfds, int timeout); +int pollinate(int in1, int in2, int out1, int out2, int timeout, int shutdown_timeout); // password.c int get_salt(char *salt, char * algo); @@ -55,3 +55,40 @@ int xpoll(struct pollfd *fds, int nfds, int timeout) } else return i; } } + +// Loop forwarding data from in1 to out1 and in2 to out2, handling +// half-connection shutdown. timeouts return if no data for X miliseconds. +// Returns 0: both closed, 1 shutdown_timeout, 2 timeout +int pollinate(int in1, int in2, int out1, int out2, int timeout, int shutdown_timeout) +{ + struct pollfd pollfds[2]; + int i, pollcount = 2; + + memset(pollfds, 0, 2*sizeof(struct pollfd)); + pollfds[0].events = pollfds[1].events = POLLIN; + pollfds[0].fd = in1; + pollfds[1].fd = in2; + + // Poll loop copying data from each fd to the other one. + for (;;) { + if (!xpoll(pollfds, pollcount, timeout)) return pollcount; + + for (i=0; i<pollcount; i++) { + if (pollfds[i].revents & POLLIN) { + int len = read(pollfds[i].fd, libbuf, sizeof(libbuf)); + if (len<1) pollfds[i].revents = POLLHUP; + else xwrite(i ? out2 : out1, libbuf, len); + } + if (pollfds[i].revents & POLLHUP) { + // Close half-connection. This is needed for things like + // "echo GET / | netcat landley.net 80" + // Note that in1 closing triggers timeout, in2 returns now. + if (i) { + shutdown(pollfds[0].fd, SHUT_WR); + pollcount--; + timeout = shutdown_timeout; + } else return 0; + } + } + } +} |