| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121 |
- /* include dgecho1 */
- #include "unp.h"
- static int sockfd;
- #define QSIZE 8 /* size of input queue */
- #define MAXDG 4096 /* max datagram size */
- typedef struct {
- void *dg_data; /* ptr to actual datagram */
- size_t dg_len; /* length of datagram */
- struct sockaddr *dg_sa; /* ptr to sockaddr{} w/client's address */
- socklen_t dg_salen; /* length of sockaddr{} */
- } DG;
- static DG dg[QSIZE]; /* queue of datagrams to process */
- static long cntread[QSIZE+1]; /* diagnostic counter */
- static int iget; /* next one for main loop to process */
- static int iput; /* next one for signal handler to read into */
- static int nqueue; /* # on queue for main loop to process */
- static socklen_t clilen;/* max length of sockaddr{} */
- static void sig_io(int);
- static void sig_hup(int);
- /* end dgecho1 */
- /* include dgecho2 */
- void
- dg_echo(int sockfd_arg, SA *pcliaddr, socklen_t clilen_arg)
- {
- int i;
- const int on = 1;
- sigset_t zeromask, newmask, oldmask;
- sockfd = sockfd_arg;
- clilen = clilen_arg;
- for (i = 0; i < QSIZE; i++) { /* init queue of buffers */
- dg[i].dg_data = Malloc(MAXDG);
- dg[i].dg_sa = Malloc(clilen);
- dg[i].dg_salen = clilen;
- }
- iget = iput = nqueue = 0;
- Signal(SIGHUP, sig_hup);
- Signal(SIGIO, sig_io);
- Fcntl(sockfd, F_SETOWN, getpid());
- Ioctl(sockfd, FIOASYNC, &on);
- Ioctl(sockfd, FIONBIO, &on);
- Sigemptyset(&zeromask); /* init three signal sets */
- Sigemptyset(&oldmask);
- Sigemptyset(&newmask);
- Sigaddset(&newmask, SIGIO); /* signal we want to block */
- Sigprocmask(SIG_BLOCK, &newmask, &oldmask);
- for ( ; ; ) {
- while (nqueue == 0)
- sigsuspend(&zeromask); /* wait for datagram to process */
- /* 4unblock SIGIO */
- Sigprocmask(SIG_SETMASK, &oldmask, NULL);
- Sendto(sockfd, dg[iget].dg_data, dg[iget].dg_len, 0,
- dg[iget].dg_sa, dg[iget].dg_salen);
- if (++iget >= QSIZE)
- iget = 0;
- /* 4block SIGIO */
- Sigprocmask(SIG_BLOCK, &newmask, &oldmask);
- nqueue--;
- }
- }
- /* end dgecho2 */
- /* include sig_io */
- static void
- sig_io(int signo)
- {
- ssize_t len;
- int nread;
- DG *ptr;
- for (nread = 0; ; ) {
- if (nqueue >= QSIZE)
- err_quit("receive overflow");
- ptr = &dg[iput];
- ptr->dg_salen = clilen;
- len = recvfrom(sockfd, ptr->dg_data, MAXDG, 0,
- ptr->dg_sa, &ptr->dg_salen);
- if (len < 0) {
- if (errno == EWOULDBLOCK)
- break; /* all done; no more queued to read */
- else
- err_sys("recvfrom error");
- }
- ptr->dg_len = len;
- nread++;
- nqueue++;
- if (++iput >= QSIZE)
- iput = 0;
- }
- cntread[nread]++; /* histogram of # datagrams read per signal */
- }
- /* end sig_io */
- /* include sig_hup */
- static void
- sig_hup(int signo)
- {
- int i;
- for (i = 0; i <= QSIZE; i++)
- printf("cntread[%d] = %ld\n", i, cntread[i]);
- }
- /* end sig_hup */
|