+ int cmpu64(uint64_t a, uint64_t b) {
+ if(a < b)
+ return -1;
+ else if(a > b)
+ return 1;
+ else
+ return 0;
+ }
+
+ int sortfunc(const void *a, const void *b) {
+ const nodestats_t *na = *(const nodestats_t **)a;
+ const nodestats_t *nb = *(const nodestats_t **)b;
+ switch(sortmode) {
+ case 1:
+ if(cumulative)
+ return -cmpu64(na->in_packets, nb->in_packets) ?: na->i - nb->i;
+ else
+ return -cmpfloat(na->in_packets_rate, nb->in_packets_rate) ?: na->i - nb->i;
+ case 2:
+ if(cumulative)
+ return -cmpu64(na->in_bytes, nb->in_bytes) ?: na->i - nb->i;
+ else
+ return -cmpfloat(na->in_bytes_rate, nb->in_bytes_rate) ?: na->i - nb->i;
+ case 3:
+ if(cumulative)
+ return -cmpu64(na->out_packets, nb->out_packets) ?: na->i - nb->i;
+ else
+ return -cmpfloat(na->out_packets_rate, nb->out_packets_rate) ?: na->i - nb->i;
+ case 4:
+ if(cumulative)
+ return -cmpu64(na->out_bytes, nb->out_bytes) ?: na->i - nb->i;
+ else
+ return -cmpfloat(na->out_bytes_rate, nb->out_bytes_rate) ?: na->i - nb->i;
+ case 5:
+ if(cumulative)
+ return -cmpu64(na->in_packets + na->out_packets, nb->in_packets + nb->out_packets) ?: na->i - nb->i;
+ else
+ return -cmpfloat(na->in_packets_rate + na->out_packets_rate, nb->in_packets_rate + nb->out_packets_rate) ?: na->i - nb->i;
+ case 6:
+ if(cumulative)
+ return -cmpu64(na->in_bytes + na->out_bytes, nb->in_bytes + nb->out_bytes) ?: na->i - nb->i;
+ else
+ return -cmpfloat(na->in_bytes_rate + na->out_bytes_rate, nb->in_bytes_rate + nb->out_bytes_rate) ?: na->i - nb->i;
+ default:
+ return strcmp(na->name, nb->name) ?: na->i - nb->i;
+ }
+ }
+
+ qsort(sorted, n, sizeof *sorted, sortfunc);
+
+ for(int i = 0, row = 3; i < n; i++, row++) {
+ nodestats_t *node = sorted[i];
+ if(node->known)
+ if(node->in_packets_rate || node->out_packets_rate)
+ attrset(A_BOLD);
+ else
+ attrset(A_NORMAL);
+ else
+ attrset(A_DIM);
+
+ if(cumulative)
+ mvprintw(row, 0, "%-16s %10"PRIu64" %10.0f %10"PRIu64" %10.0f",
+ node->name, node->in_packets, node->in_bytes * scale, node->out_packets, node->out_bytes * scale);
+ else
+ mvprintw(row, 0, "%-16s %10.0f %10.0f %10.0f %10.0f",
+ node->name, node->in_packets_rate, node->in_bytes_rate * scale, node->out_packets_rate, node->out_bytes_rate * scale);
+ }
+
+ attrset(A_NORMAL);
+ move(1, 0);
+
+ refresh();
+}
+
+void top(int fd) {
+ initscr();
+ timeout(delay);
+ bool running = true;
+
+ while(running) {
+ update(fd);
+ redraw();
+
+ switch(getch()) {
+ case 's': {
+ timeout(-1);
+ float input = delay * 1e-3;
+ mvprintw(1, 0, "Change delay from %.1fs to: ", input);
+ scanw("%f", &input);
+ if(input < 0.1)
+ input = 0.1;
+ delay = input * 1e3;
+ timeout(delay);
+ break;
+ }
+ case 'c':
+ cumulative = !cumulative;
+ break;
+ case 'n':
+ sortmode = 0;
+ break;
+ case 'i':
+ sortmode = 2;
+ break;
+ case 'I':
+ sortmode = 1;
+ break;
+ case 'o':
+ sortmode = 4;
+ break;
+ case 'O':
+ sortmode = 3;
+ break;
+ case 't':
+ sortmode = 6;
+ break;
+ case 'T':
+ sortmode = 5;
+ break;
+ case 'b':
+ unit = "bytes";
+ scale = 1;
+ break;
+ case 'k':
+ unit = "kbyte";
+ scale = 1e-3;
+ break;
+ case 'M':
+ unit = "Mbyte";
+ scale = 1e-6;
+ break;
+ case 'G':
+ unit = "Gbyte";
+ scale = 1e-9;
+ break;
+ case 'q':
+ case KEY_BREAK:
+ running = false;
+ break;
+ default:
+ break;
+ }
+ }