From 0c6fbfe10cd430bdfb23bc709a4cc88f3b238660 Mon Sep 17 00:00:00 2001 From: Mohamed Boussaffa Date: Thu, 10 Mar 2016 19:21:29 +0800 Subject: [PATCH] removed multithreading and c++11 and used a pcap_loop-like api --- MakeLib.mk | 4 +- libnethogs.cpp | 182 +++++++++++++++++++++++++------------------------ libnethogs.h | 20 +++--- 3 files changed, 106 insertions(+), 100 deletions(-) diff --git a/MakeLib.mk b/MakeLib.mk index 8a26d6b..1795950 100644 --- a/MakeLib.mk +++ b/MakeLib.mk @@ -14,12 +14,12 @@ ifeq ($(DEBUG),1) $(info Bulding debug version) ODIR:=$(ODIR_BASE)/lib/debug CFLAGS?=-Wall -Wextra -O0 -g -fPIC $(VISIBILITY) - CXXFLAGS?=-Wall --std=c++0x -Wextra -O0 -g -fPIC $(VISIBILITY) $(CXXINCLUDES) + CXXFLAGS?=-Wall -Wextra -O0 -g -fPIC $(VISIBILITY) $(CXXINCLUDES) else # Release mode options ODIR:=$(ODIR_BASE)/lib/release CFLAGS?=-Wall -Wextra -O3 -fPIC $(VISIBILITY) - CXXFLAGS?=-Wall --std=c++0x -Wextra -O3 -fPIC $(VISIBILITY) $(CXXINCLUDES) + CXXFLAGS?=-Wall -Wextra -O3 -fPIC $(VISIBILITY) $(CXXINCLUDES) endif OBJ_NAMES= libnethogs.o packet.o connection.o process.o refresh.o decpcap.o inode2prog.o conninode.o devices.o diff --git a/libnethogs.cpp b/libnethogs.cpp index adbd5ef..97302e9 100644 --- a/libnethogs.cpp +++ b/libnethogs.cpp @@ -4,16 +4,12 @@ extern "C" } #include "nethogs.cpp" -#include #include -#include -#include -#include #include -#include #include #include #include +#include ////////////////////////////// extern ProcList * processes; @@ -22,12 +18,10 @@ extern Process * unknownudp; extern Process * unknownip; ////////////////////////////// -static std::shared_ptr monitor_thread_ptr; -static std::atomic_bool monitor_thread_run_flag(false); - //The self_pipe is used to interrupt the select() in the main loop static std::pair self_pipe = std::make_pair(-1, -1); +static bool monitor_run_flag = false; static NethogsMonitorCallback monitor_udpate_callback; typedef std::map NethogsAppUpdateMap; static NethogsAppUpdateMap monitor_update_data; @@ -57,7 +51,7 @@ static std::pair create_self_pipe() return std::make_pair(pfd[0], pfd[1]); } -static void wait_for_next_trigger() +static bool wait_for_next_trigger() { if( pc_loop_use_select ) { @@ -71,13 +65,20 @@ static void wait_for_next_trigger() FD_SET(fd, &pc_loop_fd_set); } timeval timeout = {monitor_refresh_delay, 0}; - select(nfds, &pc_loop_fd_set, 0, 0, &timeout); + if( select(nfds, &pc_loop_fd_set, 0, 0, &timeout) != -1 ) + { + if( FD_ISSET(self_pipe.first, &pc_loop_fd_set) ) + { + return false; + } + } } else { // If select() not possible, pause to prevent 100% usleep(1000); } + return true; } static int nethogsmonitor_init() @@ -178,7 +179,7 @@ static int nethogsmonitor_init() return NETHOGS_STATUS_OK; } -static void nethogsmonitor_handle_update() +static void nethogsmonitor_handle_update(NethogsMonitorCallback cb) { refreshconninode(); refreshcount++; @@ -205,16 +206,13 @@ static void nethogsmonitor_handle_update() if (DEBUG) std::cout << "PROC: Deleting process\n"; - if( monitor_udpate_callback ) + NethogsAppUpdateMap::iterator it = monitor_update_data.find(curproc->getVal()->pid); + if( it != monitor_update_data.end() ) { - NethogsAppUpdateMap::iterator it = monitor_update_data.find(curproc->getVal()->pid); - if( it != monitor_update_data.end() ) - { - NethogsMonitorUpdate& data = it->second; - data.action = NETHOGS_APP_ACTION_REMOVE; - monitor_udpate_callback(&data); - monitor_update_data.erase(curproc->getVal()->pid); - } + NethogsMonitorUpdate& data = it->second; + data.action = NETHOGS_APP_ACTION_REMOVE; + (*cb)(&data); + monitor_update_data.erase(curproc->getVal()->pid); } ProcList * todelete = curproc; @@ -244,38 +242,35 @@ static void nethogsmonitor_handle_update() curproc->getVal()->getkbps (&recv_kbs, &sent_kbs); curproc->getVal()->gettotal (&recv_bytes, &sent_bytes); - if( monitor_udpate_callback ) - { - //notify update - bool const new_data = (monitor_update_data.find(pid) == monitor_update_data.end()); - NethogsMonitorUpdate &data = monitor_update_data[pid]; - - bool data_change = false; - if( new_data ) - { - data_change = true; - memset(&data, 0, sizeof(data)); - data.pid = pid; - data.app_name = curproc->getVal()->name; - } - - data.device_name = curproc->getVal()->devicename; + //notify update + bool const new_data = (monitor_update_data.find(pid) == monitor_update_data.end()); + NethogsMonitorUpdate &data = monitor_update_data[pid]; - #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 = NETHOGS_APP_ACTION_SET; - monitor_udpate_callback(&data); - } + bool data_change = false; + if( new_data ) + { + data_change = true; + memset(&data, 0, sizeof(data)); + data.pid = pid; + data.app_name = curproc->getVal()->name; + } + + 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 = NETHOGS_APP_ACTION_SET; + (*cb)(&data); } //next @@ -285,13 +280,45 @@ static void nethogsmonitor_handle_update() } } -static void nethogsmonitor_threadproc() +static void nethogsmonitor_clean_up() { - fprintf(stderr, "Waiting for first packet to arrive (see sourceforge.net bug 1019381)\n"); + //clean up + handle * current_handle = handles; + while (current_handle != NULL) + { + pcap_close(current_handle->content->pcap_handle); + current_handle = current_handle->next; + } + + //close file descriptors + for(std::vector::const_iterator it=pc_loop_fd_list.begin(); + it != pc_loop_fd_list.end(); ++it) + { + close(*it); + } + + procclean(); +} + +int nethogsmonitor_loop(NethogsMonitorCallback cb) +{ + if( monitor_run_flag ) + { + return NETHOGS_STATUS_FAILURE; + } + + int return_value = nethogsmonitor_init(); + if( return_value != NETHOGS_STATUS_OK ) + { + return return_value; + } + + monitor_run_flag = true; + struct dpargs * userdata = (dpargs *) malloc (sizeof (struct dpargs)); // Main loop - while (monitor_thread_run_flag) + while (monitor_run_flag) { bool packets_read = false; @@ -320,50 +347,25 @@ static void nethogsmonitor_threadproc() if( monitor_last_refresh_time + monitor_refresh_delay <= now ) { monitor_last_refresh_time = now; - nethogsmonitor_handle_update(); + nethogsmonitor_handle_update(cb); } if (!packets_read) { - wait_for_next_trigger(); + if( !wait_for_next_trigger() ) + { + break; + } } } - handle * current_handle = handles; - while (current_handle != NULL) - { - pcap_close(current_handle->content->pcap_handle); - current_handle = current_handle->next; - } + nethogsmonitor_clean_up(); + + return NETHOGS_STATUS_OK; } -void nethogsmonitor_register_callback(NethogsMonitorCallback cb) +void nethogsmonitor_breakloop() { - if( !monitor_thread_run_flag ) - { - monitor_udpate_callback = cb; - } -} - -int nethogsmonitor_start() -{ - bool expected = false; - int ret = NETHOGS_STATUS_OK; - if( monitor_thread_run_flag.compare_exchange_strong(expected, true) ) - { - ret = nethogsmonitor_init(); - monitor_thread_ptr = std::make_shared(&nethogsmonitor_threadproc); - } - return ret; -} - -void nethogsmonitor_stop() -{ - bool expected = true; - if( monitor_thread_run_flag.compare_exchange_strong(expected, false) ) - { - write(self_pipe.second, "x", 1); - monitor_thread_ptr->join(); - monitor_udpate_callback = nullptr; - } + monitor_run_flag = false; + write(self_pipe.second, "x", 1); } diff --git a/libnethogs.h b/libnethogs.h index 674e5a5..2479d8c 100644 --- a/libnethogs.h +++ b/libnethogs.h @@ -33,15 +33,19 @@ typedef struct NethogsMonitorUpdate typedef void(*NethogsMonitorCallback)(NethogsMonitorUpdate const*); -//register async callback to receive updates -//have to be called before start -NETHOGS_DSO_VISIBLE void nethogsmonitor_register_callback(NethogsMonitorCallback); - -//start the monitor (return one of the NETHOGS_STATUS above) -NETHOGS_DSO_VISIBLE int nethogsmonitor_start(); +/** + * @brief Enter the process monitoring loop and reports updates using the + * callback provided as parameter. + * This call will block until nethogsmonitor_stop is called or a failure occurs. + * @param cb A pointer to a callback function following the NethogsMonitorCallback definition + */ -//stop the monitor -NETHOGS_DSO_VISIBLE void nethogsmonitor_stop(); +NETHOGS_DSO_VISIBLE int nethogsmonitor_loop(NethogsMonitorCallback cb); + +/** + * @brief Makes the call to nethogsmonitor_loop return. + */ +NETHOGS_DSO_VISIBLE void nethogsmonitor_breakloop(); #undef NETHOGS_DSO_VISIBLE #undef NETHOGS_DSO_HIDDEN