Annotation of embedaddon/mtr/select.c, revision 1.1.1.2

1.1       misho       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: 
1.1.1.2 ! misho      19: #include "config.h"
        !            20: 
1.1       misho      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"
1.1.1.2 ! misho      36: #include "display.h"
1.1       misho      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: 
1.1.1.2 ! misho      49: #define GRACETIME (5 * 1000*1000)
        !            50: 
1.1       misho      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;
1.1.1.2 ! misho      63:   struct timeval startgrace;
1.1       misho      64:   int dt;
                     65:   int rv; 
1.1.1.2 ! misho      66:   int graceperiod = 0;
        !            67: 
        !            68:   memset(&startgrace, 0, sizeof(startgrace));
1.1       misho      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();
1.1.1.2 ! misho      90:       if (dnsfd6 >= 0) {
        !            91:         FD_SET(dnsfd6, &readfd);
        !            92:         if(dnsfd6 >= maxfd) maxfd = dnsfd6 + 1;
        !            93:       } else {
        !            94:         dnsfd6 = 0;
        !            95:       }
1.1       misho      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) {
1.1.1.2 ! misho     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:         */
1.1       misho     120:        selecttime.tv_sec = 0;
1.1.1.2 ! misho     121:        selecttime.tv_usec = paused?100000:0; 
1.1       misho     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;
1.1.1.2 ! misho     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)
1.1       misho     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
1.1.1.2 ! misho     200:     if(dns && dnsfd6 && FD_ISSET(dnsfd6, &readfd)) {
1.1       misho     201:       dns_ack6();
                    202:       anyset = 1;
                    203:     }
                    204: #endif
1.1.1.2 ! misho     205:     if(dns && dnsfd && FD_ISSET(dnsfd, &readfd)) {
1.1       misho     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;
1.1.1.2 ! misho     241: #ifdef IPINFO
1.1       misho     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>