1063 lines · 19.5 KB · C
RawDownload
#include <u.h>#include <libc.h>#include <ctype.h>#include <auth.h>#include <fcall.h>#include <draw.h>#include <event.h>#include <ip.h>#include "icmp.h" #define	MAXNUM	8	/* maximum number of numbers on data line */ typedef struct Graph	Graph;typedef struct Machine	Machine;typedef struct Req	Req; enum {	Gmsglen	= 16,}; struct Graph{	int		colindex;	Rectangle	r;	long		*data;	int		ndata;	char		*label;	void		(*newvalue)(Machine*, long*, long*, long*);	void		(*update)(Graph*, long, long, long);	Machine		*mach;	int		overflow;	Image		*overtmp;	int		overtmplen;	char		msg[Gmsglen];	int		cursor;	int		vmax;}; enum{	MSGLEN		= 64, 	Rttmax		= 50,}; struct Req{	int	seq;	/* sequence number */	vlong	time;	/* time sent *///	int	rtt;	Req	*next;}; struct Machine{	Lock;	char	*name;	int	pingfd;	int	nproc; 	int	rttmsgs;	ulong	rttsum;	ulong	lastrtt; 	int	lostmsgs;	int	rcvdmsgs;	ulong	lostavg;	int	unreachable; 	ushort	seq;	Req	*first;	Req	*last;	Req	*rcvd; 	char	buf[1024];	char	*bufp;	char	*ebufp;}; enum{	Ncolor		= 6,	Ysqueeze	= 2,	/* vertical squeezing of label text */	Labspace	= 2,	/* room around label */	Dot		= 2,	/* height of dot */	Opwid		= 5,	/* strlen("add  ") or strlen("drop ") */	NPROC		= 128,	NMACH		= 32,}; enum Menu2{	Mrtt,	Mlost,	Nmenu2,}; char	*menu2str[Nmenu2+1] = {	"add  sec rtt",	"add  % lost ",	nil,};  void	rttval(Machine*, long*, long*, long*);void	lostval(Machine*, long*, long*, long*); Menu	menu2 = {menu2str, nil};int		present[Nmenu2];void		(*newvaluefn[Nmenu2])(Machine*, long*, long*, long*) = {	rttval,	lostval,}; Image		*cols[Ncolor][3];Graph		*graph;Machine		mach[NMACH];Font		*mediumfont;int		pids[NPROC];int		npid;int 		parity;	/* toggled to avoid patterns in textured background */int		nmach;int		ngraph;	/* totaly number is ngraph*nmach */long		starttime;int		pinginterval; void	dropgraph(int);void	addgraph(int);void	startproc(void (*)(void*), void*);void	resize(void);long	rttscale(long);int	which2index(int);int	index2which(int); voidkillall(char *s){	int i, pid; 	pid = getpid();	for(i=0; i<NPROC; i++)		if(pids[i] && pids[i]!=pid)			postnote(PNPROC, pids[i], "kill");	exits(s);} void*emalloc(ulong sz){	void *v;	v = malloc(sz);	if(v == nil) {		fprint(2, "%s: out of memory allocating %ld: %r\n", argv0, sz);		killall("mem");	}	memset(v, 0, sz);	return v;} void*erealloc(void *v, ulong sz){	v = realloc(v, sz);	if(v == nil) {		fprint(2, "%s: out of memory reallocating %ld: %r\n", argv0, sz);		killall("mem");	}	return v;} char*estrdup(char *s){	char *t;	if((t = strdup(s)) == nil) {		fprint(2, "%s: out of memory in strdup(%.10s): %r\n", argv0, s);		killall("mem");	}	return t;} voidmkcol(int i, int c0, int c1, int c2){	cols[i][0] = allocimagemix(display, c0, DWhite);	cols[i][1] = allocimage(display, Rect(0,0,1,1), CMAP8, 1, c1);	cols[i][2] = allocimage(display, Rect(0,0,1,1), CMAP8, 1, c2);} voidcolinit(void){	mediumfont = openfont(display, "/lib/font/bit/pelm/latin1.8.font");	if(mediumfont == nil)		mediumfont = font; 	/* Peach */	mkcol(0, 0xFFAAAAFF, 0xFFAAAAFF, 0xBB5D5DFF);	/* Aqua */	mkcol(1, DPalebluegreen, DPalegreygreen, DPurpleblue);	/* Yellow */	mkcol(2, DPaleyellow, DDarkyellow, DYellowgreen);	/* Green */	mkcol(3, DPalegreen, DMedgreen, DDarkgreen);	/* Blue */	mkcol(4, 0x00AAFFFF, 0x00AAFFFF, 0x0088CCFF);	/* Grey */	cols[5][0] = allocimage(display, Rect(0,0,1,1), CMAP8, 1, 0xEEEEEEFF);	cols[5][1] = allocimage(display, Rect(0,0,1,1), CMAP8, 1, 0xCCCCCCFF);	cols[5][2] = allocimage(display, Rect(0,0,1,1), CMAP8, 1, 0x888888FF);} intloadbuf(Machine *m, int *fd){	int n;  	if(*fd < 0)		return 0;	seek(*fd, 0, 0);	n = read(*fd, m->buf, sizeof m->buf);	if(n <= 0){		close(*fd);		*fd = -1;		return 0;	}	m->bufp = m->buf;	m->ebufp = m->buf+n;	return 1;} voidlabel(Point p, int dy, char *text){	char *s;	Rune r[2];	int w, maxw, maxy; 	p.x += Labspace;	maxy = p.y+dy;	maxw = 0;	r[1] = '\0';	for(s=text; *s; ){		if(p.y+mediumfont->height-Ysqueeze > maxy)			break;		w = chartorune(r, s);		s += w;		w = runestringwidth(mediumfont, r);		if(w > maxw)			maxw = w;		runestring(screen, p, display->black, ZP, mediumfont, r);		p.y += mediumfont->height-Ysqueeze;	}} voidhashmark(Point p, int dy, long v, long vmax, char *label){	int y;	int x; 	x = p.x + Labspace;	y = p.y + (dy*(vmax-v))/vmax;	draw(screen, Rect(p.x, y-1, p.x+Labspace, y+1), display->black, nil, ZP);	if(dy > 5*mediumfont->height)		string(screen, Pt(x, y-mediumfont->height/2),			display->black, ZP, mediumfont, label);} voidhashmarks(Point p, int dy, int which){	switch(index2which(which)){	case Mrtt:		hashmark(p, dy, rttscale(1000000), Rttmax, "1.");		hashmark(p, dy, rttscale(100000), Rttmax, "0.1");		hashmark(p, dy, rttscale(10000), Rttmax, "0.01");		hashmark(p, dy, rttscale(1000), Rttmax, "0.001");		break;	case Mlost:		hashmark(p, dy, 75, 100, " 75%");		hashmark(p, dy, 50, 100, " 50%");		hashmark(p, dy, 25, 100, " 25%");		break;	}} Pointparitypt(int x){	return Pt(x+parity, 0);} Pointdatapoint(Graph *g, int x, long v, long vmax){	Point p; 	p.x = x;	p.y = g->r.max.y - Dy(g->r)*v/vmax - Dot;	if(p.y < g->r.min.y)		p.y = g->r.min.y;	if(p.y > g->r.max.y-Dot)		p.y = g->r.max.y-Dot;	return p;} voiddrawdatum(Graph *g, int x, long prev, long v, long vmax){	int c;	Point p, q; 	c = g->colindex;	p = datapoint(g, x, v, vmax);	q = datapoint(g, x, prev, vmax);	if(p.y < q.y){		draw(screen, Rect(p.x, g->r.min.y, p.x+1, p.y), cols[c][0], nil, paritypt(p.x));		draw(screen, Rect(p.x, p.y, p.x+1, q.y+Dot), cols[c][2], nil, ZP);		draw(screen, Rect(p.x, q.y+Dot, p.x+1, g->r.max.y), cols[c][1], nil, ZP);	}else{		draw(screen, Rect(p.x, g->r.min.y, p.x+1, q.y), cols[c][0], nil, paritypt(p.x));		draw(screen, Rect(p.x, q.y, p.x+1, p.y+Dot), cols[c][2], nil, ZP);		draw(screen, Rect(p.x, p.y+Dot, p.x+1, g->r.max.y), cols[c][1], nil, ZP);	}	g->vmax = vmax;} voiddrawmark(Graph *g, int x){	int c; 	c = (g->colindex+1)&Ncolor;	draw(screen, Rect(x, g->r.min.y, x+1, g->r.max.y), cols[c][2], nil, ZP);} voidredraw(Graph *g, int vmax){	int i, c; 	c = g->colindex;	draw(screen, g->r, cols[c][0], nil, paritypt(g->r.min.x));	for(i=1; i<Dx(g->r); i++)		drawdatum(g, g->r.max.x-i, g->data[i-1], g->data[i], vmax);	drawdatum(g, g->r.min.x, g->data[i], g->data[i], vmax);} voidclearmsg(Graph *g){	if(g->overtmp != nil)		draw(screen, g->overtmp->r, g->overtmp, nil, g->overtmp->r.min);	g->overflow = 0;} voiddrawmsg(Graph *g, char *msg){	if(g->overtmp == nil)		return; 	/* save previous contents of screen */	draw(g->overtmp, g->overtmp->r, screen, nil, g->overtmp->r.min); 	/* draw message */	if(strlen(msg) > g->overtmplen)		msg[g->overtmplen] = 0;	string(screen, g->overtmp->r.min, display->black, ZP, mediumfont, msg);} voidclearcursor(Graph *g){	int x;	long prev; 	if(g->overtmp == nil)		return; 	if(g->cursor > 0 && g->cursor < g->ndata){		x = g->r.max.x - g->cursor;		prev = 0;		if(g->cursor > 0)			prev = g->data[g->cursor-1];		drawdatum(g, x, prev, g->data[g->cursor], g->vmax);		g->cursor = -1;	}} voiddrawcursor(Graph *g, int x){	if(g->overtmp == nil)		return; 	draw(screen, Rect(x, g->r.min.y, x+1, g->r.max.y), cols[g->colindex][2], nil, ZP);} voidupdate1(Graph *g, long v, long vmax, long mark){	char buf[Gmsglen]; 	/* put back screen value sans message */	if(g->overflow || *g->msg){		clearmsg(g);		g->overflow = 0;	} 	draw(screen, g->r, screen, nil, Pt(g->r.min.x+1, g->r.min.y));	drawdatum(g, g->r.max.x-1, g->data[0], v, vmax);	if(mark)		drawmark(g, g->r.max.x-1);	memmove(g->data+1, g->data, (g->ndata-1)*sizeof(g->data[0]));	g->data[0] = v;	if(v>vmax){		g->overflow = 1;		sprint(buf, "%ld", v);		drawmsg(g, buf);	} else if(*g->msg)		drawmsg(g, g->msg); 	if(g->cursor >= 0){		g->cursor++;		if(g->cursor >= g->ndata){			g->cursor = -1;			if(*g->msg){				clearmsg(g);				*g->msg = 0;			}		}	} } voidpinglost(Machine *m, Req*){	m->lostmsgs++;} voidpingreply(Machine *m, Req *r){	ulong x; 	x = r->time/1000LL;	m->rttsum += x;	m->rcvdmsgs++;	m->rttmsgs++;}  voidpingclean(Machine *m, ushort seq, vlong now, int){	Req **l, *r;	vlong x, y; 	y = 10LL*1000000000LL;	for(l = &m->first; *l; ){		r = *l;		x = now - r->time;		if(x > y || r->seq == seq){			*l = r->next;			r->time = x;			if(r->seq != seq)				pinglost(m, r);			else				pingreply(m, r);			free(r);		} else			l = &(r->next);	}} /* IPv4 only */voidpingsend(Machine *m){	int i;	char buf[128], err[ERRMAX];	Icmphdr *ip;	Req *r; 	ip = (Icmphdr *)(buf + IPV4HDR_LEN);	memset(buf, 0, sizeof buf);	r = malloc(sizeof *r);	if(r == nil)		return; 	for(i = 32; i < MSGLEN; i++)		buf[i] = i;	ip->type = EchoRequest;	ip->code = 0;	ip->seq[0] = m->seq;	ip->seq[1] = m->seq>>8;

Lines 1–500 of 1063.