File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / mtr / select.c
Revision 1.1.1.2 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue Nov 1 09:33:48 2016 UTC (7 years, 8 months ago) by misho
Branches: mtr, elwix, MAIN
CVS tags: v0_86, HEAD
mtr 0.86

    1: /*
    2:     mtr  --  a network diagnostic tool
    3:     Copyright (C) 1997,1998  Matt Kimball
    4: 
    5:     This program is free software; you can redistribute it and/or modify
    6:     it under the terms of the GNU General Public License version 2 as 
    7:     published by the Free Software Foundation.
    8: 
    9:     This program is distributed in the hope that it will be useful,
   10:     but WITHOUT ANY WARRANTY; without even the implied warranty of
   11:     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   12:     GNU General Public License for more details.
   13: 
   14:     You should have received a copy of the GNU General Public License
   15:     along with this program; if not, write to the Free Software
   16:     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
   17: */
   18: 
   19: #include "config.h"
   20: 
   21: #include <sys/types.h>
   22: #include <sys/time.h>
   23: #include <stdlib.h>
   24: #include <stdio.h>
   25: #include <unistd.h>
   26: #include <time.h>
   27: #include <sys/select.h>
   28: #include <string.h>
   29: #include <math.h>
   30: #include <errno.h>
   31: 
   32: #include "mtr.h"
   33: #include "dns.h"
   34: #include "net.h"
   35: #include "asn.h"
   36: #include "display.h"
   37: 
   38: extern int Interactive;
   39: extern int MaxPing;
   40: extern int ForceMaxPing;
   41: extern float WaitTime;
   42: double dnsinterval;
   43: extern int mtrtype;
   44: 
   45: static struct timeval intervaltime;
   46: int display_offset = 0;
   47: 
   48: 
   49: #define GRACETIME (5 * 1000*1000)
   50: 
   51: void select_loop(void) {
   52:   fd_set readfd;
   53:   fd_set writefd;
   54:   int anyset = 0;
   55:   int maxfd = 0;
   56:   int dnsfd, netfd;
   57: #ifdef ENABLE_IPV6
   58:   int dnsfd6;
   59: #endif
   60:   int NumPing = 0;
   61:   int paused = 0;
   62:   struct timeval lasttime, thistime, selecttime;
   63:   struct timeval startgrace;
   64:   int dt;
   65:   int rv; 
   66:   int graceperiod = 0;
   67: 
   68:   memset(&startgrace, 0, sizeof(startgrace));
   69: 
   70:   gettimeofday(&lasttime, NULL);
   71: 
   72:   while(1) {
   73:     dt = calc_deltatime (WaitTime);
   74:     intervaltime.tv_sec  = dt / 1000000;
   75:     intervaltime.tv_usec = dt % 1000000;
   76: 
   77:     FD_ZERO(&readfd);
   78:     FD_ZERO(&writefd);
   79: 
   80:     maxfd = 0;
   81: 
   82:     if(Interactive) {
   83:       FD_SET(0, &readfd);
   84:       maxfd = 1;
   85:     }
   86: 
   87: #ifdef ENABLE_IPV6
   88:     if (dns) {
   89:       dnsfd6 = dns_waitfd6();
   90:       if (dnsfd6 >= 0) {
   91:         FD_SET(dnsfd6, &readfd);
   92:         if(dnsfd6 >= maxfd) maxfd = dnsfd6 + 1;
   93:       } else {
   94:         dnsfd6 = 0;
   95:       }
   96:     } else
   97:       dnsfd6 = 0;
   98: #endif
   99:     if (dns) {
  100:       dnsfd = dns_waitfd();
  101:       FD_SET(dnsfd, &readfd);
  102:       if(dnsfd >= maxfd) maxfd = dnsfd + 1;
  103:     } else
  104:       dnsfd = 0;
  105: 
  106:     netfd = net_waitfd();
  107:     FD_SET(netfd, &readfd);
  108:     if(netfd >= maxfd) maxfd = netfd + 1;
  109: 
  110:     if (mtrtype == IPPROTO_TCP)
  111:       net_add_fds(&writefd, &maxfd);
  112: 
  113:     do {
  114:       if(anyset || paused) {
  115: 	/* Set timeout to 0.1s.
  116: 	 * While this is almost instantaneous for human operators,
  117: 	 * it's slow enough for computers to go do something else;
  118: 	 * this prevents mtr from hogging 100% CPU time on one core.
  119: 	 */
  120: 	selecttime.tv_sec = 0;
  121: 	selecttime.tv_usec = paused?100000:0; 
  122:       
  123: 	rv = select(maxfd, (void *)&readfd, &writefd, NULL, &selecttime);
  124: 
  125:       } else {
  126: 	if(Interactive) display_redraw();
  127: 
  128: 	gettimeofday(&thistime, NULL);
  129: 
  130: 	if(thistime.tv_sec > lasttime.tv_sec + intervaltime.tv_sec ||
  131: 	   (thistime.tv_sec == lasttime.tv_sec + intervaltime.tv_sec &&
  132: 	    thistime.tv_usec >= lasttime.tv_usec + intervaltime.tv_usec)) {
  133: 	  lasttime = thistime;
  134: 
  135: 	  if (!graceperiod) {
  136: 	    if (NumPing >= MaxPing && (!Interactive || ForceMaxPing)) {
  137: 	      graceperiod = 1;
  138: 	      startgrace = thistime;
  139: 	    }
  140: 
  141: 	    /* do not send out batch when we've already initiated grace period */
  142: 	    if (!graceperiod && net_send_batch())
  143: 	      NumPing++;
  144: 	  }
  145: 	}
  146: 
  147: 	if (graceperiod) {
  148: 	  dt = (thistime.tv_usec - startgrace.tv_usec) +
  149: 		    1000000 * (thistime.tv_sec - startgrace.tv_sec);
  150: 	  if (dt > GRACETIME)
  151: 	    return;
  152: 	}
  153: 
  154: 	selecttime.tv_usec = (thistime.tv_usec - lasttime.tv_usec);
  155: 	selecttime.tv_sec = (thistime.tv_sec - lasttime.tv_sec);
  156: 	if (selecttime.tv_usec < 0) {
  157: 	  --selecttime.tv_sec;
  158: 	  selecttime.tv_usec += 1000000;
  159: 	}
  160: 	selecttime.tv_usec = intervaltime.tv_usec - selecttime.tv_usec;
  161: 	selecttime.tv_sec = intervaltime.tv_sec - selecttime.tv_sec;
  162: 	if (selecttime.tv_usec < 0) {
  163: 	  --selecttime.tv_sec;
  164: 	  selecttime.tv_usec += 1000000;
  165: 	}
  166: 
  167: 	if (dns) {
  168: 	  if ((selecttime.tv_sec > (time_t)dnsinterval) ||
  169: 	      ((selecttime.tv_sec == (time_t)dnsinterval) &&
  170: 	       (selecttime.tv_usec > ((time_t)(dnsinterval * 1000000) % 1000000)))) {
  171: 	    selecttime.tv_sec = (time_t)dnsinterval;
  172: 	    selecttime.tv_usec = (time_t)(dnsinterval * 1000000) % 1000000;
  173: 	  }
  174: 	}
  175: 
  176: 	rv = select(maxfd, (void *)&readfd, NULL, NULL, &selecttime);
  177:       }
  178:     } while ((rv < 0) && (errno == EINTR));
  179: 
  180:     if (rv < 0) {
  181:       perror ("Select failed");
  182:       exit (1);
  183:     }
  184:     anyset = 0;
  185: 
  186:     /*  Have we got new packets back?  */
  187:     if(FD_ISSET(netfd, &readfd)) {
  188:       net_process_return();
  189:       anyset = 1;
  190:     }
  191: 
  192:     if (dns) {
  193:       /* Handle any pending resolver events */
  194:       dnsinterval = WaitTime;
  195:       dns_events(&dnsinterval);
  196:     }
  197: 
  198:     /*  Have we finished a nameservice lookup?  */
  199: #ifdef ENABLE_IPV6
  200:     if(dns && dnsfd6 && FD_ISSET(dnsfd6, &readfd)) {
  201:       dns_ack6();
  202:       anyset = 1;
  203:     }
  204: #endif
  205:     if(dns && dnsfd && FD_ISSET(dnsfd, &readfd)) {
  206:       dns_ack();
  207:       anyset = 1;
  208:     }
  209: 
  210:     /*  Has a key been pressed?  */
  211:     if(FD_ISSET(0, &readfd)) {
  212:       switch (display_keyaction()) {
  213:       case ActionQuit: 
  214: 	return;
  215: 	break;
  216:       case ActionReset:
  217: 	net_reset();
  218: 	break;
  219:       case ActionDisplay:
  220:         display_mode = (display_mode+1) % 3;
  221: 	break;
  222:       case ActionClear:
  223: 	display_clear();
  224: 	break;
  225:       case ActionPause:
  226: 	paused=1;
  227: 	break;
  228:       case  ActionResume:
  229: 	paused=0;
  230: 	break;
  231:       case ActionMPLS:
  232: 	   enablempls = !enablempls;
  233: 	   display_clear();
  234: 	break;
  235:       case ActionDNS:
  236: 	if (dns) {
  237: 	  use_dns = !use_dns;
  238: 	  display_clear();
  239: 	}
  240: 	break;
  241: #ifdef IPINFO
  242:       case ActionII:
  243: 	if (ipinfo_no >= 0) {
  244: 	  ipinfo_no++;
  245:           if (ipinfo_no > ipinfo_max)
  246:             ipinfo_no = 0;
  247: 	}
  248: 	break;
  249:       case ActionAS:
  250: 	if (ipinfo_no >= 0)
  251:           ipinfo_no = ipinfo_no?0:ipinfo_max;
  252: 	break;
  253: #endif
  254: 
  255:       case ActionScrollDown:
  256:         display_offset += 5;
  257: 	break;
  258:       case ActionScrollUp:
  259:         display_offset -= 5;
  260: 	if (display_offset < 0) {
  261: 	  display_offset = 0;
  262: 	}
  263: 	break;
  264:       }
  265:       anyset = 1;
  266:     }
  267: 
  268:     /* Check for activity on open sockets */
  269:     if (mtrtype == IPPROTO_TCP)
  270:       net_process_fds(&writefd);
  271:   }
  272:   return;
  273: }
  274: 

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>