Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Thusand separator in data sent/received #247

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
80 changes: 71 additions & 9 deletions src/cui.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,11 @@
#include <strings.h>
#include <sys/types.h>

#include <iomanip>
#include <iostream>
#include <locale>
#include <sstream>

#include "nethogs.h"
#include "process.h"
#include <ncurses.h>
Expand Down Expand Up @@ -61,17 +66,22 @@ 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] = {
"KB/s ", "KB ", "B ", "MB ", "MB/s ", "GB/s "};

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,
Expand Down Expand Up @@ -218,9 +228,15 @@ 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]);
}

Expand Down Expand Up @@ -336,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;
}
}
Expand Down Expand Up @@ -387,8 +403,14 @@ 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());

mvprintw(3 + 1 + i, cols - COLUMN_WIDTH_UNIT, "%s", desc_view_mode[viewMode]);
attroff(A_REVERSE);
mvprintw(totalrow + 1, 0, "%s", "");
Expand Down Expand Up @@ -461,3 +483,43 @@ 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 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.
// . 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> {
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<separate_thousands>();
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;
};
5 changes: 3 additions & 2 deletions src/libnethogs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down
6 changes: 2 additions & 4 deletions src/libnethogs.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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.
Expand Down
15 changes: 8 additions & 7 deletions src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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");
}

Expand Down
7 changes: 3 additions & 4 deletions src/packet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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 */
Expand Down
2 changes: 1 addition & 1 deletion src/packet.h
Original file line number Diff line number Diff line change
Expand Up @@ -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();

Expand Down
13 changes: 7 additions & 6 deletions src/process.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,12 @@
#endif
#include <map>
#include <pwd.h>
#include <signal.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <signal.h>

#include "conninode.h"
#include "inode2prog.h"
Expand Down Expand Up @@ -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);
Expand All @@ -92,7 +91,6 @@ void process_init() {
// unknownip = new Process (0, "", "unknown IP");
// processes = new ProcList (unknownip, processes);
}

}

int Process::getLastPacket() {
Expand All @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
}

Expand Down
8 changes: 4 additions & 4 deletions src/process.h
Original file line number Diff line number Diff line change
Expand Up @@ -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<Connection*, ConnectionComparator> ConnList;
typedef std::multiset<Connection *, ConnectionComparator> ConnList;

class Process {
public:
Expand Down