On Mon, Jun 16, 2014 at 10:57 PM, Ted Unangst <[email protected]> wrote:
> On Sat, Jun 14, 2014 at 10:55, Ted Unangst wrote: > > On Fri, Jun 13, 2014 at 10:40, sven falempin wrote: > >>>> > >>>> Now soliciting diffs to change readwrite to a loop with two buffers > >>>> that poll()s in all four directions. :) > >>>> > >>>> > >>> Is using kqueue ok ? > >>> > >>> like : http://pastebin.com/F1c5Hswi > > > > uh, maybe. the kqueue changes make it harder to review at first, but > > I'll look closer soonish. > > Turns out pastebin isn't a very good place for storing diffs. It's > gone now, making it very hard to review. Can you send the diff to the > list? Thanks. > Index: netcat.c =================================================================== RCS file: /cvs/src/usr.bin/nc/netcat.c,v retrieving revision 1.121 diff -u -p -r1.121 netcat.c --- netcat.c 10 Jun 2014 16:35:42 -0000 1.121 +++ netcat.c 14 Jun 2014 17:46:31 -0000 @@ -36,6 +36,7 @@ #include <sys/time.h> #include <sys/uio.h> #include <sys/un.h> +#include <sys/event.h> #include <netinet/in.h> #include <netinet/in_systm.h> @@ -734,58 +735,124 @@ readwrite(int nfd) { struct pollfd pfd[2]; unsigned char buf[16 * 1024]; + struct kevent keventlist[4]; + quad_t write_space_network; + quad_t write_space_stdout; + quad_t available; int n, wfd = fileno(stdin); int lfd = fileno(stdout); int plen; + int kq; + int evcount; + int evid; plen = sizeof(buf); - /* Setup Network FD */ - pfd[0].fd = nfd; - pfd[0].events = POLLIN; + /* Set up kqueue*/ + kq = kqueue(); + if (kq == -1) { + close(nfd); + err(1, "Kqueue Error"); + } + + /* Set up STDOUT FD. */ + EV_SET(&keventlist[0], nfd, EVFILT_WRITE, EV_ADD, 0, 0, NULL); + + /* Set up Network FD */ + EV_SET(&keventlist[1], lfd, EVFILT_WRITE, EV_ADD, 0, 0, NULL); + EV_SET(&keventlist[2], nfd, EVFILT_READ, EV_ADD, 0, 0, NULL); /* Set up STDIN FD. */ - pfd[1].fd = wfd; - pfd[1].events = POLLIN; + EV_SET(&keventlist[3], wfd, EVFILT_READ, EV_ADD, 0, 0, NULL); - while (pfd[0].fd != -1) { + /* Registering events */ + evcount = kevent(kq, keventlist, 4, NULL, 0, NULL); + if (evcount == -1) { + close(nfd); + err(1, "Kevent Error"); + } + + while (evcount != -1) { if (iflag) sleep(iflag); - - if ((n = poll(pfd, 2 - dflag, timeout)) < 0) { + evcount = kevent(kq, NULL, 0, keventlist, 4, NULL); + if (evcount == -1) { close(nfd); - err(1, "Polling Error"); + err(1, "Kevent Error"); } + for (evid = 0; evid < evcount; evid++) { + struct kevent event = keventlist[evid]; + if (event.flags & EV_ERROR) { + close(nfd); + err(1, "Kevent Error"); + } - if (n == 0) - return; - - if (pfd[0].revents & POLLIN) { - if ((n = read(nfd, buf, plen)) < 0) - return; - else if (n == 0) { - shutdown(nfd, SHUT_RD); - pfd[0].fd = -1; - pfd[0].events = 0; - } else { - if (tflag) - atelnet(nfd, buf, n); - if (atomicio(vwrite, lfd, buf, n) != n) + if (event.ident == nfd) { + if (event.flags & EV_EOF) { + shutdown(nfd, SHUT_RD); return; + } else { + if (event.filter == EVFILT_WRITE) { + write_space_network = event.data; + } + else if (event.filter == EVFILT_READ) { + available = MIN(event.data, write_space_stdout); + available = MIN(available, plen); + if (available > 0) { + n = read(nfd, buf, available); + if (n != available) { + return; + } else { + n = write(lfd, buf, available); + if (n != available) { + return; + } + } + write_space_stdout -= available; + /* Break to ignore EVFILT_WRITE that could + * be in current keventlist, after this event + * and which is now invalid, because we just + * write in the fd. + */ + break; + } + } + } } - } - - if (!dflag && pfd[1].revents & POLLIN) { - if ((n = read(wfd, buf, plen)) < 0) - return; - else if (n == 0) { - if (Nflag) - shutdown(nfd, SHUT_WR); - pfd[1].fd = -1; - pfd[1].events = 0; - } else { - if (atomicio(vwrite, nfd, buf, n) != n) + else if (event.ident == lfd) { + if (event.filter == EVFILT_WRITE) { + write_space_stdout = event.data; + } + } + else if (event.ident == wfd) { + if (event.flags & EV_EOF) { + if (Nflag) + shutdown(nfd, SHUT_WR); return; + } else { + if (event.filter == EVFILT_READ) { + available = MIN(event.data, write_space_network); + available = MIN(available, plen); + if (available > 0) { + n = read(wfd, buf, available); + if (n != available) { + return; + } else { + n = write(nfd, buf, available); + if (n != available) { + return; + } + } + write_space_network -= available; + /* Break to ignore EVFILT_WRITE that could + * be in current keventlist, after this event + * and which is now invalid, because we just + * write in the fd. + */ + break; + } + } + } -- --------------------------------------------------------------------------------------------------------------------- () ascii ribbon campaign - against html e-mail /\
