feat(net): interface discovery (#2025)

This commit is contained in:
devsnek 2021-01-03 04:48:15 -06:00 committed by GitHub
parent eb302f96ff
commit f7c2d83ef2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 96 additions and 11 deletions

View File

@ -67,6 +67,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
([`#2108`](https://github.com/polybar/polybar/issues/2108))
- `internal/xworkspaces`: Make the urgent hint persistent
([`#1081`](https://github.com/polybar/polybar/issues/1081))
- `internal/network`: `interface-type` may be used in place of `interface` to
automatically select a network interface
([`#2025`](https://github.com/polybar/polybar/pull/2025))
### Changed
- Slight changes to the value ranges the different ramp levels are responsible

View File

@ -1,15 +1,15 @@
#pragma once
#include <chrono>
#include <cstdlib>
#include <arpa/inet.h>
#include <ifaddrs.h>
#include <chrono>
#include <cstdlib>
#include "common.hpp"
#include "settings.hpp"
#include "errors.hpp"
#include "components/logger.hpp"
#include "errors.hpp"
#include "settings.hpp"
#include "utils/math.hpp"
#if WITH_LIBNL
@ -38,6 +38,8 @@ namespace net {
DEFINE_ERROR(network_error);
bool is_wireless_interface(const string& ifname);
std::string find_wireless_interface();
std::string find_wired_interface();
// types {{{

View File

@ -1,6 +1,7 @@
#include "adapters/net.hpp"
#include <arpa/inet.h>
#include <dirent.h>
#include <linux/ethtool.h>
#include <linux/if_link.h>
#include <linux/sockios.h>
@ -9,6 +10,9 @@
#include <netinet/in.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <iomanip>
#include <iomanip>
@ -21,14 +25,65 @@
POLYBAR_NS
namespace net {
enum class NetType {
WIRELESS,
ETHERNET,
OTHER,
};
static const string NO_IP = string("N/A");
static const string NET_PATH = "/sys/class/net/";
static const string VIRTUAL_PATH = "/sys/devices/virtual/";
static bool is_virtual(const std::string& ifname) {
char* target = realpath((NET_PATH + ifname).c_str(), nullptr);
const std::string real_path{target};
free(target);
return real_path.rfind(VIRTUAL_PATH, 0) == 0;
}
NetType iface_type(const std::string& ifname) {
if (file_util::exists(NET_PATH + ifname + "/wireless")) {
return NetType::WIRELESS;
}
if (is_virtual(ifname)) {
return NetType::OTHER;
}
return NetType::ETHERNET;
}
/**
* Test if interface with given name is a wireless device
*/
bool is_wireless_interface(const string& ifname) {
return file_util::exists("/sys/class/net/" + ifname + "/wireless");
return iface_type(ifname) == NetType::WIRELESS;
}
static const string NO_IP = string("N/A");
std::string find_interface(NetType type) {
struct ifaddrs* ifaddrs;
getifaddrs(&ifaddrs);
for (struct ifaddrs* i = ifaddrs; i != nullptr; i = i->ifa_next) {
const std::string name{i->ifa_name};
const NetType iftype = iface_type(name);
if (iftype != type) {
continue;
}
freeifaddrs(ifaddrs);
return name;
}
freeifaddrs(ifaddrs);
return "";
}
std::string find_wireless_interface() {
return find_interface(NetType::WIRELESS);
}
std::string find_wired_interface() {
return find_interface(NetType::ETHERNET);
}
// class : network {{{
@ -215,7 +270,7 @@ namespace net {
* Test if the network interface is in a valid state
*/
bool network::test_interface() const {
auto operstate = file_util::contents("/sys/class/net/" + m_interface + "/operstate");
auto operstate = file_util::contents(NET_PATH + m_interface + "/operstate");
bool up = operstate.compare(0, 2, "up") == 0;
return m_unknown_up ? (up || operstate.compare(0, 7, "unknown") == 0) : up;
}

View File

@ -3,9 +3,8 @@
#include "drawtypes/animation.hpp"
#include "drawtypes/label.hpp"
#include "drawtypes/ramp.hpp"
#include "utils/factory.hpp"
#include "modules/meta/base.inl"
#include "utils/factory.hpp"
POLYBAR_NS
@ -16,6 +15,32 @@ namespace modules {
: timer_module<network_module>(bar, move(name_)) {
// Load configuration values
m_interface = m_conf.get(name(), "interface", m_interface);
if (m_interface.empty()) {
std::string type = m_conf.get(name(), "interface-type");
if (type == "wired") {
m_interface = net::find_wired_interface();
if (!m_interface.empty()) {
m_log.notice("%s: Discovered wired interface %s", name(), m_interface);
}
} else if (type == "wireless") {
m_interface = net::find_wireless_interface();
if (!m_interface.empty()) {
m_log.notice("%s: Discovered wireless interface %s", name(), m_interface);
}
} else {
throw module_error("Invalid interface type '" + type + "'");
}
if (m_interface.empty()) {
throw module_error("No interface found for type '" + type + "'");
}
}
if (m_interface.empty()) {
throw module_error("missing 'interface' or 'interface-type'");
}
m_ping_nth_update = m_conf.get(name(), "ping-interval", m_ping_nth_update);
m_udspeed_minwidth = m_conf.get(name(), "udspeed-minwidth", m_udspeed_minwidth);
m_accumulate = m_conf.get(name(), "accumulate-stats", m_accumulate);
@ -189,6 +214,6 @@ namespace modules {
m_log.trace("%s: Reached end of network subthread", name());
}
}
} // namespace modules
POLYBAR_NS_END