Annotation of embedaddon/mtr/ui/select.c, revision 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:
! 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>