2
.gitignore
vendored
2
.gitignore
vendored
@@ -8,3 +8,5 @@ nethogs.project
|
|||||||
libnethogs.so.*
|
libnethogs.so.*
|
||||||
libnethogs.a
|
libnethogs.a
|
||||||
results/
|
results/
|
||||||
|
build/
|
||||||
|
nethogs.egg-info
|
||||||
|
|||||||
@@ -1,4 +0,0 @@
|
|||||||
This folder contains user-contributed scripts.
|
|
||||||
|
|
||||||
The Nethogs project does not make claims about the quality of the scripts, maintains
|
|
||||||
them in any way, or necessarily think they're a good idea in the first place :).
|
|
||||||
8
pyproject.toml
Normal file
8
pyproject.toml
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
[build-system]
|
||||||
|
requires = [
|
||||||
|
"setuptools>=42",
|
||||||
|
"wheel",
|
||||||
|
"pybind11>=2.8.0",
|
||||||
|
]
|
||||||
|
|
||||||
|
build-backend = "setuptools.build_meta"
|
||||||
49
python/README.md
Normal file
49
python/README.md
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
## Python stuff
|
||||||
|
This directory contains the code that wraps `libnethogs` into a python module.
|
||||||
|
|
||||||
|
### To build + install
|
||||||
|
Install dependencies:
|
||||||
|
``` bash
|
||||||
|
apt-get install build-essential libncurses5-dev libpcap-dev pybind11-dev
|
||||||
|
```
|
||||||
|
All the code is compiled through the [pybind11 setuptools building system](https://pybind11.readthedocs.io/en/stable/compiling.html). So to build and install you just need to do:
|
||||||
|
``` bash
|
||||||
|
### if you have the code cloned locally
|
||||||
|
pip install .
|
||||||
|
```
|
||||||
|
Or:
|
||||||
|
``` bash
|
||||||
|
### if you can't bother to clone the repo yourself
|
||||||
|
pip install git+https://github.com/raboof/nethogs.git
|
||||||
|
```
|
||||||
|
|
||||||
|
### To use
|
||||||
|
``` python
|
||||||
|
import nethogs
|
||||||
|
import threading
|
||||||
|
|
||||||
|
def callback(action: int, record: nethogs.NethogsMonitorRecord) -> None:
|
||||||
|
do_whatever_with_record(record)
|
||||||
|
return
|
||||||
|
|
||||||
|
th = threading.Thread(target=nethogs.nethogsmonitor_loop, args(callback, filter, to_ms))
|
||||||
|
th.start()
|
||||||
|
do_whatever_you_need_to_do()
|
||||||
|
nethogs.nethogsmonitor_breakloop()
|
||||||
|
th.join()
|
||||||
|
```
|
||||||
|
|
||||||
|
### Caveats
|
||||||
|
- **Ideally this should not be run in the main thread**, stopping the nethogsmonitor_loop with a SIGINT or SIGTERM is a bit hacky and could break things.
|
||||||
|
- Only one instance of the loop can be run at a time, callbacks would get completely messed up if more than one is run. I believe nethogs only allows one at a time anyways.
|
||||||
|
- There is no way of setting pidsToWatch, but it is not difficult to implement if anyone wants to do it :)
|
||||||
|
- The package version is set in setup.py using the script determineVersion.sh, but it is very hacky as a PEP compatible string is needed. Something stronger should be implemented, ideally using the regex module.
|
||||||
|
|
||||||
|
## Extra stuff
|
||||||
|
The script `python-wrapper.py` used to be in a contrib directory. This script loads the libnethogs library directly, which you shouldn't really do anyways. The way of using nethogs in python by the `python-wrapper.py` is now deprecated. I'm just leaving it here to not destroy the previous contribution. This is the original comment that **raboof** made about the `python-wrapper.py` and the `contrib` directory:
|
||||||
|
```
|
||||||
|
This folder contains user-contributed scripts.
|
||||||
|
|
||||||
|
The Nethogs project does not make claims about the quality of the scripts, maintains
|
||||||
|
them in any way, or necessarily think they're a good idea in the first place :).
|
||||||
|
```
|
||||||
98
python/bindings.cpp
Normal file
98
python/bindings.cpp
Normal file
@@ -0,0 +1,98 @@
|
|||||||
|
#include <pybind11/functional.h>
|
||||||
|
#include <pybind11/pybind11.h>
|
||||||
|
#include <pybind11/stl.h>
|
||||||
|
#include <set>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
#include "libnethogs.h"
|
||||||
|
|
||||||
|
namespace py = pybind11;
|
||||||
|
|
||||||
|
//--- for some reason this is a global defined in main.cpp
|
||||||
|
std::set<pid_t> pidsToWatch;
|
||||||
|
|
||||||
|
//--- hacky way to get callbacks working and handle signals
|
||||||
|
std::function<void(int, NethogsMonitorRecord const *)> empty_callback;
|
||||||
|
std::function<void(int, NethogsMonitorRecord const *)> loop_callback;
|
||||||
|
void loop_callback_wrapper(
|
||||||
|
int action,
|
||||||
|
NethogsMonitorRecord const *record)
|
||||||
|
{
|
||||||
|
py::gil_scoped_acquire acquire;
|
||||||
|
if (PyErr_CheckSignals() != 0) {
|
||||||
|
nethogsmonitor_breakloop();
|
||||||
|
PyErr_Clear();
|
||||||
|
}
|
||||||
|
else if (loop_callback) {
|
||||||
|
loop_callback(action, record);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int nethogsmonitor_loop_py(
|
||||||
|
std::function<void(int, NethogsMonitorRecord const *)> &cb,
|
||||||
|
char *filter,
|
||||||
|
int to_ms)
|
||||||
|
{
|
||||||
|
int retval;
|
||||||
|
loop_callback = cb;
|
||||||
|
{
|
||||||
|
py::gil_scoped_release release;
|
||||||
|
retval = nethogsmonitor_loop(loop_callback_wrapper, filter, to_ms);
|
||||||
|
}
|
||||||
|
loop_callback = empty_callback;
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
int nethogsmonitor_loop_devices_py(
|
||||||
|
std::function<void(int, NethogsMonitorRecord const *)> &cb,
|
||||||
|
char *filter,
|
||||||
|
std::vector<std::string> __devicenames,
|
||||||
|
bool all,
|
||||||
|
int to_ms)
|
||||||
|
{
|
||||||
|
// this is ok because we only use the vector here
|
||||||
|
std::vector<char*> _devicenames;
|
||||||
|
for (auto _dn : __devicenames) _devicenames.push_back(const_cast<char*>(_dn.c_str()));
|
||||||
|
int devc = _devicenames.size();
|
||||||
|
char **devicenames = (_devicenames.empty()) ? NULL : _devicenames.data();
|
||||||
|
|
||||||
|
int retval;
|
||||||
|
loop_callback = cb;
|
||||||
|
{
|
||||||
|
py::gil_scoped_release release;
|
||||||
|
retval = nethogsmonitor_loop_devices(loop_callback_wrapper, filter, devc, devicenames, all, to_ms);
|
||||||
|
}
|
||||||
|
loop_callback = empty_callback;
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
//--- python module binding
|
||||||
|
PYBIND11_MODULE(nethogs, m) {
|
||||||
|
py::class_<NethogsMonitorRecord>(m, "NethogsMonitorRecord")
|
||||||
|
.def_readwrite("record_id", &NethogsMonitorRecord::record_id)
|
||||||
|
.def_readwrite("name", &NethogsMonitorRecord::name)
|
||||||
|
.def_readwrite("pid", &NethogsMonitorRecord::pid)
|
||||||
|
.def_readwrite("uid", &NethogsMonitorRecord::uid)
|
||||||
|
.def_readwrite("device_name", &NethogsMonitorRecord::device_name)
|
||||||
|
.def_readwrite("sent_bytes", &NethogsMonitorRecord::sent_bytes)
|
||||||
|
.def_readwrite("recv_bytes", &NethogsMonitorRecord::recv_bytes)
|
||||||
|
.def_readwrite("sent_kbs", &NethogsMonitorRecord::sent_kbs)
|
||||||
|
.def_readwrite("recv_kbs", &NethogsMonitorRecord::recv_kbs);
|
||||||
|
|
||||||
|
m.def("nethogsmonitor_loop", &nethogsmonitor_loop_py, R"pbdoc(
|
||||||
|
Nethogs monitor loop
|
||||||
|
)pbdoc");
|
||||||
|
m.def("nethogsmonitor_loop_devices", &nethogsmonitor_loop_devices_py, R"pbdoc(
|
||||||
|
Nethogs monitor loop
|
||||||
|
)pbdoc");
|
||||||
|
m.def("nethogsmonitor_breakloop", &nethogsmonitor_breakloop, R"pbdoc(
|
||||||
|
Nethogs monitor loop break
|
||||||
|
)pbdoc");
|
||||||
|
|
||||||
|
#ifdef VERSION
|
||||||
|
m.attr("__version__") = VERSION;
|
||||||
|
#else
|
||||||
|
m.attr("__version__") = "unknown";
|
||||||
|
#endif
|
||||||
|
|
||||||
|
}
|
||||||
63
setup.py
Normal file
63
setup.py
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
import glob
|
||||||
|
import subprocess
|
||||||
|
import sys
|
||||||
|
|
||||||
|
from pybind11 import get_cmake_dir
|
||||||
|
# Available at setup time due to pyproject.toml
|
||||||
|
from pybind11.setup_helpers import Pybind11Extension, build_ext
|
||||||
|
from setuptools import setup
|
||||||
|
|
||||||
|
_version_info = subprocess.run(['bash', "./determineVersion.sh"], stdout=subprocess.PIPE)
|
||||||
|
__version__ = _version_info.stdout.decode("utf-8").rstrip("\n").split("-")[0] if _version_info else "0.0.0"
|
||||||
|
|
||||||
|
OBJS = [
|
||||||
|
"python/bindings.cpp",
|
||||||
|
"src/libnethogs.cpp",
|
||||||
|
"src/packet.cpp",
|
||||||
|
"src/connection.cpp",
|
||||||
|
"src/process.cpp",
|
||||||
|
"src/decpcap.c",
|
||||||
|
"src/inode2prog.cpp",
|
||||||
|
"src/conninode.cpp",
|
||||||
|
"src/devices.cpp"
|
||||||
|
]
|
||||||
|
|
||||||
|
FLAGS = [
|
||||||
|
"-Wall",
|
||||||
|
"-Wextra",
|
||||||
|
"-Wno-missing-field-initializers",
|
||||||
|
"--std=c++0x",
|
||||||
|
"-O3",
|
||||||
|
"-fPIC",
|
||||||
|
'-DVERSION="{}"'.format(__version__)
|
||||||
|
]
|
||||||
|
# The main interface is through Pybind11Extension.
|
||||||
|
# * You can add cxx_std=11/14/17, and then build_ext can be removed.
|
||||||
|
# * You can set include_pybind11=false to add the include directory yourself,
|
||||||
|
# say from a submodule.
|
||||||
|
#
|
||||||
|
# Note:
|
||||||
|
# Sort input source files if you glob sources to ensure bit-for-bit
|
||||||
|
# reproducible builds (https://github.com/pybind/python_example/pull/53)
|
||||||
|
|
||||||
|
ext_modules = [
|
||||||
|
Pybind11Extension(
|
||||||
|
"nethogs",
|
||||||
|
sources = OBJS,
|
||||||
|
include_dirs = ["src/"],
|
||||||
|
extra_compile_args = FLAGS,
|
||||||
|
libraries = ["pcap"]
|
||||||
|
),
|
||||||
|
]
|
||||||
|
|
||||||
|
setup(
|
||||||
|
name="nethogs",
|
||||||
|
version=__version__,
|
||||||
|
author="raboof",
|
||||||
|
url="https://github.com/raboof/nethogs",
|
||||||
|
description="Nethogs python bindings",
|
||||||
|
ext_modules=ext_modules,
|
||||||
|
cmdclass={"build_ext": build_ext},
|
||||||
|
zip_safe=False,
|
||||||
|
python_requires=">=3.6",
|
||||||
|
)
|
||||||
@@ -268,7 +268,7 @@ Process *getProcess(unsigned long inode, const char *devicename) {
|
|||||||
if (proc != NULL)
|
if (proc != NULL)
|
||||||
return proc;
|
return proc;
|
||||||
|
|
||||||
if ( !(pidsToWatch.empty()) && pidsToWatch.find(node->pid) == pidsToWatch.end() ) {
|
if ( !(pidsToWatch.empty()) && pidsToWatch.find(node->pid) == pidsToWatch.end() ) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -440,4 +440,3 @@ void remove_timed_out_processes() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void garbage_collect_processes() { garbage_collect_inodeproc(); }
|
void garbage_collect_processes() { garbage_collect_inodeproc(); }
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user