Skip to content

Commit

Permalink
Add argument forwarding to nl_task
Browse files Browse the repository at this point in the history
Signed-off-by: Tin Švagelj <[email protected]>
  • Loading branch information
Caellian committed May 3, 2024
1 parent 830dea1 commit f470aba
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 45 deletions.
80 changes: 43 additions & 37 deletions src/netlink-conky.cc
Original file line number Diff line number Diff line change
Expand Up @@ -25,53 +25,66 @@ struct nla_policy_cache {
nla_policy *data() { return this->value.data(); }
};

template class nl_task<net_stat>;
template class nl_task<net_stat *>;
template class nl_task<net_stat *, nl_interface_id>;

template <typename Data>
int valid_handler(struct nl_msg *msg, void *arg) {
using response_proc = typename nl_task<Data>::response_proc;
using nl_cb_t = std::remove_pointer_t<nl_recvmsg_msg_cb_t>;

template <typename... Args>
int nl_task<Args...>::valid_handler(struct nl_msg *msg, void *arg) {
using response_proc = typename nl_task<Args...>::response_proc;
using arg_state = typename nl_task<Args...>::arg_state;

NORM_ERR("DEBUG: valid_handler recv msg addr %lp", msg);
auto arg_pair = static_cast<std::pair<response_proc *, Data *> *>(arg);
response_proc *processor = arg_pair->first;
Data *data = arg_pair->second;
return (*processor)(msg, static_cast<Data *>(data));
auto *task = static_cast<nl_task<Args...> *>(arg);
return std::apply(task->processor,
std::tuple_cat(std::make_tuple(msg),
std::tuple(*(task->arguments.load()))));
}
int finish_handler(struct nl_msg *msg, void *arg) {
template <typename... Args>
int nl_task<Args...>::finish_handler(struct nl_msg *msg, void *arg) {
reinterpret_cast<std::atomic<callback_state> *>(arg)->store(
callback_state::DONE, std::memory_order_release);
// FIXME: DELETE ARGUMENTS
return NL_SKIP;
};
int invalid_handler(struct nl_msg *msg, void *arg) {
}
template <typename... Args>
int nl_task<Args...>::invalid_handler(struct nl_msg *msg, void *arg) {
reinterpret_cast<std::atomic<callback_state> *>(arg)->store(
callback_state::INVALID, std::memory_order_release);
return NL_SKIP;
};
}

template <typename Data>
nl_task<Data>::nl_task(int family, uint8_t request, response_proc processor)
template <typename... Args>
nl_task<Args...>::nl_task(int family, uint8_t request, response_proc processor)
: family(family), request(request), processor(processor) {
this->cb = nl_cb_alloc(NL_CB_DEFAULT);
if (!this->cb) {
NORM_ERR("unable to allocate netlink callback.");
return;
}

nl_cb_set(this->cb, NL_CB_VALID, NL_CB_CUSTOM, &valid_handler<Data>,
std::make_pair(&this->processor, &this->data));
nl_cb_set(this->cb, NL_CB_FINISH, NL_CB_CUSTOM, &finish_handler,
&this->state);
nl_cb_set(this->cb, NL_CB_INVALID, NL_CB_CUSTOM, &invalid_handler,
&this->state);
nl_cb_set(this->cb, NL_CB_VALID, NL_CB_CUSTOM,
&nl_task<Args...>::valid_handler, static_cast<void *>(this));
nl_cb_set(this->cb, NL_CB_FINISH, NL_CB_CUSTOM,
&nl_task<Args...>::finish_handler,
static_cast<void *>(&this->state));
nl_cb_set(this->cb, NL_CB_INVALID, NL_CB_CUSTOM,
&nl_task<Args...>::invalid_handler,
static_cast<void *>(&this->state));
};

template <typename Data>
nl_task<Data>::~nl_task() {
template <typename... Args>
nl_task<Args...>::~nl_task() {
nl_cb_put(this->cb);
};

template <typename Data>
void nl_task<Data>::send_message(struct nl_sock *sock) {
template <typename... Args>
void nl_task<Args...>::send_message(struct nl_sock *sock, Args &&...args) {
this->state.store(callback_state::IN_FLIGHT, std::memory_order_release);
this->arguments.store(new auto(std::make_tuple<Args...>(std::move(args)...)),
std::memory_order_release);

struct nl_msg *msg = nlmsg_alloc();
if (!msg) {
NORM_ERR("failed to allocate netlink message.");
Expand All @@ -93,16 +106,6 @@ void nl_task<Data>::send_message(struct nl_sock *sock) {
nlmsg_free(msg);
}

template <typename Data>
nl_task<Data> &nl_task<Data>::operator=(const nl_task<Data> &other) {
nl_cb_put(this->cb);
this->cb = other.cb;
this->state.store(other.state.load());
this->family = other.family;
this->request = other.request;
return *this;
}

int ieee80211_frequency_to_channel(int freq) {
/* see 802.11-2007 17.3.8.3.2 and Annex J */
if (freq == 2484) return 14;
Expand Down Expand Up @@ -190,7 +193,8 @@ int interface_callback(struct nl_msg *msg, net_stat *ns) {
return NL_SKIP;
}

int station_callack(struct nl_msg *msg, net_stat *ns) {
int station_callack(struct nl_msg *msg, net_stat *ns,
nl_interface_id interface) {
/*
ns->bitrate NL80211_STA_INFO_TX_BITRATE
ns->link_qual NL80211_STA_INFO_SIGNAL
Expand All @@ -200,9 +204,9 @@ int station_callack(struct nl_msg *msg, net_stat *ns) {
}

void net_device_cache::setup_callbacks() {
this->interface_data_cb = nl_task<net_stat>(
this->interface_data_cb = new nl_task<net_stat *>(
this->id_nl80211, NL80211_CMD_GET_INTERFACE, interface_callback);
this->station_data_cb = nl_task<net_stat>(
this->station_data_cb = new nl_task<net_stat *, nl_interface_id>(
this->id_nl80211, NL80211_CMD_GET_STATION, station_callack);
}

Expand Down Expand Up @@ -233,6 +237,8 @@ net_device_cache::net_device_cache() {
}

net_device_cache::~net_device_cache() {
if (this->station_data_cb != nullptr) { delete this->station_data_cb; }
if (this->interface_data_cb != nullptr) { delete this->interface_data_cb; }
if (this->nl_cache != nullptr) { nl_cache_free(this->nl_cache); }
if (this->sock != nullptr) {
nl_close(this->sock);
Expand Down
22 changes: 14 additions & 8 deletions src/netlink-conky.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,12 @@ extern "C" {
#include <atomic>
#include <functional>
#include <map>
#include <optional>
#include <string>
#include <variant>

using nl_link_id = std::variant<int, char *, std::string>;
using nl_interface_id = size_t;

/// @brief State of the callback.
///
Expand All @@ -37,25 +39,29 @@ enum class callback_state : int {
IN_FLIGHT,
};

template <typename Data>
template <typename... Args>
struct nl_task {
using response_proc = std::function<int(struct nl_msg *, Data *)>;
using response_proc = std::function<int(struct nl_msg *, Args...)>;
using arg_state = std::tuple<Args...> *;

private:
struct nl_cb *cb;
std::atomic<callback_state> state;
std::atomic<callback_state> state = callback_state::DONE;
std::atomic<arg_state> arguments = nullptr;

int family;
uint8_t request;
response_proc processor;

void send_message(struct nl_sock *sock);
static int valid_handler(struct nl_msg *msg, void *arg);
static int finish_handler(struct nl_msg *msg, void *arg);
static int invalid_handler(struct nl_msg *msg, void *arg);

void send_message(struct nl_sock *sock, Args &&...args);

public:
nl_task(int family, uint8_t request, response_proc processor);
~nl_task();

nl_task<Data> &operator=(const nl_task<Data> &other);
};

class net_device_cache {
Expand All @@ -65,8 +71,8 @@ class net_device_cache {

int id_nl80211;

nl_task<net_stat> interface_data_cb;
nl_task<net_stat> station_data_cb;
nl_task<net_stat *> *interface_data_cb;
nl_task<net_stat *, nl_interface_id> *station_data_cb;

void setup_callbacks();

Expand Down

0 comments on commit f470aba

Please sign in to comment.