⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 event.c

📁 adns for unix/linux, adns-1.3.tar.gz
💻 C
📖 第 1 页 / 共 2 页
字号:
      ads->tcprecv_skip= 0;      if (!adns__vbuf_ensure(&ads->tcprecv,want)) { r= ENOMEM; goto xit; }      assert(ads->tcprecv.used <= ads->tcprecv.avail);      if (ads->tcprecv.used == ads->tcprecv.avail) continue;      r= read(ads->tcpsocket,	      ads->tcprecv.buf+ads->tcprecv.used,	      ads->tcprecv.avail-ads->tcprecv.used);      if (r>0) {	ads->tcprecv.used+= r;      } else {	if (r) {	  if (errno==EAGAIN || errno==EWOULDBLOCK) { r= 0; goto xit; }	  if (errno==EINTR) continue;	  if (errno_resources(errno)) { r= errno; goto xit; }	}	adns__tcp_broken(ads,"read",r?strerror(errno):"closed");      }    } while (ads->tcpstate == server_ok);    r= 0; goto xit;  default:    abort();  }  if (fd == ads->udpsocket) {    for (;;) {      udpaddrlen= sizeof(udpaddr);      r= recvfrom(ads->udpsocket,udpbuf,sizeof(udpbuf),0,		  (struct sockaddr*)&udpaddr,&udpaddrlen);      if (r<0) {	if (errno == EAGAIN || errno == EWOULDBLOCK) { r= 0; goto xit; }	if (errno == EINTR) continue;	if (errno_resources(errno)) { r= errno; goto xit; }	adns__warn(ads,-1,0,"datagram receive error: %s",strerror(errno));	r= 0; goto xit;      }      if (udpaddrlen != sizeof(udpaddr)) {	adns__diag(ads,-1,0,"datagram received with wrong address length %d"		   " (expected %lu)", udpaddrlen,		   (unsigned long)sizeof(udpaddr));	continue;      }      if (udpaddr.sin_family != AF_INET) {	adns__diag(ads,-1,0,"datagram received with wrong protocol family"		   " %u (expected %u)",udpaddr.sin_family,AF_INET);	continue;      }      if (ntohs(udpaddr.sin_port) != DNS_PORT) {	adns__diag(ads,-1,0,"datagram received from wrong port"		   " %u (expected %u)", ntohs(udpaddr.sin_port),DNS_PORT);	continue;      }      for (serv= 0;	   serv < ads->nservers &&	     ads->servers[serv].addr.s_addr != udpaddr.sin_addr.s_addr;	   serv++);      if (serv >= ads->nservers) {	adns__warn(ads,-1,0,"datagram received from unknown nameserver %s",		   inet_ntoa(udpaddr.sin_addr));	continue;      }      adns__procdgram(ads,udpbuf,r,serv,0,*now);    }  }  r= 0;xit:  adns__consistency(ads,0,cc_entex);  return r;}int adns_processwriteable(adns_state ads, int fd, const struct timeval *now) {  int r;    adns__consistency(ads,0,cc_entex);  switch (ads->tcpstate) {  case server_disconnected:  case server_broken:    break;  case server_connecting:    if (fd != ads->tcpsocket) break;    assert(ads->tcprecv.used==0);    assert(ads->tcprecv_skip==0);    for (;;) {      if (!adns__vbuf_ensure(&ads->tcprecv,1)) { r= ENOMEM; goto xit; }      r= read(ads->tcpsocket,&ads->tcprecv.buf,1);      if (r==0 || (r<0 && (errno==EAGAIN || errno==EWOULDBLOCK))) {	tcp_connected(ads,*now);	r= 0; goto xit;      }      if (r>0) {	adns__tcp_broken(ads,"connect/read","sent data before first request");	r= 0; goto xit;      }      if (errno==EINTR) continue;      if (errno_resources(errno)) { r= errno; goto xit; }      adns__tcp_broken(ads,"connect/read",strerror(errno));      r= 0; goto xit;    } /* not reached */  case server_ok:    if (fd != ads->tcpsocket) break;    while (ads->tcpsend.used) {      adns__sigpipe_protect(ads);      r= write(ads->tcpsocket,ads->tcpsend.buf,ads->tcpsend.used);      adns__sigpipe_unprotect(ads);      if (r<0) {	if (errno==EINTR) continue;	if (errno==EAGAIN || errno==EWOULDBLOCK) { r= 0; goto xit; }	if (errno_resources(errno)) { r= errno; goto xit; }	adns__tcp_broken(ads,"write",strerror(errno));	r= 0; goto xit;      } else if (r>0) {	ads->tcpsend.used -= r;	memmove(ads->tcpsend.buf,ads->tcpsend.buf+r,ads->tcpsend.used);      }    }    r= 0;    goto xit;  default:    abort();  }  r= 0;xit:  adns__consistency(ads,0,cc_entex);  return r;}  int adns_processexceptional(adns_state ads, int fd,			    const struct timeval *now) {  adns__consistency(ads,0,cc_entex);  switch (ads->tcpstate) {  case server_disconnected:  case server_broken:    break;  case server_connecting:  case server_ok:    if (fd != ads->tcpsocket) break;    adns__tcp_broken(ads,"poll/select","exceptional condition detected");    break;  default:    abort();  }  adns__consistency(ads,0,cc_entex);  return 0;}static void fd_event(adns_state ads, int fd,		     int revent, int pollflag,		     int maxfd, const fd_set *fds,		     int (*func)(adns_state, int fd,				 const struct timeval *now),		     struct timeval now, int *r_r) {  int r;    if (!(revent & pollflag)) return;  if (fds && !(fd<maxfd && FD_ISSET(fd,fds))) return;  r= func(ads,fd,&now);  if (r) {    if (r_r) {      *r_r= r;    } else {      adns__diag(ads,-1,0,"process fd failed after select:"		 " %s",strerror(errno));      adns_globalsystemfailure(ads);    }  }}void adns__fdevents(adns_state ads,		    const struct pollfd *pollfds, int npollfds,		    int maxfd, const fd_set *readfds,		    const fd_set *writefds, const fd_set *exceptfds,		    struct timeval now, int *r_r) {  int i, fd, revents;  for (i=0; i<npollfds; i++) {    fd= pollfds[i].fd;    if (fd >= maxfd) maxfd= fd+1;    revents= pollfds[i].revents;#define EV(pollfl,fds,how)  \    fd_event(ads,fd, revents,pollfl, maxfd,fds, adns_process##how,now,r_r)    EV( POLLIN,  readfds,   readable    );    EV( POLLOUT, writefds,  writeable   );    EV( POLLPRI, exceptfds, exceptional );#undef EV  }}/* Wrappers for select(2). */void adns_beforeselect(adns_state ads, int *maxfd_io, fd_set *readfds_io,		       fd_set *writefds_io, fd_set *exceptfds_io,		       struct timeval **tv_mod, struct timeval *tv_tobuf,		       const struct timeval *now) {  struct timeval tv_nowbuf;  struct pollfd pollfds[MAX_POLLFDS];  int i, fd, maxfd, npollfds;    adns__consistency(ads,0,cc_entex);  if (tv_mod && (!*tv_mod || (*tv_mod)->tv_sec || (*tv_mod)->tv_usec)) {    /* The caller is planning to sleep. */    adns__must_gettimeofday(ads,&now,&tv_nowbuf);    if (!now) { inter_immed(tv_mod,tv_tobuf); goto xit; }    adns__timeouts(ads, 0, tv_mod,tv_tobuf, *now);  }  npollfds= adns__pollfds(ads,pollfds);  maxfd= *maxfd_io;  for (i=0; i<npollfds; i++) {    fd= pollfds[i].fd;    if (fd >= maxfd) maxfd= fd+1;    if (pollfds[i].events & POLLIN) FD_SET(fd,readfds_io);    if (pollfds[i].events & POLLOUT) FD_SET(fd,writefds_io);    if (pollfds[i].events & POLLPRI) FD_SET(fd,exceptfds_io);  }  *maxfd_io= maxfd;xit:  adns__consistency(ads,0,cc_entex);}void adns_afterselect(adns_state ads, int maxfd, const fd_set *readfds,		      const fd_set *writefds, const fd_set *exceptfds,		      const struct timeval *now) {  struct timeval tv_buf;  struct pollfd pollfds[MAX_POLLFDS];  int npollfds, i;  adns__consistency(ads,0,cc_entex);  adns__must_gettimeofday(ads,&now,&tv_buf);  if (!now) goto xit;  adns_processtimeouts(ads,now);  npollfds= adns__pollfds(ads,pollfds);  for (i=0; i<npollfds; i++) pollfds[i].revents= POLLIN|POLLOUT|POLLPRI;  adns__fdevents(ads,		 pollfds,npollfds,		 maxfd,readfds,writefds,exceptfds,		 *now, 0);xit:  adns__consistency(ads,0,cc_entex);}/* General helpful functions. */void adns_globalsystemfailure(adns_state ads) {  adns__consistency(ads,0,cc_entex);  while (ads->udpw.head) adns__query_fail(ads->udpw.head, adns_s_systemfail);  while (ads->tcpw.head) adns__query_fail(ads->tcpw.head, adns_s_systemfail);    switch (ads->tcpstate) {  case server_connecting:  case server_ok:    adns__tcp_broken(ads,0,0);    break;  case server_disconnected:  case server_broken:    break;  default:    abort();  }  adns__consistency(ads,0,cc_entex);}int adns_processany(adns_state ads) {  int r, i;  struct timeval now;  struct pollfd pollfds[MAX_POLLFDS];  int npollfds;  adns__consistency(ads,0,cc_entex);  r= gettimeofday(&now,0);  if (!r) adns_processtimeouts(ads,&now);  /* We just use adns__fdevents to loop over the fd's trying them.   * This seems more sensible than calling select, since we're most   * likely just to want to do a read on one or two fds anyway.   */  npollfds= adns__pollfds(ads,pollfds);  for (i=0; i<npollfds; i++) pollfds[i].revents= pollfds[i].events & ~POLLPRI;  adns__fdevents(ads,		 pollfds,npollfds,		 0,0,0,0,		 now,&r);  adns__consistency(ads,0,cc_entex);  return 0;}void adns__autosys(adns_state ads, struct timeval now) {  if (ads->iflags & adns_if_noautosys) return;  adns_processany(ads);}int adns__internal_check(adns_state ads,			 adns_query *query_io,			 adns_answer **answer,			 void **context_r) {  adns_query qu;  qu= *query_io;  if (!qu) {    if (ads->output.head) {      qu= ads->output.head;    } else if (ads->udpw.head || ads->tcpw.head) {      return EAGAIN;    } else {      return ESRCH;    }  } else {    if (qu->id>=0) return EAGAIN;  }  LIST_UNLINK(ads->output,qu);  *answer= qu->answer;  if (context_r) *context_r= qu->ctx.ext;  *query_io= qu;  free(qu);  return 0;}int adns_wait(adns_state ads,	      adns_query *query_io,	      adns_answer **answer_r,	      void **context_r) {  int r, maxfd, rsel;  fd_set readfds, writefds, exceptfds;  struct timeval tvbuf, *tvp;    adns__consistency(ads,*query_io,cc_entex);  for (;;) {    r= adns__internal_check(ads,query_io,answer_r,context_r);    if (r != EAGAIN) break;    maxfd= 0; tvp= 0;    FD_ZERO(&readfds); FD_ZERO(&writefds); FD_ZERO(&exceptfds);    adns_beforeselect(ads,&maxfd,&readfds,&writefds,&exceptfds,&tvp,&tvbuf,0);    assert(tvp);    rsel= select(maxfd,&readfds,&writefds,&exceptfds,tvp);    if (rsel==-1) {      if (errno == EINTR) {	if (ads->iflags & adns_if_eintr) { r= EINTR; break; }      } else {	adns__diag(ads,-1,0,"select failed in wait: %s",strerror(errno));	adns_globalsystemfailure(ads);      }    } else {      assert(rsel >= 0);      adns_afterselect(ads,maxfd,&readfds,&writefds,&exceptfds,0);    }  }  adns__consistency(ads,0,cc_entex);  return r;}int adns_check(adns_state ads,	       adns_query *query_io,	       adns_answer **answer_r,	       void **context_r) {  struct timeval now;  int r;    adns__consistency(ads,*query_io,cc_entex);  r= gettimeofday(&now,0);  if (!r) adns__autosys(ads,now);  r= adns__internal_check(ads,query_io,answer_r,context_r);  adns__consistency(ads,0,cc_entex);  return r;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -