From 77ec0a3b934be3923616a7f26f060805c6873cfc Mon Sep 17 00:00:00 2001 From: "Dr. Nicola Mingotti" Date: Sun, 8 Jan 2023 18:04:32 +0100 Subject: [PATCH 1/4] . aggiunto supporto thousand separator, primi test ok. --- src/cui.cpp | 70 +++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 63 insertions(+), 7 deletions(-) diff --git a/src/cui.cpp b/src/cui.cpp index 8ce50fd..267c549 100644 --- a/src/cui.cpp +++ b/src/cui.cpp @@ -29,10 +29,16 @@ #include #include +#include +#include +#include +#include + #include "nethogs.h" #include "process.h" #include + std::string *caption; static int cursOrig; extern const char version[]; @@ -61,10 +67,14 @@ const int MIN_COLUMN_WIDTH_DEV = 5; const int COLUMN_WIDTH_SENT = 11; const int COLUMN_WIDTH_RECEIVED = 11; const int COLUMN_WIDTH_UNIT = 6; +const int NUMBER_OF_DECIMALS_SENT = 1; +const int NUMBER_OF_DECIMALS_RECEIVED = 1; const char *COLUMN_FORMAT_PID = "%7d"; -const char *COLUMN_FORMAT_SENT = "%11.3f"; -const char *COLUMN_FORMAT_RECEIVED = "%11.3f"; + +const char *COLUMN_FORMAT_SENT = "%s"; +const char *COLUMN_FORMAT_RECEIVED = "%s"; + // All descriptions are padded to 6 characters in length with spaces const char *const desc_view_mode[VIEWMODE_COUNT] = { @@ -72,6 +82,8 @@ const char *const desc_view_mode[VIEWMODE_COUNT] = { constexpr char FILE_SEPARATOR = '/'; +std::string prettyFloat(double val, int decimals, int maxWidth); + class Line { public: Line(const char *name, const char *cmdline, double n_recv_value, @@ -218,9 +230,12 @@ void Line::show(int row, unsigned int proglen, unsigned int devlen) { mvaddstr(row, column_offset_dev, devicename); - mvprintw(row, column_offset_sent, COLUMN_FORMAT_SENT, sent_value); + mvprintw(row, column_offset_sent, COLUMN_FORMAT_SENT, + prettyFloat(sent_value, NUMBER_OF_DECIMALS_SENT, COLUMN_WIDTH_SENT ).c_str() ); + + mvprintw(row, column_offset_received, COLUMN_FORMAT_RECEIVED, + prettyFloat(recv_value, NUMBER_OF_DECIMALS_RECEIVED, COLUMN_WIDTH_RECEIVED).c_str() ); - mvprintw(row, column_offset_received, COLUMN_FORMAT_RECEIVED, recv_value); mvaddstr(row, column_offset_unit, desc_view_mode[viewMode]); } @@ -277,7 +292,7 @@ int GreatestFirst(const void *ma, const void *mb) { return 1; } -void init_ui() { +void init_ui() { WINDOW *screen = initscr(); cursOrig = curs_set(0); raw(); @@ -387,8 +402,12 @@ void show_ncurses(Line *lines[], int nproc) { } attron(A_REVERSE); int totalrow = std::min(rows - 1, 3 + 1 + i); - mvprintw(totalrow, 0, " TOTAL %-*.*s %-*.*s %11.3f %11.3f ", - proglen, proglen, "", devlen, devlen, "", sent_global, recv_global); + mvprintw(totalrow, 0, " TOTAL %-*.*s %-*.*s %s %s ", + proglen, proglen, "", devlen, devlen, "", + prettyFloat(sent_global, NUMBER_OF_DECIMALS_SENT, COLUMN_WIDTH_SENT).c_str(), + prettyFloat(recv_global, NUMBER_OF_DECIMALS_RECEIVED, COLUMN_WIDTH_RECEIVED).c_str() + ); +// recv_global); mvprintw(3 + 1 + i, cols - COLUMN_WIDTH_UNIT, "%s", desc_view_mode[viewMode]); attroff(A_REVERSE); mvprintw(totalrow + 1, 0, "%s", ""); @@ -461,3 +480,40 @@ void do_refresh() { if (refreshlimit != 0 && refreshcount >= refreshlimit) quit_cb(0); } + + +// . Returns a String with a nice representation of the floating point value 'val' +// . There will be 'decimals' number of digits after the decimal point +// . There will be thousand separators as "'", independent of the user locale +// . String wiil have width 'maxWidth', the value is aligned to the right, the padding +// values at the left are white spaces. +// . If the the resulting number-string is bigger in than 'maxWidth' a +// default string "ERR:tooBig" is returned, padded to maxWidth. +// . test with something like: +// std::cout << "Test di prettyFloat: " << prettyFloat(123456.123456, 1, 15) << "\n"; +// . Adapted from here: https://stackoverflow.com/a/43482688/2129178 +std::string prettyFloat(double val, int decimals, int maxWidth) { + + struct separate_thousands : std::numpunct { + char_type do_thousands_sep() const override { return ','; } // separate with commas + string_type do_grouping() const override { return "\3"; } // groups of 3 digit + }; + + std::stringstream ss1; + auto thousands = std::make_unique() ; + ss1.imbue( std::locale(std::cout.getloc(), thousands.release() ) ); + ss1.setf(std::ios_base::fixed, std::ios_base::floatfield); + ss1.precision(decimals); + ss1 << std::setw(maxWidth); + ss1 << val; + std::string out = ss1.str(); + if (out.length() > (long unsigned)maxWidth) { + ss1.str(""); + ss1 << std::setw(maxWidth); + ss1 << "ERR:tooBig"; + out = ss1.str(); + } + return out; +}; + + From ea1d845d4fa1d28d03239276c0a1da424c5ce377 Mon Sep 17 00:00:00 2001 From: "Dr. Nicola Mingotti" Date: Mon, 9 Jan 2023 10:07:38 +0100 Subject: [PATCH 2/4] . spell check comment in prettyFloat --- src/cui.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cui.cpp b/src/cui.cpp index 267c549..d054be8 100644 --- a/src/cui.cpp +++ b/src/cui.cpp @@ -485,7 +485,7 @@ void do_refresh() { // . Returns a String with a nice representation of the floating point value 'val' // . There will be 'decimals' number of digits after the decimal point // . There will be thousand separators as "'", independent of the user locale -// . String wiil have width 'maxWidth', the value is aligned to the right, the padding +// . String will have width 'maxWidth', the value is aligned to the right, the padding // values at the left are white spaces. // . If the the resulting number-string is bigger in than 'maxWidth' a // default string "ERR:tooBig" is returned, padded to maxWidth. From ca8d0b256bc47d4af30853d58db4de065ad31b1e Mon Sep 17 00:00:00 2001 From: "Dr. Nicola Mingotti" Date: Mon, 9 Jan 2023 15:54:04 +0100 Subject: [PATCH 3/4] . removed commend recv_global --- src/cui.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cui.cpp b/src/cui.cpp index d054be8..48b2420 100644 --- a/src/cui.cpp +++ b/src/cui.cpp @@ -407,7 +407,7 @@ void show_ncurses(Line *lines[], int nproc) { prettyFloat(sent_global, NUMBER_OF_DECIMALS_SENT, COLUMN_WIDTH_SENT).c_str(), prettyFloat(recv_global, NUMBER_OF_DECIMALS_RECEIVED, COLUMN_WIDTH_RECEIVED).c_str() ); -// recv_global); + mvprintw(3 + 1 + i, cols - COLUMN_WIDTH_UNIT, "%s", desc_view_mode[viewMode]); attroff(A_REVERSE); mvprintw(totalrow + 1, 0, "%s", ""); From 3b3774d2d08a44bc572b0837b3609a33e508eb74 Mon Sep 17 00:00:00 2001 From: "Dr. Nicola Mingotti" Date: Mon, 9 Jan 2023 16:02:07 +0100 Subject: [PATCH 4/4] . make format --- src/cui.cpp | 78 +++++++++++++++++++++++++--------------------- src/libnethogs.cpp | 5 +-- src/libnethogs.h | 6 ++-- src/main.cpp | 15 ++++----- src/packet.cpp | 7 ++--- src/packet.h | 2 +- src/process.cpp | 13 ++++---- src/process.h | 8 ++--- 8 files changed, 70 insertions(+), 64 deletions(-) diff --git a/src/cui.cpp b/src/cui.cpp index 48b2420..700401f 100644 --- a/src/cui.cpp +++ b/src/cui.cpp @@ -29,16 +29,15 @@ #include #include +#include #include #include #include -#include #include "nethogs.h" #include "process.h" #include - std::string *caption; static int cursOrig; extern const char version[]; @@ -67,15 +66,14 @@ const int MIN_COLUMN_WIDTH_DEV = 5; const int COLUMN_WIDTH_SENT = 11; const int COLUMN_WIDTH_RECEIVED = 11; const int COLUMN_WIDTH_UNIT = 6; -const int NUMBER_OF_DECIMALS_SENT = 1; -const int NUMBER_OF_DECIMALS_RECEIVED = 1; +const int NUMBER_OF_DECIMALS_SENT = 1; +const int NUMBER_OF_DECIMALS_RECEIVED = 1; const char *COLUMN_FORMAT_PID = "%7d"; const char *COLUMN_FORMAT_SENT = "%s"; const char *COLUMN_FORMAT_RECEIVED = "%s"; - // All descriptions are padded to 6 characters in length with spaces const char *const desc_view_mode[VIEWMODE_COUNT] = { "KB/s ", "KB ", "B ", "MB ", "MB/s ", "GB/s "}; @@ -230,11 +228,14 @@ void Line::show(int row, unsigned int proglen, unsigned int devlen) { mvaddstr(row, column_offset_dev, devicename); - mvprintw(row, column_offset_sent, COLUMN_FORMAT_SENT, - prettyFloat(sent_value, NUMBER_OF_DECIMALS_SENT, COLUMN_WIDTH_SENT ).c_str() ); + mvprintw(row, column_offset_sent, COLUMN_FORMAT_SENT, + prettyFloat(sent_value, NUMBER_OF_DECIMALS_SENT, COLUMN_WIDTH_SENT) + .c_str()); - mvprintw(row, column_offset_received, COLUMN_FORMAT_RECEIVED, - prettyFloat(recv_value, NUMBER_OF_DECIMALS_RECEIVED, COLUMN_WIDTH_RECEIVED).c_str() ); + mvprintw(row, column_offset_received, COLUMN_FORMAT_RECEIVED, + prettyFloat(recv_value, NUMBER_OF_DECIMALS_RECEIVED, + COLUMN_WIDTH_RECEIVED) + .c_str()); mvaddstr(row, column_offset_unit, desc_view_mode[viewMode]); } @@ -292,7 +293,7 @@ int GreatestFirst(const void *ma, const void *mb) { return 1; } -void init_ui() { +void init_ui() { WINDOW *screen = initscr(); cursOrig = curs_set(0); raw(); @@ -351,9 +352,9 @@ void show_trace(Line *lines[], int nproc) { } /* print the 'unknown' connections, for debugging */ - for (auto it = unknowntcp->connections.begin(); it != unknowntcp->connections.end(); ++it) { - std::cout << "Unknown connection: " - << (*it)->refpacket->gethashstring() + for (auto it = unknowntcp->connections.begin(); + it != unknowntcp->connections.end(); ++it) { + std::cout << "Unknown connection: " << (*it)->refpacket->gethashstring() << std::endl; } } @@ -402,11 +403,13 @@ void show_ncurses(Line *lines[], int nproc) { } attron(A_REVERSE); int totalrow = std::min(rows - 1, 3 + 1 + i); - mvprintw(totalrow, 0, " TOTAL %-*.*s %-*.*s %s %s ", - proglen, proglen, "", devlen, devlen, "", - prettyFloat(sent_global, NUMBER_OF_DECIMALS_SENT, COLUMN_WIDTH_SENT).c_str(), - prettyFloat(recv_global, NUMBER_OF_DECIMALS_RECEIVED, COLUMN_WIDTH_RECEIVED).c_str() - ); + mvprintw(totalrow, 0, " TOTAL %-*.*s %-*.*s %s %s ", proglen, + proglen, "", devlen, devlen, "", + prettyFloat(sent_global, NUMBER_OF_DECIMALS_SENT, COLUMN_WIDTH_SENT) + .c_str(), + prettyFloat(recv_global, NUMBER_OF_DECIMALS_RECEIVED, + COLUMN_WIDTH_RECEIVED) + .c_str()); mvprintw(3 + 1 + i, cols - COLUMN_WIDTH_UNIT, "%s", desc_view_mode[viewMode]); attroff(A_REVERSE); @@ -481,39 +484,42 @@ void do_refresh() { quit_cb(0); } - -// . Returns a String with a nice representation of the floating point value 'val' -// . There will be 'decimals' number of digits after the decimal point -// . There will be thousand separators as "'", independent of the user locale -// . String will have width 'maxWidth', the value is aligned to the right, the padding +// . Returns a String with a nice representation of the floating point value +// 'val' . There will be 'decimals' number of digits after the decimal point . +// There will be thousand separators as "'", independent of the user locale . +// String will have width 'maxWidth', the value is aligned to the right, the +// padding // values at the left are white spaces. -// . If the the resulting number-string is bigger in than 'maxWidth' a +// . If the the resulting number-string is bigger in than 'maxWidth' a // default string "ERR:tooBig" is returned, padded to maxWidth. // . test with something like: -// std::cout << "Test di prettyFloat: " << prettyFloat(123456.123456, 1, 15) << "\n"; +// std::cout << "Test di prettyFloat: " << prettyFloat(123456.123456, 1, 15) +// << "\n"; // . Adapted from here: https://stackoverflow.com/a/43482688/2129178 std::string prettyFloat(double val, int decimals, int maxWidth) { struct separate_thousands : std::numpunct { - char_type do_thousands_sep() const override { return ','; } // separate with commas - string_type do_grouping() const override { return "\3"; } // groups of 3 digit + char_type do_thousands_sep() const override { + return ','; + } // separate with commas + string_type do_grouping() const override { + return "\3"; + } // groups of 3 digit }; - std::stringstream ss1; - auto thousands = std::make_unique() ; - ss1.imbue( std::locale(std::cout.getloc(), thousands.release() ) ); - ss1.setf(std::ios_base::fixed, std::ios_base::floatfield); - ss1.precision(decimals); + std::stringstream ss1; + auto thousands = std::make_unique(); + ss1.imbue(std::locale(std::cout.getloc(), thousands.release())); + ss1.setf(std::ios_base::fixed, std::ios_base::floatfield); + ss1.precision(decimals); ss1 << std::setw(maxWidth); ss1 << val; std::string out = ss1.str(); - if (out.length() > (long unsigned)maxWidth) { + if (out.length() > (long unsigned)maxWidth) { ss1.str(""); ss1 << std::setw(maxWidth); ss1 << "ERR:tooBig"; out = ss1.str(); } return out; -}; - - +}; diff --git a/src/libnethogs.cpp b/src/libnethogs.cpp index ef4df82..2d02d05 100644 --- a/src/libnethogs.cpp +++ b/src/libnethogs.cpp @@ -277,11 +277,12 @@ static void nethogsmonitor_clean_up() { } int nethogsmonitor_loop(NethogsMonitorCallback cb, char *filter, int to_ms) { - return nethogsmonitor_loop_devices(cb, filter, 0, NULL, false, to_ms); + return nethogsmonitor_loop_devices(cb, filter, 0, NULL, false, to_ms); } int nethogsmonitor_loop_devices(NethogsMonitorCallback cb, char *filter, - int devc, char **devicenames, bool all, int to_ms) { + int devc, char **devicenames, bool all, + int to_ms) { if (monitor_run_flag) { return NETHOGS_STATUS_FAILURE; } diff --git a/src/libnethogs.h b/src/libnethogs.h index 81d127d..2ea0167 100644 --- a/src/libnethogs.h +++ b/src/libnethogs.h @@ -62,8 +62,7 @@ typedef void (*NethogsMonitorCallback)(int action, */ NETHOGS_DSO_VISIBLE int nethogsmonitor_loop(NethogsMonitorCallback cb, - char *filter, - int to_ms); + char *filter, int to_ms); /** * @brief Enter the process monitoring loop and reports updates using the @@ -87,8 +86,7 @@ NETHOGS_DSO_VISIBLE int nethogsmonitor_loop(NethogsMonitorCallback cb, NETHOGS_DSO_VISIBLE int nethogsmonitor_loop_devices(NethogsMonitorCallback cb, char *filter, int devc, char **devicenames, - bool all, - int to_ms); + bool all, int to_ms); /** * @brief Makes the call to nethogsmonitor_loop return. diff --git a/src/main.cpp b/src/main.cpp index 2c71f88..da10cca 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -51,7 +51,8 @@ static void help(bool iserror) { output << " -C : capture TCP and UDP.\n"; output << " -g : garbage collection period in number of refresh. " "default is 50.\n"; - output << " -b : Short program name. Displays only the program name.\n"; + output << " -b : Short program name. Displays only the program " + "name.\n"; output << " -f : EXPERIMENTAL: specify string pcap filter (like " "tcpdump)." " This may be removed or changed in a future version.\n"; @@ -150,7 +151,6 @@ int main(int argc, char **argv) { char *filter = NULL; int garbage_collection_period = 50; - int opt; while ((opt = getopt(argc, argv, "Vhxtpsd:v:c:laf:Cbg:P:")) != -1) { switch (opt) { @@ -201,7 +201,7 @@ int main(int argc, char **argv) { garbage_collection_period = (time_t)atoi(optarg); break; case 'P': - pidsToWatch.insert((pid_t) atoi(optarg)); + pidsToWatch.insert((pid_t)atoi(optarg)); break; default: help(true); @@ -287,10 +287,11 @@ int main(int argc, char **argv) { if (nb_devices == nb_failed_devices) { if (geteuid() != 0) - fprintf(stderr, "To run nethogs without being root, you need to enable " - "capabilities on the program (cap_net_admin, cap_net_raw, " - "cap_dac_read_search, cap_sys_ptrace). " - "See the documentation for details.\n"); + fprintf(stderr, + "To run nethogs without being root, you need to enable " + "capabilities on the program (cap_net_admin, cap_net_raw, " + "cap_dac_read_search, cap_sys_ptrace). " + "See the documentation for details.\n"); forceExit(false, "Error opening pcap handlers for all devices.\n"); } diff --git a/src/packet.cpp b/src/packet.cpp index 34b8791..323ae44 100644 --- a/src/packet.cpp +++ b/src/packet.cpp @@ -300,9 +300,8 @@ bool Packet::match(const Packet *other) const { bool Packet::matchSource(const Packet *other) const { return sa_family == other->sa_family && (sport == other->sport) && - (sa_family == AF_INET - ? (sameinaddr(sip, other->sip)) - : (samein6addr(sip6, other->sip6))); + (sa_family == AF_INET ? (sameinaddr(sip, other->sip)) + : (samein6addr(sip6, other->sip6))); } Packet Packet::onlySource() const { @@ -313,7 +312,7 @@ Packet Packet::onlySource() const { return p; } -bool Packet::operator< (const Packet& other) const { +bool Packet::operator<(const Packet &other) const { if (sa_family != other.sa_family) return dir < other.sa_family; /* source address first */ diff --git a/src/packet.h b/src/packet.h index 0fde51b..0eb4cfe 100644 --- a/src/packet.h +++ b/src/packet.h @@ -74,7 +74,7 @@ class Packet { bool matchSource(const Packet *other) const; /* returns a copy with destination information stripped (for comparisons) */ Packet onlySource() const; - bool operator< (const Packet& other) const; + bool operator<(const Packet &other) const; /* returns '1.2.3.4:5-1.2.3.4:6'-style string */ char *gethashstring(); diff --git a/src/process.cpp b/src/process.cpp index 1cfc741..6c6dd30 100644 --- a/src/process.cpp +++ b/src/process.cpp @@ -30,12 +30,12 @@ #endif #include #include +#include #include #include #include #include #include -#include #include "conninode.h" #include "inode2prog.h" @@ -81,7 +81,6 @@ float tokbps(u_int64_t bytes) { return (((double)bytes) / PERIOD) / KB; } float tombps(u_int64_t bytes) { return (((double)bytes) / PERIOD) / MB; } float togbps(u_int64_t bytes) { return (((double)bytes) / PERIOD) / GB; } - void process_init() { unknowntcp = new Process(0, "", "unknown TCP"); processes = new ProcList(unknowntcp, NULL); @@ -92,7 +91,6 @@ void process_init() { // unknownip = new Process (0, "", "unknown IP"); // processes = new ProcList (unknownip, processes); } - } int Process::getLastPacket() { @@ -110,7 +108,8 @@ static void sum_active_connections(Process *process_ptr, u_int64_t &sum_sent, u_int64_t &sum_recv) { /* walk though all process_ptr process's connections, and sum * them up */ - for (auto it = process_ptr->connections.begin(); it != process_ptr->connections.end(); ) { + for (auto it = process_ptr->connections.begin(); + it != process_ptr->connections.end();) { if ((*it)->getLastPacket() <= curtime.tv_sec - CONNTIMEOUT) { /* capture sent and received totals before deleting */ process_ptr->sent_by_closed_bytes += (*it)->sumSent; @@ -158,7 +157,8 @@ void Process::getgbps(float *recvd, float *sent) { /** get total values for this process */ void Process::gettotal(u_int64_t *recvd, u_int64_t *sent) { u_int64_t sum_sent = 0, sum_recv = 0; - for (auto it = this->connections.begin(); it != this->connections.end(); ++it) { + for (auto it = this->connections.begin(); it != this->connections.end(); + ++it) { Connection *conn = (*it); sum_sent += conn->sumSent; sum_recv += conn->sumRecv; @@ -253,7 +253,8 @@ Process *getProcess(unsigned long inode, const char *devicename) { if (proc != NULL) return proc; - if ( !(pidsToWatch.empty()) && pidsToWatch.find(node->pid) == pidsToWatch.end() ) { + if (!(pidsToWatch.empty()) && + pidsToWatch.find(node->pid) == pidsToWatch.end()) { return NULL; } diff --git a/src/process.h b/src/process.h index 3730e33..5396b41 100644 --- a/src/process.h +++ b/src/process.h @@ -36,19 +36,19 @@ void check_all_procs(); /* compares Connection pointers by their refpacket */ struct ConnectionComparator { using is_transparent = void; - bool operator()(const Connection* l, const Connection* r) const { + bool operator()(const Connection *l, const Connection *r) const { return *l->refpacket < *r->refpacket; } - bool operator()(const Packet* l, const Connection* r) const { + bool operator()(const Packet *l, const Connection *r) const { return *l < *r->refpacket; } - bool operator()(const Connection* l, const Packet* r) const { + bool operator()(const Connection *l, const Packet *r) const { return *l->refpacket < *r; } }; /* ordered set of Connection pointers */ -typedef std::multiset ConnList; +typedef std::multiset ConnList; class Process { public: