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

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: 
                     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>