Skip to content

Commit

Permalink
add python bindings
Browse files Browse the repository at this point in the history
  • Loading branch information
jimmylomro committed Mar 15, 2022
1 parent 358f445 commit 257b576
Show file tree
Hide file tree
Showing 5 changed files with 141 additions and 2 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,5 @@ nethogs.project
libnethogs.so.*
libnethogs.a
results/
build/
nethogs.egg-info
8 changes: 8 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
[build-system]
requires = [
"setuptools>=42",
"wheel",
"pybind11>=2.8.0",
]

build-backend = "setuptools.build_meta"
62 changes: 62 additions & 0 deletions setup.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
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 = [
"src/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,
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",
)
68 changes: 68 additions & 0 deletions src/bindings.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
#include <pybind11/pybind11.h>
#include <pybind11/functional.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 arg1, NethogsMonitorRecord const *arg2){
py::gil_scoped_acquire acquire;
if (PyErr_CheckSignals() != 0) {
nethogsmonitor_breakloop();
PyErr_Clear();
}
else if (loop_callback) {
loop_callback(arg1, arg2);
}
}

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;
}

//--- 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_breakloop", &nethogsmonitor_breakloop, R"pbdoc(
Nethogs monitor loop break
)pbdoc");

#ifdef VERSION
m.attr("__version__") = VERSION;
#else
m.attr("__version__") = "unknown";
#endif

}
3 changes: 1 addition & 2 deletions src/process.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -268,7 +268,7 @@ Process *getProcess(unsigned long inode, const char *devicename) {
if (proc != NULL)
return proc;

if ( !(pidsToWatch.empty()) && pidsToWatch.find(node->pid) == pidsToWatch.end() ) {
if ( !(pidsToWatch.empty()) && pidsToWatch.find(node->pid) == pidsToWatch.end() ) {
return NULL;
}

Expand Down Expand Up @@ -440,4 +440,3 @@ void remove_timed_out_processes() {
}

void garbage_collect_processes() { garbage_collect_inodeproc(); }

0 comments on commit 257b576

Please sign in to comment.