removed multithreading and c++11 and used a pcap_loop-like api

This commit is contained in:
Mohamed Boussaffa
2016-03-10 19:21:29 +08:00
parent 81218523c8
commit 0c6fbfe10c
3 changed files with 106 additions and 100 deletions

View File

@@ -14,12 +14,12 @@ ifeq ($(DEBUG),1)
$(info Bulding debug version) $(info Bulding debug version)
ODIR:=$(ODIR_BASE)/lib/debug ODIR:=$(ODIR_BASE)/lib/debug
CFLAGS?=-Wall -Wextra -O0 -g -fPIC $(VISIBILITY) 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 else
# Release mode options # Release mode options
ODIR:=$(ODIR_BASE)/lib/release ODIR:=$(ODIR_BASE)/lib/release
CFLAGS?=-Wall -Wextra -O3 -fPIC $(VISIBILITY) CFLAGS?=-Wall -Wextra -O3 -fPIC $(VISIBILITY)
CXXFLAGS?=-Wall --std=c++0x -Wextra -O3 -fPIC $(VISIBILITY) $(CXXINCLUDES) CXXFLAGS?=-Wall -Wextra -O3 -fPIC $(VISIBILITY) $(CXXINCLUDES)
endif endif
OBJ_NAMES= libnethogs.o packet.o connection.o process.o refresh.o decpcap.o inode2prog.o conninode.o devices.o OBJ_NAMES= libnethogs.o packet.o connection.o process.o refresh.o decpcap.o inode2prog.o conninode.o devices.o

View File

@@ -4,16 +4,12 @@ extern "C"
} }
#include "nethogs.cpp" #include "nethogs.cpp"
#include <pthread.h>
#include <iostream> #include <iostream>
#include <mutex>
#include <condition_variable>
#include <atomic>
#include <memory> #include <memory>
#include <thread>
#include <map> #include <map>
#include <vector> #include <vector>
#include <fcntl.h> #include <fcntl.h>
#include <errno.h>
////////////////////////////// //////////////////////////////
extern ProcList * processes; extern ProcList * processes;
@@ -22,12 +18,10 @@ extern Process * unknownudp;
extern Process * unknownip; extern Process * unknownip;
////////////////////////////// //////////////////////////////
static std::shared_ptr<std::thread> 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 //The self_pipe is used to interrupt the select() in the main loop
static std::pair<int,int> self_pipe = std::make_pair(-1, -1); static std::pair<int,int> self_pipe = std::make_pair(-1, -1);
static bool monitor_run_flag = false;
static NethogsMonitorCallback monitor_udpate_callback; static NethogsMonitorCallback monitor_udpate_callback;
typedef std::map<int, NethogsMonitorUpdate> NethogsAppUpdateMap; typedef std::map<int, NethogsMonitorUpdate> NethogsAppUpdateMap;
static NethogsAppUpdateMap monitor_update_data; static NethogsAppUpdateMap monitor_update_data;
@@ -57,7 +51,7 @@ static std::pair<int, int> create_self_pipe()
return std::make_pair(pfd[0], pfd[1]); 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 ) if( pc_loop_use_select )
{ {
@@ -71,13 +65,20 @@ static void wait_for_next_trigger()
FD_SET(fd, &pc_loop_fd_set); FD_SET(fd, &pc_loop_fd_set);
} }
timeval timeout = {monitor_refresh_delay, 0}; 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 else
{ {
// If select() not possible, pause to prevent 100% // If select() not possible, pause to prevent 100%
usleep(1000); usleep(1000);
} }
return true;
} }
static int nethogsmonitor_init() static int nethogsmonitor_init()
@@ -178,7 +179,7 @@ static int nethogsmonitor_init()
return NETHOGS_STATUS_OK; return NETHOGS_STATUS_OK;
} }
static void nethogsmonitor_handle_update() static void nethogsmonitor_handle_update(NethogsMonitorCallback cb)
{ {
refreshconninode(); refreshconninode();
refreshcount++; refreshcount++;
@@ -205,17 +206,14 @@ static void nethogsmonitor_handle_update()
if (DEBUG) if (DEBUG)
std::cout << "PROC: Deleting process\n"; std::cout << "PROC: Deleting process\n";
if( monitor_udpate_callback )
{
NethogsAppUpdateMap::iterator it = monitor_update_data.find(curproc->getVal()->pid); NethogsAppUpdateMap::iterator it = monitor_update_data.find(curproc->getVal()->pid);
if( it != monitor_update_data.end() ) if( it != monitor_update_data.end() )
{ {
NethogsMonitorUpdate& data = it->second; NethogsMonitorUpdate& data = it->second;
data.action = NETHOGS_APP_ACTION_REMOVE; data.action = NETHOGS_APP_ACTION_REMOVE;
monitor_udpate_callback(&data); (*cb)(&data);
monitor_update_data.erase(curproc->getVal()->pid); monitor_update_data.erase(curproc->getVal()->pid);
} }
}
ProcList * todelete = curproc; ProcList * todelete = curproc;
Process * p_todelete = curproc->getVal(); Process * p_todelete = curproc->getVal();
@@ -244,8 +242,6 @@ static void nethogsmonitor_handle_update()
curproc->getVal()->getkbps (&recv_kbs, &sent_kbs); curproc->getVal()->getkbps (&recv_kbs, &sent_kbs);
curproc->getVal()->gettotal (&recv_bytes, &sent_bytes); curproc->getVal()->gettotal (&recv_bytes, &sent_bytes);
if( monitor_udpate_callback )
{
//notify update //notify update
bool const new_data = (monitor_update_data.find(pid) == monitor_update_data.end()); bool const new_data = (monitor_update_data.find(pid) == monitor_update_data.end());
NethogsMonitorUpdate &data = monitor_update_data[pid]; NethogsMonitorUpdate &data = monitor_update_data[pid];
@@ -274,8 +270,7 @@ static void nethogsmonitor_handle_update()
if( data_change ) if( data_change )
{ {
data.action = NETHOGS_APP_ACTION_SET; data.action = NETHOGS_APP_ACTION_SET;
monitor_udpate_callback(&data); (*cb)(&data);
}
} }
//next //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<int>::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)); struct dpargs * userdata = (dpargs *) malloc (sizeof (struct dpargs));
// Main loop // Main loop
while (monitor_thread_run_flag) while (monitor_run_flag)
{ {
bool packets_read = false; bool packets_read = false;
@@ -320,50 +347,25 @@ static void nethogsmonitor_threadproc()
if( monitor_last_refresh_time + monitor_refresh_delay <= now ) if( monitor_last_refresh_time + monitor_refresh_delay <= now )
{ {
monitor_last_refresh_time = now; monitor_last_refresh_time = now;
nethogsmonitor_handle_update(); nethogsmonitor_handle_update(cb);
} }
if (!packets_read) if (!packets_read)
{ {
wait_for_next_trigger(); if( !wait_for_next_trigger() )
{
break;
}
} }
} }
handle * current_handle = handles; nethogsmonitor_clean_up();
while (current_handle != NULL)
{ return NETHOGS_STATUS_OK;
pcap_close(current_handle->content->pcap_handle);
current_handle = current_handle->next;
}
} }
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<std::thread>(&nethogsmonitor_threadproc);
}
return ret;
}
void nethogsmonitor_stop()
{
bool expected = true;
if( monitor_thread_run_flag.compare_exchange_strong(expected, false) )
{ {
monitor_run_flag = false;
write(self_pipe.second, "x", 1); write(self_pipe.second, "x", 1);
monitor_thread_ptr->join();
monitor_udpate_callback = nullptr;
}
} }

View File

@@ -33,15 +33,19 @@ typedef struct NethogsMonitorUpdate
typedef void(*NethogsMonitorCallback)(NethogsMonitorUpdate const*); typedef void(*NethogsMonitorCallback)(NethogsMonitorUpdate const*);
//register async callback to receive updates /**
//have to be called before start * @brief Enter the process monitoring loop and reports updates using the
NETHOGS_DSO_VISIBLE void nethogsmonitor_register_callback(NethogsMonitorCallback); * 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
*/
//start the monitor (return one of the NETHOGS_STATUS above) NETHOGS_DSO_VISIBLE int nethogsmonitor_loop(NethogsMonitorCallback cb);
NETHOGS_DSO_VISIBLE int nethogsmonitor_start();
//stop the monitor /**
NETHOGS_DSO_VISIBLE void nethogsmonitor_stop(); * @brief Makes the call to nethogsmonitor_loop return.
*/
NETHOGS_DSO_VISIBLE void nethogsmonitor_breakloop();
#undef NETHOGS_DSO_VISIBLE #undef NETHOGS_DSO_VISIBLE
#undef NETHOGS_DSO_HIDDEN #undef NETHOGS_DSO_HIDDEN