Annotation of embedaddon/mtr/ui/select.c, revision 1.1.1.3

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
1.1.1.3 ! misho       6:     it under the terms of the GNU General Public License version 2 as
1.1       misho       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: 
1.1.1.2   misho      14:     You should have received a copy of the GNU General Public License along
                     15:     with this program; if not, write to the Free Software Foundation, Inc.,
                     16:     51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
1.1       misho      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: #ifdef HAVE_ERROR_H
                     32: #include <error.h>
                     33: #else
                     34: #include "portability/error.h"
                     35: #endif
                     36: 
                     37: #include "mtr.h"
                     38: #include "dns.h"
                     39: #include "net.h"
                     40: #include "asn.h"
                     41: #include "display.h"
                     42: #include "select.h"
                     43: 
                     44: void select_loop(
                     45:     struct mtr_ctl *ctl)
                     46: {
                     47:     fd_set readfd;
                     48:     fd_set writefd;
                     49:     int anyset = 0;
                     50:     int maxfd = 0;
                     51:     int dnsfd, netfd;
                     52: #ifdef ENABLE_IPV6
                     53:     int dnsfd6;
                     54: #endif
                     55:     int NumPing = 0;
                     56:     int paused = 0;
                     57:     struct timeval lasttime, thistime, selecttime;
                     58:     struct timeval startgrace;
                     59:     int dt;
                     60:     int rv;
                     61:     int graceperiod = 0;
                     62:     struct timeval intervaltime;
                     63:     static double dnsinterval = 0;
                     64: 
                     65:     memset(&startgrace, 0, sizeof(startgrace));
                     66: 
                     67:     gettimeofday(&lasttime, NULL);
                     68: 
                     69:     while (1) {
                     70:         dt = calc_deltatime(ctl->WaitTime);
                     71:         intervaltime.tv_sec = dt / 1000000;
                     72:         intervaltime.tv_usec = dt % 1000000;
                     73: 
                     74:         FD_ZERO(&readfd);
                     75:         FD_ZERO(&writefd);
                     76: 
                     77:         maxfd = 0;
                     78: 
                     79:         if (ctl->Interactive) {
                     80:             FD_SET(0, &readfd);
                     81:             maxfd = 1;
                     82:         }
                     83: #ifdef ENABLE_IPV6
                     84:         if (ctl->dns) {
                     85:             dnsfd6 = dns_waitfd6();
                     86:             if (dnsfd6 >= 0) {
                     87:                 FD_SET(dnsfd6, &readfd);
                     88:                 if (dnsfd6 >= maxfd)
                     89:                     maxfd = dnsfd6 + 1;
                     90:             } else {
                     91:                 dnsfd6 = 0;
                     92:             }
                     93:         } else
                     94:             dnsfd6 = 0;
                     95: #endif
                     96:         if (ctl->dns) {
                     97:             dnsfd = dns_waitfd();
                     98:             FD_SET(dnsfd, &readfd);
                     99:             if (dnsfd >= maxfd)
                    100:                 maxfd = dnsfd + 1;
                    101:         } else
                    102:             dnsfd = 0;
                    103: 
                    104:         netfd = net_waitfd();
                    105:         FD_SET(netfd, &readfd);
                    106:         if (netfd >= maxfd)
                    107:             maxfd = netfd + 1;
                    108: 
                    109:         do {
                    110:             if (anyset || paused) {
                    111:                 /* Set timeout to 0.1s.
                    112:                  * While this is almost instantaneous for human operators,
                    113:                  * it's slow enough for computers to go do something else;
                    114:                  * this prevents mtr from hogging 100% CPU time on one core.
                    115:                  */
                    116:                 selecttime.tv_sec = 0;
                    117:                 selecttime.tv_usec = paused ? 100000 : 0;
                    118: 
                    119:                 rv = select(maxfd, (void *) &readfd, &writefd, NULL,
                    120:                             &selecttime);
                    121: 
                    122:             } else {
                    123:                 if (ctl->Interactive)
                    124:                     display_redraw(ctl);
                    125: 
                    126:                 gettimeofday(&thistime, NULL);
                    127: 
                    128:                 if (thistime.tv_sec > lasttime.tv_sec + intervaltime.tv_sec
                    129:                     || (thistime.tv_sec ==
                    130:                         lasttime.tv_sec + intervaltime.tv_sec
                    131:                         && thistime.tv_usec >=
                    132:                         lasttime.tv_usec + intervaltime.tv_usec)) {
                    133:                     lasttime = thistime;
                    134: 
                    135:                     if (!graceperiod) {
                    136:                         if (NumPing >= ctl->MaxPing
                    137:                             && (!ctl->Interactive || ctl->ForceMaxPing)) {
                    138:                             graceperiod = 1;
                    139:                             startgrace = thistime;
                    140:                         }
                    141: 
                    142:                         /* do not send out batch when we've already initiated grace period */
                    143:                         if (!graceperiod && net_send_batch(ctl))
                    144:                             NumPing++;
                    145:                     }
                    146:                 }
                    147: 
                    148:                 if (graceperiod) {
                    149:                     dt = (thistime.tv_usec - startgrace.tv_usec) +
                    150:                         1000000 * (thistime.tv_sec - startgrace.tv_sec);
                    151:                     if ((ctl->GraceTime * 1000 * 1000) < dt)
                    152:                         return;
                    153:                 }
                    154: 
                    155:                 selecttime.tv_usec = (thistime.tv_usec - lasttime.tv_usec);
                    156:                 selecttime.tv_sec = (thistime.tv_sec - lasttime.tv_sec);
                    157:                 if (selecttime.tv_usec < 0) {
                    158:                     --selecttime.tv_sec;
                    159:                     selecttime.tv_usec += 1000000;
                    160:                 }
                    161:                 selecttime.tv_usec =
                    162:                     intervaltime.tv_usec - selecttime.tv_usec;
                    163:                 selecttime.tv_sec =
                    164:                     intervaltime.tv_sec - selecttime.tv_sec;
                    165:                 if (selecttime.tv_usec < 0) {
                    166:                     --selecttime.tv_sec;
                    167:                     selecttime.tv_usec += 1000000;
                    168:                 }
                    169: 
                    170:                 if (ctl->dns) {
                    171:                     if ((selecttime.tv_sec > (time_t) dnsinterval) ||
                    172:                         ((selecttime.tv_sec == (time_t) dnsinterval) &&
                    173:                          (selecttime.tv_usec >
                    174:                           ((time_t) (dnsinterval * 1000000) % 1000000)))) {
                    175:                         selecttime.tv_sec = (time_t) dnsinterval;
                    176:                         selecttime.tv_usec =
                    177:                             (time_t) (dnsinterval * 1000000) % 1000000;
                    178:                     }
                    179:                 }
                    180: 
                    181:                 rv = select(maxfd, (void *) &readfd, NULL, NULL,
                    182:                             &selecttime);
                    183:             }
                    184:         } while ((rv < 0) && (errno == EINTR));
                    185: 
                    186:         if (rv < 0) {
                    187:             error(EXIT_FAILURE, errno, "Select failed");
                    188:         }
                    189:         anyset = 0;
                    190: 
                    191:         /*  Have we got new packets back?  */
                    192:         if (FD_ISSET(netfd, &readfd)) {
                    193:             net_process_return(ctl);
                    194:             anyset = 1;
                    195:         }
                    196: 
                    197:         if (ctl->dns) {
                    198:             /* Handle any pending resolver events */
                    199:             dnsinterval = ctl->WaitTime;
                    200:         }
                    201: 
                    202:         /*  Have we finished a nameservice lookup?  */
                    203: #ifdef ENABLE_IPV6
                    204:         if (ctl->dns && dnsfd6 && FD_ISSET(dnsfd6, &readfd)) {
                    205:             dns_ack6();
                    206:             anyset = 1;
                    207:         }
                    208: #endif
                    209:         if (ctl->dns && dnsfd && FD_ISSET(dnsfd, &readfd)) {
                    210:             dns_ack(ctl);
                    211:             anyset = 1;
                    212:         }
                    213: 
                    214:         /*  Has a key been pressed?  */
                    215:         if (FD_ISSET(0, &readfd)) {
                    216:             switch (display_keyaction(ctl)) {
                    217:             case ActionQuit:
                    218:                 return;
                    219:                 break;
                    220:             case ActionReset:
                    221:                 net_reset(ctl);
                    222:                 break;
                    223:             case ActionDisplay:
                    224:                 ctl->display_mode =
                    225:                     (ctl->display_mode + 1) % DisplayModeMAX;
                    226:                 break;
                    227:             case ActionClear:
                    228:                 display_clear(ctl);
                    229:                 break;
                    230:             case ActionPause:
                    231:                 paused = 1;
                    232:                 break;
                    233:             case ActionResume:
                    234:                 paused = 0;
                    235:                 break;
                    236:             case ActionMPLS:
                    237:                 ctl->enablempls = !ctl->enablempls;
                    238:                 display_clear(ctl);
                    239:                 break;
                    240:             case ActionDNS:
                    241:                 if (ctl->dns) {
                    242:                     ctl->use_dns = !ctl->use_dns;
                    243:                     display_clear(ctl);
                    244:                 }
                    245:                 break;
                    246: #ifdef HAVE_IPINFO
                    247:             case ActionII:
                    248:                 ctl->ipinfo_no++;
                    249:                 if (ctl->ipinfo_no > ctl->ipinfo_max)
                    250:                     ctl->ipinfo_no = 0;
                    251:                 break;
                    252:             case ActionAS:
                    253:                 ctl->ipinfo_no = ctl->ipinfo_no ? 0 : ctl->ipinfo_max;
                    254:                 break;
                    255: #endif
                    256: 
                    257:             case ActionScrollDown:
                    258:                 ctl->display_offset += 5;
                    259:                 break;
                    260:             case ActionScrollUp:
                    261:                 ctl->display_offset -= 5;
                    262:                 if (ctl->display_offset < 0) {
                    263:                     ctl->display_offset = 0;
                    264:                 }
                    265:                 break;
                    266:             }
                    267:             anyset = 1;
                    268:         }
                    269:     }
                    270:     return;
                    271: }

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