dgecho01.c 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  1. /* include dgecho1 */
  2. #include "unp.h"
  3. static int sockfd;
  4. #define QSIZE 8 /* size of input queue */
  5. #define MAXDG 4096 /* max datagram size */
  6. typedef struct {
  7. void *dg_data; /* ptr to actual datagram */
  8. size_t dg_len; /* length of datagram */
  9. struct sockaddr *dg_sa; /* ptr to sockaddr{} w/client's address */
  10. socklen_t dg_salen; /* length of sockaddr{} */
  11. } DG;
  12. static DG dg[QSIZE]; /* queue of datagrams to process */
  13. static long cntread[QSIZE+1]; /* diagnostic counter */
  14. static int iget; /* next one for main loop to process */
  15. static int iput; /* next one for signal handler to read into */
  16. static int nqueue; /* # on queue for main loop to process */
  17. static socklen_t clilen;/* max length of sockaddr{} */
  18. static void sig_io(int);
  19. static void sig_hup(int);
  20. /* end dgecho1 */
  21. /* include dgecho2 */
  22. void
  23. dg_echo(int sockfd_arg, SA *pcliaddr, socklen_t clilen_arg)
  24. {
  25. int i;
  26. const int on = 1;
  27. sigset_t zeromask, newmask, oldmask;
  28. sockfd = sockfd_arg;
  29. clilen = clilen_arg;
  30. for (i = 0; i < QSIZE; i++) { /* init queue of buffers */
  31. dg[i].dg_data = Malloc(MAXDG);
  32. dg[i].dg_sa = Malloc(clilen);
  33. dg[i].dg_salen = clilen;
  34. }
  35. iget = iput = nqueue = 0;
  36. Signal(SIGHUP, sig_hup);
  37. Signal(SIGIO, sig_io);
  38. Fcntl(sockfd, F_SETOWN, getpid());
  39. Ioctl(sockfd, FIOASYNC, &on);
  40. Ioctl(sockfd, FIONBIO, &on);
  41. Sigemptyset(&zeromask); /* init three signal sets */
  42. Sigemptyset(&oldmask);
  43. Sigemptyset(&newmask);
  44. Sigaddset(&newmask, SIGIO); /* signal we want to block */
  45. Sigprocmask(SIG_BLOCK, &newmask, &oldmask);
  46. for ( ; ; ) {
  47. while (nqueue == 0)
  48. sigsuspend(&zeromask); /* wait for datagram to process */
  49. /* 4unblock SIGIO */
  50. Sigprocmask(SIG_SETMASK, &oldmask, NULL);
  51. Sendto(sockfd, dg[iget].dg_data, dg[iget].dg_len, 0,
  52. dg[iget].dg_sa, dg[iget].dg_salen);
  53. if (++iget >= QSIZE)
  54. iget = 0;
  55. /* 4block SIGIO */
  56. Sigprocmask(SIG_BLOCK, &newmask, &oldmask);
  57. nqueue--;
  58. }
  59. }
  60. /* end dgecho2 */
  61. /* include sig_io */
  62. static void
  63. sig_io(int signo)
  64. {
  65. ssize_t len;
  66. int nread;
  67. DG *ptr;
  68. for (nread = 0; ; ) {
  69. if (nqueue >= QSIZE)
  70. err_quit("receive overflow");
  71. ptr = &dg[iput];
  72. ptr->dg_salen = clilen;
  73. len = recvfrom(sockfd, ptr->dg_data, MAXDG, 0,
  74. ptr->dg_sa, &ptr->dg_salen);
  75. if (len < 0) {
  76. if (errno == EWOULDBLOCK)
  77. break; /* all done; no more queued to read */
  78. else
  79. err_sys("recvfrom error");
  80. }
  81. ptr->dg_len = len;
  82. nread++;
  83. nqueue++;
  84. if (++iput >= QSIZE)
  85. iput = 0;
  86. }
  87. cntread[nread]++; /* histogram of # datagrams read per signal */
  88. }
  89. /* end sig_io */
  90. /* include sig_hup */
  91. static void
  92. sig_hup(int signo)
  93. {
  94. int i;
  95. for (i = 0; i <= QSIZE; i++)
  96. printf("cntread[%d] = %ld\n", i, cntread[i]);
  97. }
  98. /* end sig_hup */