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>