📄 gping.c
字号:
#include <u.h>#include <libc.h>#include <ctype.h>#include <auth.h>#include <fcall.h>#include <draw.h>#include <event.h>#include <ip.h>#define MAXNUM 8 /* maximum number of numbers on data line */typedef struct Graph Graph;typedef struct Machine Machine;typedef struct Req Req;typedef struct Icmp Icmp;enum { Gmsglen = 16,};struct Graph{ int colindex; Rectangle r; int *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;};struct Icmp{ uchar vihl; /* Version and header length */ uchar tos; /* Type of service */ uchar length[2]; /* packet length */ uchar id[2]; /* Identification */ uchar frag[2]; /* Fragment information */ uchar ttl; /* Time to live */ uchar proto; /* Protocol */ uchar ipcksum[2]; /* Header checksum */ uchar src[4]; /* Ip source */ uchar dst[4]; /* Ip destination */ uchar type; uchar code; uchar cksum[2]; uchar icmpid[2]; uchar seq[2]; uchar data[1];};enum{ /* Packet Types */ EchoReply = 0, Unreachable = 3, SrcQuench = 4, EchoRequest = 8, TimeExceed = 11, Timestamp = 13, TimestampReply = 14, InfoRequest = 15, InfoReply = 16, ICMP_IPSIZE = 20, ICMP_HDRSIZE = 8, 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);ulong rttscale(ulong);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, int v, int 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); }}voidpingsend(Machine *m){ char buf[128]; Icmp *ip; int i; Req *r; char err[ERRMAX]; ip = (Icmp*)buf; r = malloc(sizeof *r); if(r == nil) return; for(i = 32; i < 64; i++) buf[i] = i; ip->type = EchoRequest; ip->code = 0; ip->seq[0] = m->seq; ip->seq[1] = m->seq>>8; r->seq = m->seq; r->next = nil; lock(m); pingclean(m, -1, nsec(), 0); if(m->first == nil) m->first = r; else m->last->next = r; m->last = r; r->time = nsec(); unlock(m); if(write(m->pingfd, ip, MSGLEN) < MSGLEN){ errstr(err, sizeof err); if(strstr(err, "unreach")||strstr(err, "exceed"))
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -