mirror of
https://github.com/rad4day/Waybar.git
synced 2023-12-21 10:22:59 +01:00
network: Rework initial interface search by using a dump
Instead of using an alternative way to list all links in order to choose one when an "interface" is in the configuration, we can ask for a dump of all interface an reuse the handleEvents() function. This patch also start to rework the handleEvents() function to grab more information out of each event, like the interface name.
This commit is contained in:
parent
63fdf66ad6
commit
c9bbaa7241
@ -28,8 +28,11 @@ class Network : public ALabel {
|
|||||||
static const uint8_t EPOLL_MAX = 200;
|
static const uint8_t EPOLL_MAX = 200;
|
||||||
|
|
||||||
static int handleEvents(struct nl_msg*, void*);
|
static int handleEvents(struct nl_msg*, void*);
|
||||||
|
static int handleEventsDone(struct nl_msg*, void*);
|
||||||
static int handleScan(struct nl_msg*, void*);
|
static int handleScan(struct nl_msg*, void*);
|
||||||
|
|
||||||
|
void askForStateDump(void);
|
||||||
|
|
||||||
void worker();
|
void worker();
|
||||||
void createInfoSocket();
|
void createInfoSocket();
|
||||||
void createEventSocket();
|
void createEventSocket();
|
||||||
@ -59,6 +62,9 @@ class Network : public ALabel {
|
|||||||
int nl80211_id_;
|
int nl80211_id_;
|
||||||
std::mutex mutex_;
|
std::mutex mutex_;
|
||||||
|
|
||||||
|
bool want_link_dump_;
|
||||||
|
bool dump_in_progress_;
|
||||||
|
|
||||||
unsigned long long bandwidth_down_total_;
|
unsigned long long bandwidth_down_total_;
|
||||||
unsigned long long bandwidth_up_total_;
|
unsigned long long bandwidth_up_total_;
|
||||||
|
|
||||||
|
@ -86,6 +86,8 @@ waybar::modules::Network::Network(const std::string &id, const Json::Value &conf
|
|||||||
family_(config["family"] == "ipv6" ? AF_INET6 : AF_INET),
|
family_(config["family"] == "ipv6" ? AF_INET6 : AF_INET),
|
||||||
efd_(-1),
|
efd_(-1),
|
||||||
ev_fd_(-1),
|
ev_fd_(-1),
|
||||||
|
want_link_dump_(false),
|
||||||
|
dump_in_progress_(false),
|
||||||
cidr_(0),
|
cidr_(0),
|
||||||
signal_strength_dbm_(0),
|
signal_strength_dbm_(0),
|
||||||
signal_strength_(0),
|
signal_strength_(0),
|
||||||
@ -114,6 +116,11 @@ waybar::modules::Network::Network(const std::string &id, const Json::Value &conf
|
|||||||
bandwidth_up_total_ = 0;
|
bandwidth_up_total_ = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (config_["interface"].isString()) {
|
||||||
|
// Look for an interface that match "interface"
|
||||||
|
want_link_dump_ = true;
|
||||||
|
}
|
||||||
|
|
||||||
createEventSocket();
|
createEventSocket();
|
||||||
createInfoSocket();
|
createInfoSocket();
|
||||||
auto default_iface = getPreferredIface(-1, false);
|
auto default_iface = getPreferredIface(-1, false);
|
||||||
@ -125,6 +132,10 @@ waybar::modules::Network::Network(const std::string &id, const Json::Value &conf
|
|||||||
getInterfaceAddress();
|
getInterfaceAddress();
|
||||||
}
|
}
|
||||||
dp.emit();
|
dp.emit();
|
||||||
|
// Ask for a dump of interfaces and then addresses to populate our
|
||||||
|
// information. First the interface dump, and once done, the callback
|
||||||
|
// will be called again which will ask for addresses dump.
|
||||||
|
askForStateDump();
|
||||||
worker();
|
worker();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -155,6 +166,7 @@ void waybar::modules::Network::createEventSocket() {
|
|||||||
ev_sock_ = nl_socket_alloc();
|
ev_sock_ = nl_socket_alloc();
|
||||||
nl_socket_disable_seq_check(ev_sock_);
|
nl_socket_disable_seq_check(ev_sock_);
|
||||||
nl_socket_modify_cb(ev_sock_, NL_CB_VALID, NL_CB_CUSTOM, handleEvents, this);
|
nl_socket_modify_cb(ev_sock_, NL_CB_VALID, NL_CB_CUSTOM, handleEvents, this);
|
||||||
|
nl_socket_modify_cb(ev_sock_, NL_CB_FINISH, NL_CB_CUSTOM, handleEventsDone, this);
|
||||||
auto groups = RTMGRP_LINK | (family_ == AF_INET ? RTMGRP_IPV4_IFADDR : RTMGRP_IPV6_IFADDR);
|
auto groups = RTMGRP_LINK | (family_ == AF_INET ? RTMGRP_IPV4_IFADDR : RTMGRP_IPV6_IFADDR);
|
||||||
nl_join_groups(ev_sock_, groups); // Deprecated
|
nl_join_groups(ev_sock_, groups); // Deprecated
|
||||||
if (nl_connect(ev_sock_, NETLINK_ROUTE) != 0) {
|
if (nl_connect(ev_sock_, NETLINK_ROUTE) != 0) {
|
||||||
@ -590,29 +602,9 @@ bool waybar::modules::Network::checkInterface(struct ifinfomsg *rtif, std::strin
|
|||||||
int waybar::modules::Network::getPreferredIface(int skip_idx, bool wait) const {
|
int waybar::modules::Network::getPreferredIface(int skip_idx, bool wait) const {
|
||||||
int ifid = -1;
|
int ifid = -1;
|
||||||
if (config_["interface"].isString()) {
|
if (config_["interface"].isString()) {
|
||||||
ifid = if_nametoindex(config_["interface"].asCString());
|
// Using link dump instead
|
||||||
if (ifid > 0) {
|
|
||||||
return ifid;
|
|
||||||
} else {
|
|
||||||
// Try with wildcard
|
|
||||||
struct ifaddrs *ifaddr, *ifa;
|
|
||||||
int success = getifaddrs(&ifaddr);
|
|
||||||
if (success != 0) {
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
ifa = ifaddr;
|
|
||||||
ifid = -1;
|
|
||||||
while (ifa != nullptr) {
|
|
||||||
if (wildcardMatch(config_["interface"].asString(), ifa->ifa_name)) {
|
|
||||||
ifid = if_nametoindex(ifa->ifa_name);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
ifa = ifa->ifa_next;
|
|
||||||
}
|
|
||||||
freeifaddrs(ifaddr);
|
|
||||||
return ifid;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// getExternalInterface may need some delay to detect external interface
|
// getExternalInterface may need some delay to detect external interface
|
||||||
for (uint8_t tries = 0; tries < MAX_RETRY; tries += 1) {
|
for (uint8_t tries = 0; tries < MAX_RETRY; tries += 1) {
|
||||||
ifid = getExternalInterface(skip_idx);
|
ifid = getExternalInterface(skip_idx);
|
||||||
@ -656,6 +648,55 @@ int waybar::modules::Network::handleEvents(struct nl_msg *msg, void *data) {
|
|||||||
std::lock_guard<std::mutex> lock(net->mutex_);
|
std::lock_guard<std::mutex> lock(net->mutex_);
|
||||||
auto nh = nlmsg_hdr(msg);
|
auto nh = nlmsg_hdr(msg);
|
||||||
auto ifi = static_cast<struct ifinfomsg *>(NLMSG_DATA(nh));
|
auto ifi = static_cast<struct ifinfomsg *>(NLMSG_DATA(nh));
|
||||||
|
bool is_del_event = false;
|
||||||
|
|
||||||
|
switch (nh->nlmsg_type) {
|
||||||
|
case RTM_DELLINK:
|
||||||
|
is_del_event = true;
|
||||||
|
case RTM_NEWLINK: {
|
||||||
|
struct ifinfomsg *ifi = static_cast<struct ifinfomsg *>(NLMSG_DATA(nh));
|
||||||
|
ssize_t attrlen = IFLA_PAYLOAD(nh);
|
||||||
|
struct rtattr *ifla = IFLA_RTA(ifi);
|
||||||
|
const char *ifname = NULL;
|
||||||
|
size_t ifname_len = 0;
|
||||||
|
|
||||||
|
if (net->ifid_ != -1 && ifi->ifi_index != net->ifid_) {
|
||||||
|
return NL_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (; RTA_OK(ifla, attrlen); ifla = RTA_NEXT(ifla, attrlen)) {
|
||||||
|
switch (ifla->rta_type) {
|
||||||
|
case IFLA_IFNAME:
|
||||||
|
ifname = static_cast<const char *>(RTA_DATA(ifla));
|
||||||
|
ifname_len = RTA_PAYLOAD(ifla) - 1; // minus \0
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!is_del_event && net->ifid_ == -1) {
|
||||||
|
// Checking if it's an interface we care about.
|
||||||
|
std::string new_ifname (ifname, ifname_len);
|
||||||
|
if (net->checkInterface(ifi, new_ifname)) {
|
||||||
|
spdlog::debug("network: selecting new interface {}/{}", new_ifname, ifi->ifi_index);
|
||||||
|
|
||||||
|
net->ifname_ = new_ifname;
|
||||||
|
net->ifid_ = ifi->ifi_index;
|
||||||
|
net->getInterfaceAddress();
|
||||||
|
net->thread_timer_.wake_up();
|
||||||
|
}
|
||||||
|
} else if (is_del_event && net->ifid_ >= 0) {
|
||||||
|
// Our interface has been deleted, start looking/waiting for one we care.
|
||||||
|
spdlog::debug("network: interface {}/{} deleted", net->ifname_, net->ifid_);
|
||||||
|
|
||||||
|
net->clearIface();
|
||||||
|
// Check for a new interface and get info
|
||||||
|
net->checkNewInterface(ifi);
|
||||||
|
net->dp.emit();
|
||||||
|
}
|
||||||
|
return NL_OK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (nh->nlmsg_type == RTM_DELADDR) {
|
if (nh->nlmsg_type == RTM_DELADDR) {
|
||||||
// Check for valid interface
|
// Check for valid interface
|
||||||
if (ifi->ifi_index == net->ifid_) {
|
if (ifi->ifi_index == net->ifid_) {
|
||||||
@ -671,25 +712,6 @@ int waybar::modules::Network::handleEvents(struct nl_msg *msg, void *data) {
|
|||||||
}
|
}
|
||||||
return NL_OK;
|
return NL_OK;
|
||||||
}
|
}
|
||||||
} else if (nh->nlmsg_type == RTM_NEWLINK || nh->nlmsg_type == RTM_DELLINK) {
|
|
||||||
char ifname[IF_NAMESIZE];
|
|
||||||
if_indextoname(ifi->ifi_index, ifname);
|
|
||||||
// Check for valid interface
|
|
||||||
if (ifi->ifi_index != net->ifid_ && net->checkInterface(ifi, ifname)) {
|
|
||||||
net->ifname_ = ifname;
|
|
||||||
net->ifid_ = ifi->ifi_index;
|
|
||||||
// Get Iface and WIFI info
|
|
||||||
net->getInterfaceAddress();
|
|
||||||
net->thread_timer_.wake_up();
|
|
||||||
return NL_OK;
|
|
||||||
} else if (ifi->ifi_index == net->ifid_ &&
|
|
||||||
(!(ifi->ifi_flags & IFF_RUNNING) || !(ifi->ifi_flags & IFF_UP) ||
|
|
||||||
!net->checkInterface(ifi, ifname))) {
|
|
||||||
net->clearIface();
|
|
||||||
// Check for a new interface and get info
|
|
||||||
net->checkNewInterface(ifi);
|
|
||||||
return NL_OK;
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
char ifname[IF_NAMESIZE];
|
char ifname[IF_NAMESIZE];
|
||||||
if_indextoname(ifi->ifi_index, ifname);
|
if_indextoname(ifi->ifi_index, ifname);
|
||||||
@ -713,6 +735,32 @@ int waybar::modules::Network::handleEvents(struct nl_msg *msg, void *data) {
|
|||||||
return NL_SKIP;
|
return NL_SKIP;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void waybar::modules::Network::askForStateDump(void) {
|
||||||
|
/* We need to wait until the current dump is done before sending new
|
||||||
|
* messages. handleEventsDone() is called when a dump is done. */
|
||||||
|
if (dump_in_progress_)
|
||||||
|
return;
|
||||||
|
|
||||||
|
struct rtgenmsg rt_hdr = {
|
||||||
|
.rtgen_family = AF_UNSPEC,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (want_link_dump_) {
|
||||||
|
nl_send_simple(ev_sock_, RTM_GETLINK, NLM_F_DUMP,
|
||||||
|
&rt_hdr, sizeof (rt_hdr));
|
||||||
|
want_link_dump_ = false;
|
||||||
|
dump_in_progress_ = true;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int waybar::modules::Network::handleEventsDone(struct nl_msg *msg, void *data) {
|
||||||
|
auto net = static_cast<waybar::modules::Network *>(data);
|
||||||
|
net->dump_in_progress_ = false;
|
||||||
|
net->askForStateDump();
|
||||||
|
return NL_OK;
|
||||||
|
}
|
||||||
|
|
||||||
int waybar::modules::Network::handleScan(struct nl_msg *msg, void *data) {
|
int waybar::modules::Network::handleScan(struct nl_msg *msg, void *data) {
|
||||||
auto net = static_cast<waybar::modules::Network *>(data);
|
auto net = static_cast<waybar::modules::Network *>(data);
|
||||||
auto gnlh = static_cast<genlmsghdr *>(nlmsg_data(nlmsg_hdr(msg)));
|
auto gnlh = static_cast<genlmsghdr *>(nlmsg_data(nlmsg_hdr(msg)));
|
||||||
|
Loading…
Reference in New Issue
Block a user