Diff for /embedaddon/iftop/ui.c between versions 1.1.1.1 and 1.1.1.2

version 1.1.1.1, 2012/02/21 16:57:34 version 1.1.1.2, 2016/10/18 14:04:50
Line 3 Line 3
  *   *
  */   */
   
   #include "config.h"
   
 #include <sys/types.h>  #include <sys/types.h>
   
 #include <ctype.h>  #include <ctype.h>
#include <curses.h>#include <ncurses.h>
 #include <errno.h>  #include <errno.h>
 #include <string.h>  #include <string.h>
 #include <math.h>  #include <math.h>
Line 26 Line 28
 #include "options.h"  #include "options.h"
 #include "screenfilter.h"  #include "screenfilter.h"
   
#define HOSTNAME_LENGTH 256#include "ui_common.h"
   
 #define HISTORY_DIVISIONS   3  
   
 #define HELP_TIME 2  #define HELP_TIME 2
   
 #define HELP_MESSAGE \  #define HELP_MESSAGE \
Line 38 Line 38
 " s - toggle show source host            h - toggle this help display\n"\  " s - toggle show source host            h - toggle this help display\n"\
 " d - toggle show destination host       b - toggle bar graph display\n"\  " d - toggle show destination host       b - toggle bar graph display\n"\
 " t - cycle line display mode            B - cycle bar graph average\n"\  " t - cycle line display mode            B - cycle bar graph average\n"\
"                                        T - toggle cummulative line totals\n"\"                                        T - toggle cumulative line totals\n"\
 "Port display:                           j/k - scroll display\n"\  "Port display:                           j/k - scroll display\n"\
 " N - toggle service resolution          f - edit filter code\n"\  " N - toggle service resolution          f - edit filter code\n"\
 " S - toggle show source port            l - set screen filter\n"\  " S - toggle show source port            l - set screen filter\n"\
Line 51 Line 51
 " > - sort by dest name\n"\  " > - sort by dest name\n"\
 " o - freeze current order\n"\  " o - freeze current order\n"\
 "\n"\  "\n"\
"iftop, version " IFTOP_VERSION "iftop, version " PACKAGE_VERSION
   
   
 /* 2, 10 and 40 seconds */  
 int history_divs[HISTORY_DIVISIONS] = {1, 5, 20};  
   
 #define UNIT_DIVISIONS 4  
 char* unit_bits[UNIT_DIVISIONS] =  { "b", "Kb", "Mb", "Gb"};  
 char* unit_bytes[UNIT_DIVISIONS] =  { "B", "KB", "MB", "GB"};  
   
 typedef struct host_pair_line_tag {  
     addr_pair ap;  
     double long total_recv;  
     double long total_sent;  
     double long recv[HISTORY_DIVISIONS];  
     double long sent[HISTORY_DIVISIONS];  
 } host_pair_line;  
   
   
 extern hash_type* history;  extern hash_type* history;
 extern int history_pos;  extern int history_pos;
 extern int history_len;  extern int history_len;
Line 78  extern options_t options ; Line 62  extern options_t options ;
   
 void ui_finish();  void ui_finish();
   
 hash_type* screen_hash;  
 hash_type* service_hash;  
 sorted_list_type screen_list;  
 host_pair_line totals;  
 int peaksent, peakrecv, peaktotal;  
   
 #define HELP_MSG_SIZE 80  #define HELP_MSG_SIZE 80
 int showhelphint = 0;  int showhelphint = 0;
 int persistenthelp = 0;  int persistenthelp = 0;
Line 91  time_t helptimer = 0; Line 69  time_t helptimer = 0;
 char helpmsg[HELP_MSG_SIZE];  char helpmsg[HELP_MSG_SIZE];
 int dontshowdisplay = 0;  int dontshowdisplay = 0;
   
 /*  
  * Compare two screen lines based on bandwidth.  Start comparing from the   
  * specified column  
  */  
 int screen_line_bandwidth_compare(host_pair_line* aa, host_pair_line* bb, int start_div) {  
     int i;  
     for(i = start_div; i < HISTORY_DIVISIONS; i++) {  
         if(aa->recv[i] + aa->sent[i] != bb->recv[i] + bb->sent[i]) {  
             return(aa->recv[i] + aa->sent[i] < bb->recv[i] + bb->sent[i]);  
         }  
     }  
     return 1;  
 }  
   
 /*  
  * Compare two screen lines based on hostname / IP.  Fall over to compare by  
  * bandwidth.  
  */  
 int screen_line_host_compare(struct in_addr* a, struct in_addr* b, host_pair_line* aa, host_pair_line* bb) {  
     char hosta[HOSTNAME_LENGTH], hostb[HOSTNAME_LENGTH];  
     int r;  
   
     /* This isn't overly efficient because we resolve again before   
        display. */  
     if (options.dnsresolution) {  
         resolve(a, hosta, HOSTNAME_LENGTH);  
         resolve(b, hostb, HOSTNAME_LENGTH);  
     }  
     else {  
         strcpy(hosta, inet_ntoa(*a));  
         strcpy(hostb, inet_ntoa(*b));  
     }  
   
     r = strcmp(hosta, hostb);  
   
     if(r == 0) {  
         return screen_line_bandwidth_compare(aa, bb, 2);  
     }  
     else {  
         return (r > 0);  
     }  
   
   
 }  
   
 int screen_line_compare(void* a, void* b) {  
     host_pair_line* aa = (host_pair_line*)a;  
     host_pair_line* bb = (host_pair_line*)b;  
     if(options.sort == OPTION_SORT_DIV1) {  
       return screen_line_bandwidth_compare(aa, bb, 0);  
     }  
     else if(options.sort == OPTION_SORT_DIV2) {  
       return screen_line_bandwidth_compare(aa, bb, 1);  
     }  
     else if(options.sort == OPTION_SORT_DIV3) {  
       return screen_line_bandwidth_compare(aa, bb, 2);  
     }  
     else if(options.sort == OPTION_SORT_SRC) {  
       return screen_line_host_compare(&(aa->ap.src), &(bb->ap.src), aa, bb);  
     }  
     else if(options.sort == OPTION_SORT_DEST) {  
       return screen_line_host_compare(&(aa->ap.dst), &(bb->ap.dst), aa, bb);  
     }  
   
     return 1;  
 }  
   
 void readable_size(float n, char* buf, int bsize, int ksize, int bytes) {  
   
     int i = 0;  
     float size = 1;  
   
     /* Convert to bits? */  
     if(bytes == 0) {   
       n *= 8;  
     }  
   
     while(1) {  
       if(n < size * 1000 || i >= UNIT_DIVISIONS - 1) {  
         snprintf(buf, bsize, " %4.0f%s", n / size, bytes ? unit_bytes[i] : unit_bits[i]);   
         break;  
       }  
       i++;  
       size *= ksize;  
       if(n < size * 10) {  
         snprintf(buf, bsize, " %4.2f%s", n / size, bytes ? unit_bytes[i] : unit_bits[i]);   
         break;  
       }  
       else if(n < size * 100) {  
         snprintf(buf, bsize, " %4.1f%s", n / size, bytes ? unit_bytes[i] : unit_bits[i]);   
         break;  
       }  
   }  
 }  
   
   
 /* Barchart scales. */  /* Barchart scales. */
 static struct {  static struct {
     int max, interval;      int max, interval;
Line 201  static struct { Line 83  static struct {
     };      };
 static int rateidx = 0, wantbiggerrate;  static int rateidx = 0, wantbiggerrate;
   
   static int rateidx_init = 0;
   
 static int get_bar_interval(float bandwidth) {  static int get_bar_interval(float bandwidth) {
     int i = 10;      int i = 10;
     if(bandwidth > 100000000) {      if(bandwidth > 100000000) {
Line 225  static int get_bar_length(const int rate) { Line 109  static int get_bar_length(const int rate) {
     float l;      float l;
     if (rate <= 0)      if (rate <= 0)
         return 0;          return 0;
    if (rate > scale[rateidx].max)    if (rate > scale[rateidx].max) {
        wantbiggerrate = 1;      wantbiggerrate = 1;
       if(! rateidx_init) {
         while(rate > scale[rateidx_init++].max) {
         }
         rateidx = rateidx_init;
       }
     }
     if(options.log_scale) {      if(options.log_scale) {
         l = log(rate) / log(get_max_bandwidth());          l = log(rate) / log(get_max_bandwidth());
     }      }
Line 263  static void draw_bar_scale(int* y) { Line 153  static void draw_bar_scale(int* y) {
             char s[40], *p;              char s[40], *p;
             int x;              int x;
             /* This 1024 vs 1000 stuff is just plain evil */              /* This 1024 vs 1000 stuff is just plain evil */
            readable_size(i, s, sizeof s, options.log_scale ? 1000 : 1024, 0);            readable_size(i, s, sizeof s, options.log_scale ? 1000 : 1024, options.bandwidth_in_bytes);
             p = s + strspn(s, " ");              p = s + strspn(s, " ");
             x = get_bar_length(i * 8);              x = get_bar_length(i * 8);
             mvaddch(*y + 1, x, ACS_BTEE);              mvaddch(*y + 1, x, ACS_BTEE);
Line 287  static void draw_bar_scale(int* y) { Line 177  static void draw_bar_scale(int* y) {
     }      }
 }  }
   
 int history_length(const int d) {  
     if (history_len < history_divs[d])  
         return history_len * RESOLUTION;  
     else  
         return history_divs[d] * RESOLUTION;  
 }  
   
 void draw_line_total(float sent, float recv, int y, int x, option_linedisplay_t linedisplay, int bytes) {  void draw_line_total(float sent, float recv, int y, int x, option_linedisplay_t linedisplay, int bytes) {
     char buf[10];      char buf[10];
    float n;    float n = 0;
     switch(linedisplay) {      switch(linedisplay) {
         case OPTION_LINEDISPLAY_TWO_LINE:          case OPTION_LINEDISPLAY_TWO_LINE:
           draw_line_total(sent, recv, y, x, OPTION_LINEDISPLAY_ONE_LINE_SENT, bytes);            draw_line_total(sent, recv, y, x, OPTION_LINEDISPLAY_ONE_LINE_SENT, bytes);
Line 372  void draw_totals(host_pair_line* totals) { Line 255  void draw_totals(host_pair_line* totals) {
   
 extern history_type history_totals;  extern history_type history_totals;
   
 void screen_list_init() {  
     screen_list.compare = &screen_line_compare;  
     sorted_list_initialise(&screen_list);  
 }  
   
 void screen_list_clear() {  
     sorted_list_node* nn = NULL;  
     peaksent = peakrecv = peaktotal = 0;  
     while((nn = sorted_list_next_item(&screen_list, nn)) != NULL) {  
         free(nn->data);  
     }  
     sorted_list_destroy(&screen_list);  
 }  
   
 void calculate_totals() {  
     int i;  
   
     /**  
      * Calculate peaks and totals  
      */  
     for(i = 0; i < HISTORY_LENGTH; i++) {  
         int j;  
         int ii = (HISTORY_LENGTH + history_pos - i) % HISTORY_LENGTH;  
   
         for(j = 0; j < HISTORY_DIVISIONS; j++) {  
             if(i < history_divs[j]) {  
                 totals.recv[j] += history_totals.recv[ii];  
                 totals.sent[j] += history_totals.sent[ii];  
             }  
         }  
   
         if(history_totals.recv[i] > peakrecv) {  
             peakrecv = history_totals.recv[i];  
         }  
         if(history_totals.sent[i] > peaksent) {  
             peaksent = history_totals.sent[i];  
         }  
         if(history_totals.recv[i] + history_totals.sent[i] > peaktotal) {  
             peaktotal = history_totals.recv[i] + history_totals.sent[i];          
         }  
     }  
     for(i = 0; i < HISTORY_DIVISIONS; i++) {  
       int t = history_length(i);  
       totals.recv[i] /= t;  
       totals.sent[i] /= t;  
     }  
 }  
   
 void make_screen_list() {  
     hash_node_type* n = NULL;  
     while(hash_next_item(screen_hash, &n) == HASH_STATUS_OK) {  
         host_pair_line* line = (host_pair_line*)n->rec;  
         int i;  
         for(i = 0; i < HISTORY_DIVISIONS; i++) {  
           line->recv[i] /= history_length(i);  
           line->sent[i] /= history_length(i);  
         }  
   
         /* Don't make a new, sorted screen list if order is frozen  
          */  
         if(!options.freezeorder) {  
             sorted_list_insert(&screen_list, line);  
         }   
            
     }  
 }  
   
 /*  
  * Zeros all data in the screen hash, but does not remove items.  
  */  
 void screen_hash_clear() {  
     hash_node_type* n = NULL;  
     while(hash_next_item(screen_hash, &n) == HASH_STATUS_OK) {  
         host_pair_line* hpl = (host_pair_line*)n->rec;  
         memset(hpl->recv, 0, sizeof(hpl->recv));  
         memset(hpl->sent, 0, sizeof(hpl->sent));  
     }  
 }  
   
 void analyse_data() {  
     hash_node_type* n = NULL;  
   
     if(options.paused == 1) {  
       return;  
     }  
   
     // Zero totals  
     memset(&totals, 0, sizeof totals);  
   
     if(options.freezeorder) {  
       screen_hash_clear();  
     }  
     else {  
       screen_list_clear();  
       hash_delete_all(screen_hash);  
     }  
   
     while(hash_next_item(history, &n) == HASH_STATUS_OK) {  
         history_type* d = (history_type*)n->rec;  
         host_pair_line* screen_line;  
         union {  
             host_pair_line **h_p_l_pp;  
             void **void_pp;  
         } u_screen_line = { &screen_line };  
         addr_pair ap;  
         int i;  
         int tsent, trecv;  
         tsent = trecv = 0;  
   
   
         ap = *(addr_pair*)n->key;  
   
         /* Aggregate hosts, if required */  
         if(options.aggregate_src) {  
             ap.src.s_addr = 0;  
         }  
         if(options.aggregate_dest) {  
             ap.dst.s_addr = 0;  
         }  
   
         /* Aggregate ports, if required */  
         if(options.showports == OPTION_PORTS_DEST || options.showports == OPTION_PORTS_OFF) {  
             ap.src_port = 0;  
         }  
         if(options.showports == OPTION_PORTS_SRC || options.showports == OPTION_PORTS_OFF) {  
             ap.dst_port = 0;  
         }  
         if(options.showports == OPTION_PORTS_OFF) {  
             ap.protocol = 0;  
         }  
   
           
         if(hash_find(screen_hash, &ap, u_screen_line.void_pp) == HASH_STATUS_KEY_NOT_FOUND) {  
             screen_line = xcalloc(1, sizeof *screen_line);  
             hash_insert(screen_hash, &ap, screen_line);  
             screen_line->ap = ap;  
         }  
           
         screen_line->total_sent += d->total_sent;  
         screen_line->total_recv += d->total_recv;  
   
         for(i = 0; i < HISTORY_LENGTH; i++) {  
             int j;  
             int ii = (HISTORY_LENGTH + history_pos - i) % HISTORY_LENGTH;  
   
             for(j = 0; j < HISTORY_DIVISIONS; j++) {  
                 if(i < history_divs[j]) {  
                     screen_line->recv[j] += d->recv[ii];  
                     screen_line->sent[j] += d->sent[ii];  
                 }  
             }  
         }  
   
     }  
   
     make_screen_list();  
   
       
     calculate_totals();  
   
 }  
   
 void sprint_host(char * line, struct in_addr* addr, unsigned int port, unsigned int protocol, int L) {  
     char hostname[HOSTNAME_LENGTH];  
     char service[HOSTNAME_LENGTH];  
     char* s_name;  
     union {  
         char **ch_pp;  
         void **void_pp;  
     } u_s_name = { &s_name };  
   
     ip_service skey;  
     int left;  
     if(addr->s_addr == 0) {  
         sprintf(hostname, " * ");  
     }  
     else {  
         if (options.dnsresolution)  
             resolve(addr, hostname, L);  
         else  
             strcpy(hostname, inet_ntoa(*addr));  
     }  
     left = strlen(hostname);  
   
     if(port != 0) {  
       skey.port = port;  
       skey.protocol = protocol;  
       if(options.portresolution && hash_find(service_hash, &skey, u_s_name.void_pp) == HASH_STATUS_OK) {  
         snprintf(service, HOSTNAME_LENGTH, ":%s", s_name);  
       }  
       else {  
         snprintf(service, HOSTNAME_LENGTH, ":%d", port);  
       }  
     }  
     else {  
       service[0] = '\0';  
     }  
   
   
     sprintf(line, "%-*s", L, hostname);  
     if(left > (L - strlen(service))) {  
         left = L - strlen(service);  
         if(left < 0) {  
            left = 0;  
         }  
     }  
     sprintf(line + left, "%-*s", L-left, service);  
 }  
   
   
   
 void ui_print() {  void ui_print() {
     sorted_list_node* nn = NULL;      sorted_list_node* nn = NULL;
     char host1[HOSTNAME_LENGTH], host2[HOSTNAME_LENGTH];      char host1[HOSTNAME_LENGTH], host2[HOSTNAME_LENGTH];
Line 636  void ui_print() { Line 309  void ui_print() {
                     L = HOSTNAME_LENGTH;                      L = HOSTNAME_LENGTH;
                 }                  }
   
                sprint_host(host1, &(screen_line->ap.src), screen_line->ap.src_port, screen_line->ap.protocol, L);                sprint_host(host1, screen_line->ap.af,
                sprint_host(host2, &(screen_line->ap.dst), screen_line->ap.dst_port, screen_line->ap.protocol, L);                            &(screen_line->ap.src6),
                             screen_line->ap.src_port,
                             screen_line->ap.protocol, L, options.aggregate_src);
                 sprint_host(host2, screen_line->ap.af,
                             &(screen_line->ap.dst6),
                             screen_line->ap.dst_port,
                             screen_line->ap.protocol, L, options.aggregate_dest);
 
                 if(!screen_filter_match(host1) && !screen_filter_match(host2)) {                  if(!screen_filter_match(host1) && !screen_filter_match(host2)) {
                   continue;                    continue;
                 }                  }
Line 693  void ui_print() { Line 373  void ui_print() {
     mvaddstr(y+2, 0, "TOTAL: ");      mvaddstr(y+2, 0, "TOTAL: ");
   
     /* Cummulative totals */      /* Cummulative totals */
    mvaddstr(y, 16, "cumm: ");    mvaddstr(y, 16, "cum: ");
   
     readable_size(history_totals.total_sent, line, 10, 1024, 1);      readable_size(history_totals.total_sent, line, 10, 1024, 1);
     mvaddstr(y, 22, line);      mvaddstr(y, 22, line);
Line 733  void ui_print() { Line 413  void ui_print() {
   
     /* Bar chart auto scale */      /* Bar chart auto scale */
     if (wantbiggerrate && options.max_bandwidth == 0) {      if (wantbiggerrate && options.max_bandwidth == 0) {
        ++rateidx;      ++rateidx;
        wantbiggerrate = 0;      wantbiggerrate = 0;
     }      }
 }  }
   
Line 754  void ui_curses_init() { Line 434  void ui_curses_init() {
     (void) nonl();         /* tell curses not to do NL->CR/NL on output */      (void) nonl();         /* tell curses not to do NL->CR/NL on output */
     (void) cbreak();       /* take input chars one at a time, no wait for \n */      (void) cbreak();       /* take input chars one at a time, no wait for \n */
     (void) noecho();       /* don't echo input */      (void) noecho();       /* don't echo input */
       (void) curs_set(0);    /* hide blinking cursor in ui */
     halfdelay(2);      halfdelay(2);
 }  }
   
Line 1045  void ui_loop() { Line 726  void ui_loop() {
                 break;                  break;
             }              }
             case '!': {              case '!': {
#ifndef NO_SYSTEM#ifdef ALLOW_SUBSHELL
                 char *s;                  char *s;
                 dontshowdisplay = 1;                  dontshowdisplay = 1;
                 if ((s = edline(0, "Command", "")) && s[strspn(s, " \t")]) {                  if ((s = edline(0, "Command", "")) && s[strspn(s, " \t")]) {
Line 1082  void ui_loop() { Line 763  void ui_loop() {
             case 'T':              case 'T':
                 options.show_totals = !options.show_totals;                  options.show_totals = !options.show_totals;
                 if(options.show_totals) {                  if(options.show_totals) {
                    showhelp("Show cummulative totals");                    showhelp("Show cumulative totals");
                 }                  }
                 else {                  else {
                    showhelp("Hide cummulative totals");                    showhelp("Hide cumulative totals");
                 }                  }
                 ui_print();                  ui_print();
                 break;                  break;

Removed from v.1.1.1.1  
changed lines
  Added in v.1.1.1.2


FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>