From 0690c3e2b59495f2d5dd39ba588811963c385f7b Mon Sep 17 00:00:00 2001 From: Mohamed Boussaffa Date: Sat, 5 Mar 2016 22:57:01 +0800 Subject: [PATCH] exposing c interface instead of c++, for more compatibility. --- libnethogs.cpp | 169 +++++++++++++++++++++++++++++-------------------- libnethogs.h | 58 +++++++---------- 2 files changed, 122 insertions(+), 105 deletions(-) diff --git a/libnethogs.cpp b/libnethogs.cpp index b4e43ef..56049ca 100644 --- a/libnethogs.cpp +++ b/libnethogs.cpp @@ -1,6 +1,9 @@ -#include "libnethogs.h" -#include "nethogs.cpp" +extern "C" +{ + #include "libnethogs.h" +} +#include "nethogs.cpp" #include #include #include @@ -23,27 +26,30 @@ static std::atomic_bool monitor_thread_run_flag(false); std::mutex monitor_exit_event_mutex; std::condition_variable monitor_exit_event; -static NethogsMonitor::Callback monitor_udpate_callback; +static NethogsMonitorCallback monitor_udpate_callback; -typedef std::map NethogsAppUpdateMap; +typedef std::map NethogsAppUpdateMap; static NethogsAppUpdateMap monitor_update_data; static int monitor_refresh_delay = 1; static int monitor_pc_dispatch_delay_ms = 50; static time_t monitor_last_refresh_time = 0; -void NethogsMonitor::threadProc() +static handle * handles = NULL; + +static bool nethogsmonitor_init() { + bool success = true; + process_init(); device * devices = get_default_devices(); if ( devices == NULL ) { std::cerr << "Not devices to monitor" << std::endl; - return; + return false; } - handle * handles = NULL; device * current_dev = devices; bool promiscuous = false; @@ -53,6 +59,7 @@ void NethogsMonitor::threadProc() if( !getLocal(current_dev->name, false) ) { std::cerr << "getifaddrs failed while establishing local IP." << std::endl; + success = false; continue; } @@ -79,6 +86,7 @@ void NethogsMonitor::threadProc() } else { + success = false; fprintf(stderr, "ERROR: opening handler for device %s: %s\n", current_dev->name, strerror(errno)); } @@ -86,49 +94,10 @@ void NethogsMonitor::threadProc() current_dev = current_dev->next; } - fprintf(stderr, "Waiting for first packet to arrive (see sourceforge.net bug 1019381)\n"); - struct dpargs * userdata = (dpargs *) malloc (sizeof (struct dpargs)); - - // Main loop: - // Walks though the 'handles' list, which contains handles opened in non-blocking mode. - // This causes the CPU utilisation to go up to 100%. This is tricky: - while (monitor_thread_run_flag) - { - bool packets_read = false; - - handle * current_handle = handles; - while (current_handle != NULL) - { - userdata->device = current_handle->devicename; - userdata->sa_family = AF_UNSPEC; - int retval = dp_dispatch (current_handle->content, -1, (u_char *)userdata, sizeof (struct dpargs)); - if (retval < 0) - { - std::cerr << "Error dispatching: " << retval << std::endl; - } - else if (retval != 0) - { - packets_read = true; - } - current_handle = current_handle->next; - } - - time_t const now = ::time(NULL); - if( monitor_last_refresh_time + monitor_refresh_delay <= now ) - { - monitor_last_refresh_time = now; - handleUpdate(); - } - - if (!packets_read) - { - std::unique_lock lk(monitor_exit_event_mutex); - monitor_exit_event.wait_for(lk, std::chrono::milliseconds(monitor_pc_dispatch_delay_ms)); - } - } + return success; } -void NethogsMonitor::handleUpdate() +static void nethogsmonitor_handle_update() { refreshconninode(); refreshcount++; @@ -160,9 +129,9 @@ void NethogsMonitor::handleUpdate() NethogsAppUpdateMap::iterator it = monitor_update_data.find(curproc->getVal()->pid); if( it != monitor_update_data.end() ) { - NethogsAppUpdate &data = it->second; - data.action = NethogsAppUpdate::Remove; - monitor_udpate_callback(data); + NethogsMonitorUpdate& data = it->second; + data.action = NETHOGS_APP_ACTION_REMOVE; + monitor_udpate_callback(&data); monitor_update_data.erase(curproc->getVal()->pid); } } @@ -185,7 +154,8 @@ void NethogsMonitor::handleUpdate() } else { - int const pid = curproc->getVal()->pid; + const int pid = curproc->getVal()->pid; + const u_int32_t uid = curproc->getVal()->getUid(); u_int32_t sent_bytes; u_int32_t recv_bytes; float sent_kbs; @@ -196,30 +166,34 @@ void NethogsMonitor::handleUpdate() if( monitor_udpate_callback ) { //notify update - bool const new_process = (monitor_update_data.find(pid) == monitor_update_data.end()); - NethogsAppUpdate &data = monitor_update_data[pid]; + bool const new_data = (monitor_update_data.find(pid) == monitor_update_data.end()); + NethogsMonitorUpdate &data = monitor_update_data[pid]; - bool data_change = false; - - #define NHM_UPDATE_ONE_FIELD(TO,FROM) if((TO)!=(FROM)) { TO = FROM; data_change = true; } - if( new_process ) + bool data_change = false; + if( new_data ) { - NHM_UPDATE_ONE_FIELD( data.pid, pid ) - NHM_UPDATE_ONE_FIELD( data.app_name, curproc->getVal()->name ) + data_change = true; + memset(&data, 0, sizeof(data)); + data.pid = pid; + data.app_name = curproc->getVal()->name; } - NHM_UPDATE_ONE_FIELD( data.uid, curproc->getVal()->getUid() ) - NHM_UPDATE_ONE_FIELD( data.device_name, curproc->getVal()->devicename ) + data.device_name = curproc->getVal()->devicename; + + #define NHM_UPDATE_ONE_FIELD(TO,FROM) if((TO)!=(FROM)) { TO = FROM; data_change = true; } + + NHM_UPDATE_ONE_FIELD( data.uid, uid ) NHM_UPDATE_ONE_FIELD( data.sent_bytes, sent_bytes ) NHM_UPDATE_ONE_FIELD( data.recv_bytes, recv_bytes ) NHM_UPDATE_ONE_FIELD( data.sent_kbs, sent_kbs ) NHM_UPDATE_ONE_FIELD( data.recv_kbs, recv_kbs ) + #undef NHM_UPDATE_ONE_FIELD if( data_change ) { - data.action = NethogsAppUpdate::Set; - monitor_udpate_callback(data); + data.action = NETHOGS_APP_ACTION_SET; + monitor_udpate_callback(&data); } } @@ -230,7 +204,56 @@ void NethogsMonitor::handleUpdate() } } -void NethogsMonitor::registerUpdateCallback(Callback const& cb) +static void nethogsmonitor_threadproc() +{ + fprintf(stderr, "Waiting for first packet to arrive (see sourceforge.net bug 1019381)\n"); + struct dpargs * userdata = (dpargs *) malloc (sizeof (struct dpargs)); + + // Main loop + while (monitor_thread_run_flag) + { + bool packets_read = false; + + handle * current_handle = handles; + while (current_handle != NULL) + { + userdata->device = current_handle->devicename; + userdata->sa_family = AF_UNSPEC; + int retval = dp_dispatch (current_handle->content, -1, (u_char *)userdata, sizeof (struct dpargs)); + if (retval < 0) + { + std::cerr << "Error dispatching: " << retval << std::endl; + } + else if (retval != 0) + { + packets_read = true; + } + current_handle = current_handle->next; + } + + time_t const now = ::time(NULL); + if( monitor_last_refresh_time + monitor_refresh_delay <= now ) + { + monitor_last_refresh_time = now; + nethogsmonitor_handle_update(); + } + + if (!packets_read) + { + std::unique_lock lk(monitor_exit_event_mutex); + monitor_exit_event.wait_for(lk, std::chrono::milliseconds(monitor_pc_dispatch_delay_ms)); + } + } + + handle * current_handle = handles; + while (current_handle != NULL) + { + pcap_close(current_handle->content->pcap_handle); + current_handle = current_handle->next; + } +} + +void nethogsmonitor_register_callback(NethogsMonitorCallback cb) { if( !monitor_thread_run_flag ) { @@ -238,26 +261,32 @@ void NethogsMonitor::registerUpdateCallback(Callback const& cb) } } -void NethogsMonitor::setRefreshDelay(int seconds) +void nethogsmonitor_set_refresh_delay(int seconds) { monitor_refresh_delay = seconds; } -void NethogsMonitor::setPcapDispatchDelay(int milliseconds) +void nethogsmonitor_set_pcap_dispatch_delay(int milliseconds) { monitor_pc_dispatch_delay_ms = milliseconds; } -void NethogsMonitor::start() +bool nethogsmonitor_start() { bool expected = false; + bool success = true; if( monitor_thread_run_flag.compare_exchange_strong(expected, true) ) { - monitor_thread_ptr = std::make_shared(&NethogsMonitor::threadProc); + if( !nethogsmonitor_init() ) + { + success = false; + } + monitor_thread_ptr = std::make_shared(&nethogsmonitor_threadproc); } + return success; } -void NethogsMonitor::stop() +void nethogsmonitor_stop() { bool expected = true; if( monitor_thread_run_flag.compare_exchange_strong(expected, false) ) diff --git a/libnethogs.h b/libnethogs.h index cf22643..dbd35f0 100644 --- a/libnethogs.h +++ b/libnethogs.h @@ -2,55 +2,43 @@ #define LIBNETHOGS_H_ #include -#include -#include +#include #define NETHOGS_DSO_VISIBLE __attribute__ ((visibility ("default"))) #define NETHOGS_DSO_HIDDEN __attribute__ ((visibility ("hidden"))) -class NETHOGS_DSO_VISIBLE NethogsAppUpdate +#define NETHOGS_APP_ACTION_SET 1 +#define NETHOGS_APP_ACTION_REMOVE 2 + +typedef struct NethogsMonitorUpdate { -public: - enum Action {Set, Remove}; - NethogsAppUpdate() - : action(Set), pid(0), uid(0), sent_kbs(0), recv_kbs(0) - { - } - Action action; + int action; int pid; uint32_t uid; - std::string app_name; - std::string device_name; + const char* app_name; + const char* device_name; uint32_t sent_bytes; uint32_t recv_bytes; float sent_kbs; float recv_kbs; -}; +} NethogsMonitorUpdate; -class NETHOGS_DSO_VISIBLE NethogsMonitor -{ - NethogsMonitor(); -public: - typedef void(*Callback)(NethogsAppUpdate const&); +typedef void(*NethogsMonitorCallback)(NethogsMonitorUpdate const*); - //register async callback to receive updates - //have to be called before start - static void registerUpdateCallback(Callback const& cb); - - //start the monitor - static void start(); +//register async callback to receive updates +//have to be called before start +NETHOGS_DSO_VISIBLE void nethogsmonitor_register_callback(NethogsMonitorCallback); - //stop the monitor - static void stop(); - - //tuning functions - static void setRefreshDelay(int seconds); - static void setPcapDispatchDelay(int milliseconds); - -private: - static void threadProc(); - static void handleUpdate(); - }; +//start the monitor +NETHOGS_DSO_VISIBLE bool nethogsmonitor_start(); + +//stop the monitor +NETHOGS_DSO_VISIBLE void nethogsmonitor_stop(); + +//tuning functions +NETHOGS_DSO_VISIBLE void nethogsmonitor_set_refresh_delay(int seconds); +NETHOGS_DSO_VISIBLE void nethogsmonitor_set_pcap_dispatch_delay(int milliseconds); + #undef NETHOGS_DSO_VISIBLE #undef NETHOGS_DSO_HIDDEN