exposing c interface instead of c++, for more compatibility.
This commit is contained in:
169
libnethogs.cpp
169
libnethogs.cpp
@@ -1,6 +1,9 @@
|
|||||||
#include "libnethogs.h"
|
extern "C"
|
||||||
#include "nethogs.cpp"
|
{
|
||||||
|
#include "libnethogs.h"
|
||||||
|
}
|
||||||
|
|
||||||
|
#include "nethogs.cpp"
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
@@ -23,27 +26,30 @@ static std::atomic_bool monitor_thread_run_flag(false);
|
|||||||
std::mutex monitor_exit_event_mutex;
|
std::mutex monitor_exit_event_mutex;
|
||||||
std::condition_variable monitor_exit_event;
|
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 NethogsAppUpdateMap monitor_update_data;
|
||||||
|
|
||||||
static int monitor_refresh_delay = 1;
|
static int monitor_refresh_delay = 1;
|
||||||
static int monitor_pc_dispatch_delay_ms = 50;
|
static int monitor_pc_dispatch_delay_ms = 50;
|
||||||
static time_t monitor_last_refresh_time = 0;
|
static time_t monitor_last_refresh_time = 0;
|
||||||
|
|
||||||
void NethogsMonitor::threadProc()
|
static handle * handles = NULL;
|
||||||
|
|
||||||
|
static bool nethogsmonitor_init()
|
||||||
{
|
{
|
||||||
|
bool success = true;
|
||||||
|
|
||||||
process_init();
|
process_init();
|
||||||
|
|
||||||
device * devices = get_default_devices();
|
device * devices = get_default_devices();
|
||||||
if ( devices == NULL )
|
if ( devices == NULL )
|
||||||
{
|
{
|
||||||
std::cerr << "Not devices to monitor" << std::endl;
|
std::cerr << "Not devices to monitor" << std::endl;
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
handle * handles = NULL;
|
|
||||||
device * current_dev = devices;
|
device * current_dev = devices;
|
||||||
|
|
||||||
bool promiscuous = false;
|
bool promiscuous = false;
|
||||||
@@ -53,6 +59,7 @@ void NethogsMonitor::threadProc()
|
|||||||
if( !getLocal(current_dev->name, false) )
|
if( !getLocal(current_dev->name, false) )
|
||||||
{
|
{
|
||||||
std::cerr << "getifaddrs failed while establishing local IP." << std::endl;
|
std::cerr << "getifaddrs failed while establishing local IP." << std::endl;
|
||||||
|
success = false;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -79,6 +86,7 @@ void NethogsMonitor::threadProc()
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
success = false;
|
||||||
fprintf(stderr, "ERROR: opening handler for device %s: %s\n",
|
fprintf(stderr, "ERROR: opening handler for device %s: %s\n",
|
||||||
current_dev->name, strerror(errno));
|
current_dev->name, strerror(errno));
|
||||||
}
|
}
|
||||||
@@ -86,49 +94,10 @@ void NethogsMonitor::threadProc()
|
|||||||
current_dev = current_dev->next;
|
current_dev = current_dev->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
fprintf(stderr, "Waiting for first packet to arrive (see sourceforge.net bug 1019381)\n");
|
return success;
|
||||||
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));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void NethogsMonitor::handleUpdate()
|
static void nethogsmonitor_handle_update()
|
||||||
{
|
{
|
||||||
refreshconninode();
|
refreshconninode();
|
||||||
refreshcount++;
|
refreshcount++;
|
||||||
@@ -160,9 +129,9 @@ void NethogsMonitor::handleUpdate()
|
|||||||
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() )
|
||||||
{
|
{
|
||||||
NethogsAppUpdate &data = it->second;
|
NethogsMonitorUpdate& data = it->second;
|
||||||
data.action = NethogsAppUpdate::Remove;
|
data.action = NETHOGS_APP_ACTION_REMOVE;
|
||||||
monitor_udpate_callback(data);
|
monitor_udpate_callback(&data);
|
||||||
monitor_update_data.erase(curproc->getVal()->pid);
|
monitor_update_data.erase(curproc->getVal()->pid);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -185,7 +154,8 @@ void NethogsMonitor::handleUpdate()
|
|||||||
}
|
}
|
||||||
else
|
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 sent_bytes;
|
||||||
u_int32_t recv_bytes;
|
u_int32_t recv_bytes;
|
||||||
float sent_kbs;
|
float sent_kbs;
|
||||||
@@ -196,30 +166,34 @@ void NethogsMonitor::handleUpdate()
|
|||||||
if( monitor_udpate_callback )
|
if( monitor_udpate_callback )
|
||||||
{
|
{
|
||||||
//notify update
|
//notify update
|
||||||
bool const new_process = (monitor_update_data.find(pid) == monitor_update_data.end());
|
bool const new_data = (monitor_update_data.find(pid) == monitor_update_data.end());
|
||||||
NethogsAppUpdate &data = monitor_update_data[pid];
|
NethogsMonitorUpdate &data = monitor_update_data[pid];
|
||||||
|
|
||||||
bool data_change = false;
|
bool data_change = false;
|
||||||
|
if( new_data )
|
||||||
#define NHM_UPDATE_ONE_FIELD(TO,FROM) if((TO)!=(FROM)) { TO = FROM; data_change = true; }
|
|
||||||
if( new_process )
|
|
||||||
{
|
{
|
||||||
NHM_UPDATE_ONE_FIELD( data.pid, pid )
|
data_change = true;
|
||||||
NHM_UPDATE_ONE_FIELD( data.app_name, curproc->getVal()->name )
|
memset(&data, 0, sizeof(data));
|
||||||
|
data.pid = pid;
|
||||||
|
data.app_name = curproc->getVal()->name;
|
||||||
}
|
}
|
||||||
|
|
||||||
NHM_UPDATE_ONE_FIELD( data.uid, curproc->getVal()->getUid() )
|
data.device_name = curproc->getVal()->devicename;
|
||||||
NHM_UPDATE_ONE_FIELD( 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.sent_bytes, sent_bytes )
|
||||||
NHM_UPDATE_ONE_FIELD( data.recv_bytes, recv_bytes )
|
NHM_UPDATE_ONE_FIELD( data.recv_bytes, recv_bytes )
|
||||||
NHM_UPDATE_ONE_FIELD( data.sent_kbs, sent_kbs )
|
NHM_UPDATE_ONE_FIELD( data.sent_kbs, sent_kbs )
|
||||||
NHM_UPDATE_ONE_FIELD( data.recv_kbs, recv_kbs )
|
NHM_UPDATE_ONE_FIELD( data.recv_kbs, recv_kbs )
|
||||||
|
|
||||||
#undef NHM_UPDATE_ONE_FIELD
|
#undef NHM_UPDATE_ONE_FIELD
|
||||||
|
|
||||||
if( data_change )
|
if( data_change )
|
||||||
{
|
{
|
||||||
data.action = NethogsAppUpdate::Set;
|
data.action = NETHOGS_APP_ACTION_SET;
|
||||||
monitor_udpate_callback(data);
|
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 )
|
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;
|
monitor_refresh_delay = seconds;
|
||||||
}
|
}
|
||||||
|
|
||||||
void NethogsMonitor::setPcapDispatchDelay(int milliseconds)
|
void nethogsmonitor_set_pcap_dispatch_delay(int milliseconds)
|
||||||
{
|
{
|
||||||
monitor_pc_dispatch_delay_ms = milliseconds;
|
monitor_pc_dispatch_delay_ms = milliseconds;
|
||||||
}
|
}
|
||||||
|
|
||||||
void NethogsMonitor::start()
|
bool nethogsmonitor_start()
|
||||||
{
|
{
|
||||||
bool expected = false;
|
bool expected = false;
|
||||||
|
bool success = true;
|
||||||
if( monitor_thread_run_flag.compare_exchange_strong(expected, 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;
|
bool expected = true;
|
||||||
if( monitor_thread_run_flag.compare_exchange_strong(expected, false) )
|
if( monitor_thread_run_flag.compare_exchange_strong(expected, false) )
|
||||||
|
|||||||
58
libnethogs.h
58
libnethogs.h
@@ -2,55 +2,43 @@
|
|||||||
#define LIBNETHOGS_H_
|
#define LIBNETHOGS_H_
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <inttypes.h>
|
#include <stdbool.h>
|
||||||
#include <string>
|
|
||||||
|
|
||||||
#define NETHOGS_DSO_VISIBLE __attribute__ ((visibility ("default")))
|
#define NETHOGS_DSO_VISIBLE __attribute__ ((visibility ("default")))
|
||||||
#define NETHOGS_DSO_HIDDEN __attribute__ ((visibility ("hidden")))
|
#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:
|
int action;
|
||||||
enum Action {Set, Remove};
|
|
||||||
NethogsAppUpdate()
|
|
||||||
: action(Set), pid(0), uid(0), sent_kbs(0), recv_kbs(0)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
Action action;
|
|
||||||
int pid;
|
int pid;
|
||||||
uint32_t uid;
|
uint32_t uid;
|
||||||
std::string app_name;
|
const char* app_name;
|
||||||
std::string device_name;
|
const char* device_name;
|
||||||
uint32_t sent_bytes;
|
uint32_t sent_bytes;
|
||||||
uint32_t recv_bytes;
|
uint32_t recv_bytes;
|
||||||
float sent_kbs;
|
float sent_kbs;
|
||||||
float recv_kbs;
|
float recv_kbs;
|
||||||
};
|
} NethogsMonitorUpdate;
|
||||||
|
|
||||||
class NETHOGS_DSO_VISIBLE NethogsMonitor
|
typedef void(*NethogsMonitorCallback)(NethogsMonitorUpdate const*);
|
||||||
{
|
|
||||||
NethogsMonitor();
|
|
||||||
public:
|
|
||||||
typedef void(*Callback)(NethogsAppUpdate const&);
|
|
||||||
|
|
||||||
//register async callback to receive updates
|
//register async callback to receive updates
|
||||||
//have to be called before start
|
//have to be called before start
|
||||||
static void registerUpdateCallback(Callback const& cb);
|
NETHOGS_DSO_VISIBLE void nethogsmonitor_register_callback(NethogsMonitorCallback);
|
||||||
|
|
||||||
//start the monitor
|
|
||||||
static void start();
|
|
||||||
|
|
||||||
//stop the monitor
|
//start the monitor
|
||||||
static void stop();
|
NETHOGS_DSO_VISIBLE bool nethogsmonitor_start();
|
||||||
|
|
||||||
//tuning functions
|
//stop the monitor
|
||||||
static void setRefreshDelay(int seconds);
|
NETHOGS_DSO_VISIBLE void nethogsmonitor_stop();
|
||||||
static void setPcapDispatchDelay(int milliseconds);
|
|
||||||
|
//tuning functions
|
||||||
private:
|
NETHOGS_DSO_VISIBLE void nethogsmonitor_set_refresh_delay(int seconds);
|
||||||
static void threadProc();
|
NETHOGS_DSO_VISIBLE void nethogsmonitor_set_pcap_dispatch_delay(int milliseconds);
|
||||||
static void handleUpdate();
|
|
||||||
};
|
|
||||||
|
|
||||||
#undef NETHOGS_DSO_VISIBLE
|
#undef NETHOGS_DSO_VISIBLE
|
||||||
#undef NETHOGS_DSO_HIDDEN
|
#undef NETHOGS_DSO_HIDDEN
|
||||||
|
|||||||
Reference in New Issue
Block a user