str_cli_kqueue04.c 1.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253
  1. #include "unp.h"
  2. void
  3. str_cli(FILE *fp, int sockfd)
  4. {
  5. int kq, i, n, nev, stdineof = 0, isfile;
  6. char buf[MAXLINE];
  7. struct kevent kev[2];
  8. struct timespec ts;
  9. struct stat st;
  10. isfile = ((fstat(fileno(fp), &st) == 0) &&
  11. (st.st_mode & S_IFMT) == S_IFREG);
  12. EV_SET(&kev[0], fileno(fp), EVFILT_READ, EV_ADD, 0, 0, NULL);
  13. EV_SET(&kev[1], sockfd, EVFILT_READ, EV_ADD, 0, 0, NULL);
  14. kq = Kqueue();
  15. ts.tv_sec = ts.tv_nsec = 0;
  16. Kevent(kq, kev, 2, NULL, 0, &ts);
  17. for ( ; ; ) {
  18. nev = Kevent(kq, NULL, 0, kev, 2, NULL);
  19. for (i = 0; i < nev; i++) {
  20. if (kev[i].ident == sockfd) { /* socket is readable */
  21. if ( (n = Read(sockfd, buf, MAXLINE)) == 0) {
  22. if (stdineof == 1)
  23. return; /* normal termination */
  24. else
  25. err_quit("str_cli: server terminated prematurely");
  26. }
  27. Write(fileno(stdout), buf, n);
  28. }
  29. if (kev[i].ident == fileno(fp)) { /* input is readable */
  30. n = Read(fileno(fp), buf, MAXLINE);
  31. if (n > 0)
  32. Writen(sockfd, buf, n);
  33. if (n == 0 || (isfile && n == kev[i].data)) {
  34. stdineof = 1;
  35. Shutdown(sockfd, SHUT_WR); /* send FIN */
  36. kev[i].flags = EV_DELETE;
  37. Kevent(kq, &kev[i], 1, NULL, 0, &ts); /* remove kevent */
  38. continue;
  39. }
  40. }
  41. }
  42. }
  43. }