File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / mtr / select.c
Revision 1.1: download - view: text, annotated - select for diffs - revision graph
Sun Jul 21 23:43:41 2013 UTC (11 years, 3 months ago) by misho
CVS tags: MAIN, HEAD
Initial revision

    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: #include <sys/types.h>
   21: #include <sys/time.h>
   22: #include <stdlib.h>
   23: #include <stdio.h>
   24: #include <unistd.h>
   25: #include <time.h>
   26: #include <sys/select.h>
   27: #include <string.h>
   28: #include <math.h>
   29: #include <errno.h>
   30: 
   31: #include "mtr.h"
   32: #include "display.h"
   33: #include "dns.h"
   34: #include "net.h"
   35: #ifndef NO_IPINFO
   36: #include "asn.h"
   37: #endif
   38: 
   39: extern int Interactive;
   40: extern int MaxPing;
   41: extern int ForceMaxPing;
   42: extern float WaitTime;
   43: double dnsinterval;
   44: extern int mtrtype;
   45: 
   46: static struct timeval intervaltime;
   47: int display_offset = 0;
   48: 
   49: 
   50: void select_loop(void) {
   51:   fd_set readfd;
   52:   fd_set writefd;
   53:   int anyset = 0;
   54:   int maxfd = 0;
   55:   int dnsfd, netfd;
   56: #ifdef ENABLE_IPV6
   57:   int dnsfd6;
   58: #endif
   59:   int NumPing = 0;
   60:   int paused = 0;
   61:   struct timeval lasttime, thistime, selecttime;
   62:   int dt;
   63:   int rv; 
   64: 
   65:   gettimeofday(&lasttime, NULL);
   66: 
   67:   while(1) {
   68:     dt = calc_deltatime (WaitTime);
   69:     intervaltime.tv_sec  = dt / 1000000;
   70:     intervaltime.tv_usec = dt % 1000000;
   71: 
   72:     FD_ZERO(&readfd);
   73:     FD_ZERO(&writefd);
   74: 
   75:     maxfd = 0;
   76: 
   77:     if(Interactive) {
   78:       FD_SET(0, &readfd);
   79:       maxfd = 1;
   80:     }
   81: 
   82: #ifdef ENABLE_IPV6
   83:     if (dns) {
   84:       dnsfd6 = dns_waitfd6();
   85:       FD_SET(dnsfd6, &readfd);
   86:       if(dnsfd6 >= maxfd) maxfd = dnsfd6 + 1;
   87:     } else
   88:       dnsfd6 = 0;
   89: #endif
   90:     if (dns) {
   91:       dnsfd = dns_waitfd();
   92:       FD_SET(dnsfd, &readfd);
   93:       if(dnsfd >= maxfd) maxfd = dnsfd + 1;
   94:     } else
   95:       dnsfd = 0;
   96: 
   97:     netfd = net_waitfd();
   98:     FD_SET(netfd, &readfd);
   99:     if(netfd >= maxfd) maxfd = netfd + 1;
  100: 
  101:     if (mtrtype == IPPROTO_TCP)
  102:       net_add_fds(&writefd, &maxfd);
  103: 
  104:     do {
  105:       if(anyset || paused) {
  106: 	selecttime.tv_sec = 0;
  107: 	selecttime.tv_usec = 0;
  108:       
  109: 	rv = select(maxfd, (void *)&readfd, &writefd, NULL, &selecttime);
  110: 
  111:       } else {
  112: 	if(Interactive) display_redraw();
  113: 
  114: 	gettimeofday(&thistime, NULL);
  115: 
  116: 	if(thistime.tv_sec > lasttime.tv_sec + intervaltime.tv_sec ||
  117: 	   (thistime.tv_sec == lasttime.tv_sec + intervaltime.tv_sec &&
  118: 	    thistime.tv_usec >= lasttime.tv_usec + intervaltime.tv_usec)) {
  119: 	  lasttime = thistime;
  120: 	  if(NumPing >= MaxPing && (!Interactive || ForceMaxPing))
  121: 	    return;
  122: 	  if (net_send_batch())
  123: 	    NumPing++;
  124: 	}
  125: 
  126: 	selecttime.tv_usec = (thistime.tv_usec - lasttime.tv_usec);
  127: 	selecttime.tv_sec = (thistime.tv_sec - lasttime.tv_sec);
  128: 	if (selecttime.tv_usec < 0) {
  129: 	  --selecttime.tv_sec;
  130: 	  selecttime.tv_usec += 1000000;
  131: 	}
  132: 	selecttime.tv_usec = intervaltime.tv_usec - selecttime.tv_usec;
  133: 	selecttime.tv_sec = intervaltime.tv_sec - selecttime.tv_sec;
  134: 	if (selecttime.tv_usec < 0) {
  135: 	  --selecttime.tv_sec;
  136: 	  selecttime.tv_usec += 1000000;
  137: 	}
  138: 
  139: 	if (dns) {
  140: 	  if ((selecttime.tv_sec > (time_t)dnsinterval) ||
  141: 	      ((selecttime.tv_sec == (time_t)dnsinterval) &&
  142: 	       (selecttime.tv_usec > ((time_t)(dnsinterval * 1000000) % 1000000)))) {
  143: 	    selecttime.tv_sec = (time_t)dnsinterval;
  144: 	    selecttime.tv_usec = (time_t)(dnsinterval * 1000000) % 1000000;
  145: 	  }
  146: 	}
  147: 
  148: 	rv = select(maxfd, (void *)&readfd, NULL, NULL, &selecttime);
  149:       }
  150:     } while ((rv < 0) && (errno == EINTR));
  151: 
  152:     if (rv < 0) {
  153:       perror ("Select failed");
  154:       exit (1);
  155:     }
  156:     anyset = 0;
  157: 
  158:     /*  Have we got new packets back?  */
  159:     if(FD_ISSET(netfd, &readfd)) {
  160:       net_process_return();
  161:       anyset = 1;
  162:     }
  163: 
  164:     if (dns) {
  165:       /* Handle any pending resolver events */
  166:       dnsinterval = WaitTime;
  167:       dns_events(&dnsinterval);
  168:     }
  169: 
  170:     /*  Have we finished a nameservice lookup?  */
  171: #ifdef ENABLE_IPV6
  172:     if(dns && FD_ISSET(dnsfd6, &readfd)) {
  173:       dns_ack6();
  174:       anyset = 1;
  175:     }
  176: #endif
  177:     if(dns && FD_ISSET(dnsfd, &readfd)) {
  178:       dns_ack();
  179:       anyset = 1;
  180:     }
  181: 
  182:     /*  Has a key been pressed?  */
  183:     if(FD_ISSET(0, &readfd)) {
  184:       switch (display_keyaction()) {
  185:       case ActionQuit: 
  186: 	return;
  187: 	break;
  188:       case ActionReset:
  189: 	net_reset();
  190: 	break;
  191:       case ActionDisplay:
  192:         display_mode = (display_mode+1) % 3;
  193: 	break;
  194:       case ActionClear:
  195: 	display_clear();
  196: 	break;
  197:       case ActionPause:
  198: 	paused=1;
  199: 	break;
  200:       case  ActionResume:
  201: 	paused=0;
  202: 	break;
  203:       case ActionMPLS:
  204: 	   enablempls = !enablempls;
  205: 	   display_clear();
  206: 	break;
  207:       case ActionDNS:
  208: 	if (dns) {
  209: 	  use_dns = !use_dns;
  210: 	  display_clear();
  211: 	}
  212: 	break;
  213: #ifndef NO_IPINFO
  214:       case ActionII:
  215: 	if (ipinfo_no >= 0) {
  216: 	  ipinfo_no++;
  217:           if (ipinfo_no > ipinfo_max)
  218:             ipinfo_no = 0;
  219: 	}
  220: 	break;
  221:       case ActionAS:
  222: 	if (ipinfo_no >= 0)
  223:           ipinfo_no = ipinfo_no?0:ipinfo_max;
  224: 	break;
  225: #endif
  226: 
  227:       case ActionScrollDown:
  228:         display_offset += 5;
  229: 	break;
  230:       case ActionScrollUp:
  231:         display_offset -= 5;
  232: 	if (display_offset < 0) {
  233: 	  display_offset = 0;
  234: 	}
  235: 	break;
  236:       }
  237:       anyset = 1;
  238:     }
  239: 
  240:     /* Check for activity on open sockets */
  241:     if (mtrtype == IPPROTO_TCP)
  242:       net_process_fds(&writefd);
  243:   }
  244:   return;
  245: }
  246: 

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