/* $Id: viewer.c,v 0.7 2003/10/16 10:38:32 kjc Exp $ */ /* * Copyright (c) 1996-2000 * Sony Computer Science Laboratories, Inc. All rights reserved. * * Redistribution and use in source and binary forms of parts of or the * whole original or derived work are permitted provided that the above * copyright notice is retained and the original work is properly * attributed to the author. The name of the author may not be used to * endorse or promote products derived from this software without * specific prior written permission. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ /* viewer.c -- a viewer module for remote-monitoring. this module is shared by tttview and ttttextview but TTT_TEXT flag is set for ttttextview. */ #include #include #include #include #include #include #include #include #include #include #include #include "ttt.h" #include "ttt_node.h" #include "ttt_remote.h" #include "ttt_tk.h" #define BUFFER_SIZE 4096 /* big enough */ static char buffer[BUFFER_SIZE]; /* receive buffer */ static struct sockaddr_in probe_addr; static char *probe_name = NULL; static int packets_received; static struct timeval remote_time; static int shared_port = 1; /* share the multicast port */ static int multicast = 0; /* use multicast */ void view_sockread(ClientData clientdata, int mask); static int check_seqno(int seq_no); static int read_record(struct ttt_record *trp); double get_remotetime(void); extern char *pcap_lookupdev(char *errbuf); extern int pcap_lookupnet(char *device, u_long *netp, u_long *maskp, char *errbuf); static void usage() { printf("usage: tttview [options]\n"); printf(" options:\n"); printf(" [-multicast]\n"); printf(" [-addr recv_addr]\n"); printf(" [-mcastifaddr mcast_if_addr]\n"); printf(" [-port recv_port]\n"); printf(" [-probe probe_addr]\n"); printf(" [-yscale 'K'|'M'|n]\n"); exit(1); } void view_parseargs(int argc, char **argv) { int i; for (i=1; i last_seqno+1) { /* packet loss */ lost_count = seq_no - last_seqno -1; if (last_seqno == 0) { /* this is the first packet */ lost_packets = 0; } else { lost_packets += lost_count; #ifdef REMOTE_DEBUG printf("[warning] lost %d packets\n", lost_count); #endif } last_seqno = seq_no; return (lost_count); } else { /* out of order report */ if (seq_no < 10 || (last_seqno - seq_no) > 100) { /* seq_no gets too small. the probe must have restarted. */ #ifdef TTT_TEXT printf("[warning] probe seems to have restarted.\n"); #else sprintf(buf, "probe[%s] seems to have restarted.", inet_ntoa(probe_addr.sin_addr)); ttt_showmessage(buf); #endif last_seqno = seq_no; lost_packets = out_of_order = 0; return 9999; } out_of_order++; #ifdef REMOTE_DEBUG printf("[warning] got out-of-order packet\n"); #endif return (-1); } } void view_sockread(ClientData clientdata, int mask) { int sockfd, nbytes, fromlen, rsize, seq_no, nrecords, i; struct sockaddr_in from_addr; struct ttt_hdr *hdr; char *cp; sockfd = (int)clientdata; fromlen = sizeof(from_addr); if ((nbytes = recvfrom(sockfd, buffer, BUFFER_SIZE, 0, (struct sockaddr *)&from_addr, &fromlen)) == -1) { perror("recvfrom"); return; } if (probe_addr.sin_addr.s_addr == 0) { probe_addr = from_addr; printf("reading from probe [%s] ....\n", inet_ntoa(from_addr.sin_addr)); } /* is this the probe we are reading from? */ if (from_addr.sin_addr.s_addr != probe_addr.sin_addr.s_addr) { static int warned = 0; if (!warned) { printf("[warning] there are multiple probes.\n"); printf("\tignoring probe: %s\n", inet_ntoa(from_addr.sin_addr)); warned = 1; } return; } if (nbytes < sizeof(struct ttt_hdr)) { printf("sockread: packet too short size=%d\n", nbytes); return; } hdr = (struct ttt_hdr *)buffer; if (ntohs(hdr->th_magic) != TTT_MAGIC) { printf("[warning] bad magic!\n"); return; } pcap_stats_recv = ntohl(hdr->th_recvpkts); pcap_stats_drop = ntohl(hdr->th_droppkts); seq_no = ntohl(hdr->th_seqno); if (check_seqno(seq_no) < 0) return; nrecords = ntohl(hdr->th_nrecords); remote_time.tv_sec = ntohl(hdr->th_tvsec); remote_time.tv_usec = ntohl(hdr->th_tvusec); cp = buffer + sizeof(struct ttt_hdr); for (i=0; itr_type != TTTTYPE_IPV6HOST) { type = ntohl(trp->tr_type); size = ntohl(trp->tr_size); id[0] = ntohl(trp->tr_id[0]); #ifdef IPV6 id[1] = 0; id[2] = 0; id[3] = 0; #endif rval = sizeof(struct ttt_record); } else { tr6p = (struct ttt_record6 *)trp; type = ntohl(tr6p->tr_type); size = ntohl(tr6p->tr_size); id[0] = ntohl(tr6p->tr_id[0]); #ifdef IPV6 id[1] = ntohl(tr6p->tr_id[1]); id[2] = ntohl(tr6p->tr_id[2]); id[3] = ntohl(tr6p->tr_id[3]); #endif rval = sizeof(struct ttt_record6); } node_record(type, id, size); return rval; } double get_timeindouble(void) { double sec; static struct timeval start; static int first = 1; if (first) { start = remote_time; first = 0; } sec = (double)(remote_time.tv_sec - start.tv_sec) + (double)(remote_time.tv_usec - start.tv_usec) / 1000000.0; return sec; }