exposing c interface instead of c++, for more compatibility.
This commit is contained in:
167
libnethogs.cpp
167
libnethogs.cpp
@@ -1,6 +1,9 @@
|
||||
#include "libnethogs.h"
|
||||
#include "nethogs.cpp"
|
||||
extern "C"
|
||||
{
|
||||
#include "libnethogs.h"
|
||||
}
|
||||
|
||||
#include "nethogs.cpp"
|
||||
#include <pthread.h>
|
||||
#include <iostream>
|
||||
#include <mutex>
|
||||
@@ -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<int, NethogsAppUpdate> NethogsAppUpdateMap;
|
||||
typedef std::map<int, NethogsMonitorUpdate> 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<std::mutex> 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 )
|
||||
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<std::mutex> 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<std::thread>(&NethogsMonitor::threadProc);
|
||||
if( !nethogsmonitor_init() )
|
||||
{
|
||||
success = false;
|
||||
}
|
||||
monitor_thread_ptr = std::make_shared<std::thread>(&nethogsmonitor_threadproc);
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
void NethogsMonitor::stop()
|
||||
void nethogsmonitor_stop()
|
||||
{
|
||||
bool expected = true;
|
||||
if( monitor_thread_run_flag.compare_exchange_strong(expected, false) )
|
||||
|
||||
52
libnethogs.h
52
libnethogs.h
@@ -2,55 +2,43 @@
|
||||
#define LIBNETHOGS_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <inttypes.h>
|
||||
#include <string>
|
||||
#include <stdbool.h>
|
||||
|
||||
#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);
|
||||
//register async callback to receive updates
|
||||
//have to be called before start
|
||||
NETHOGS_DSO_VISIBLE void nethogsmonitor_register_callback(NethogsMonitorCallback);
|
||||
|
||||
//start the monitor
|
||||
static void start();
|
||||
//start the monitor
|
||||
NETHOGS_DSO_VISIBLE bool nethogsmonitor_start();
|
||||
|
||||
//stop the monitor
|
||||
static void stop();
|
||||
//stop the monitor
|
||||
NETHOGS_DSO_VISIBLE void nethogsmonitor_stop();
|
||||
|
||||
//tuning functions
|
||||
static void setRefreshDelay(int seconds);
|
||||
static void setPcapDispatchDelay(int milliseconds);
|
||||
//tuning functions
|
||||
NETHOGS_DSO_VISIBLE void nethogsmonitor_set_refresh_delay(int seconds);
|
||||
NETHOGS_DSO_VISIBLE void nethogsmonitor_set_pcap_dispatch_delay(int milliseconds);
|
||||
|
||||
private:
|
||||
static void threadProc();
|
||||
static void handleUpdate();
|
||||
};
|
||||
|
||||
#undef NETHOGS_DSO_VISIBLE
|
||||
#undef NETHOGS_DSO_HIDDEN
|
||||
|
||||
Reference in New Issue
Block a user