refactor(network): Code cleanup
- Cleanup of network module and adapter - Check operstate instead of carrier when testing the the current connection state, as suggested by @patrick96 in #44 - Separate signal quality and signal strength - Log failed attempt to query device driver
This commit is contained in:
parent
334dc7731d
commit
82f311b695
@ -39,21 +39,32 @@ LEMONBUDDY_NS
|
|||||||
|
|
||||||
namespace net {
|
namespace net {
|
||||||
DEFINE_ERROR(network_error);
|
DEFINE_ERROR(network_error);
|
||||||
DEFINE_ERROR(wired_network_error);
|
|
||||||
DEFINE_ERROR(wireless_network_error);
|
|
||||||
|
|
||||||
// types {{{
|
// types {{{
|
||||||
|
|
||||||
struct bytes_t {
|
struct quality_range {
|
||||||
uint32_t transmitted = 0;
|
int val = 0;
|
||||||
uint32_t received = 0;
|
int max = 0;
|
||||||
std::chrono::system_clock::time_point time;
|
|
||||||
|
int percentage() const {
|
||||||
|
if (max < 0)
|
||||||
|
return 2 * (val + 100);
|
||||||
|
return static_cast<float>(val) / max * 100.0f + 0.5f;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct linkdata_t {
|
using bytes_t = unsigned int;
|
||||||
string ip_address;
|
|
||||||
bytes_t previous;
|
struct link_activity {
|
||||||
bytes_t current;
|
bytes_t transmitted = 0;
|
||||||
|
bytes_t received = 0;
|
||||||
|
chrono::system_clock::time_point time;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct link_status {
|
||||||
|
string ip;
|
||||||
|
link_activity previous;
|
||||||
|
link_activity current;
|
||||||
};
|
};
|
||||||
|
|
||||||
// }}}
|
// }}}
|
||||||
@ -61,169 +72,145 @@ namespace net {
|
|||||||
|
|
||||||
class network {
|
class network {
|
||||||
public:
|
public:
|
||||||
|
/**
|
||||||
|
* Construct network interface
|
||||||
|
*/
|
||||||
explicit network(string interface) : m_interface(interface) {
|
explicit network(string interface) : m_interface(interface) {
|
||||||
if (if_nametoindex(m_interface.c_str()) == 0)
|
if (if_nametoindex(m_interface.c_str()) == 0)
|
||||||
throw network_error("Invalid network interface \"" + m_interface + "\"");
|
throw network_error("Invalid network interface \"" + m_interface + "\"");
|
||||||
if ((m_fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
|
if ((m_socketfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
|
||||||
throw network_error("Failed to open socket");
|
throw network_error("Failed to open socket");
|
||||||
std::memset(&m_data, 0, sizeof(m_data));
|
|
||||||
std::strncpy(m_data.ifr_name, m_interface.data(), IFNAMSIZ - 1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
~network() {
|
/**
|
||||||
if (m_fd != -1)
|
* Destruct network interface
|
||||||
close(m_fd);
|
*/
|
||||||
|
virtual ~network() {
|
||||||
|
if (m_socketfd != -1)
|
||||||
|
close(m_socketfd);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool test_interface() {
|
/**
|
||||||
if ((ioctl(m_fd, SIOCGIFFLAGS, &m_data)) == -1)
|
* Query device driver for information
|
||||||
throw network_error("Failed to get flags");
|
*/
|
||||||
if ((m_data.ifr_flags & IFF_UP) == 0)
|
virtual bool query() {
|
||||||
return false;
|
|
||||||
if ((m_data.ifr_flags & IFF_RUNNING) == 0)
|
|
||||||
return false;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool test_connection() {
|
|
||||||
int status = EXIT_FAILURE;
|
|
||||||
|
|
||||||
try {
|
|
||||||
m_ping = command_util::make_command(
|
|
||||||
"ping -c 2 -W 2 -I " + m_interface + " " + string(CONNECTION_TEST_IP));
|
|
||||||
status = m_ping->exec(true);
|
|
||||||
m_ping.reset();
|
|
||||||
} catch (std::exception& e) {
|
|
||||||
}
|
|
||||||
|
|
||||||
return (status == EXIT_SUCCESS);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool test() {
|
|
||||||
try {
|
|
||||||
return test_interface() && test_connection();
|
|
||||||
} catch (network_error& e) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool connected() {
|
|
||||||
try {
|
|
||||||
if (!test_interface())
|
|
||||||
return false;
|
|
||||||
return file_util::get_contents("/sys/class/net/" + m_interface + "/carrier")[0] == '1';
|
|
||||||
} catch (network_error& e) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool query_interface() {
|
|
||||||
auto now = chrono::system_clock::now();
|
|
||||||
if ((now - m_last_query) < chrono::seconds(1))
|
|
||||||
return true;
|
|
||||||
m_last_query = now;
|
|
||||||
|
|
||||||
struct ifaddrs* ifaddr;
|
struct ifaddrs* ifaddr;
|
||||||
getifaddrs(&ifaddr);
|
|
||||||
bool match = false;
|
if (getifaddrs(&ifaddr) == -1)
|
||||||
|
return false;
|
||||||
|
|
||||||
for (auto ifa = ifaddr; ifa != nullptr; ifa = ifa->ifa_next) {
|
for (auto ifa = ifaddr; ifa != nullptr; ifa = ifa->ifa_next) {
|
||||||
if (m_interface.compare(0, m_interface.length(), ifa->ifa_name) != 0)
|
if (m_interface.compare(0, m_interface.length(), ifa->ifa_name) != 0)
|
||||||
continue;
|
continue;
|
||||||
match = true;
|
|
||||||
|
|
||||||
switch (ifa->ifa_addr->sa_family) {
|
switch (ifa->ifa_addr->sa_family) {
|
||||||
case AF_INET:
|
case AF_INET:
|
||||||
char ip_buffer[NI_MAXHOST];
|
char ip_buffer[NI_MAXHOST];
|
||||||
getnameinfo(ifa->ifa_addr, sizeof(sockaddr_in), ip_buffer, NI_MAXHOST, nullptr, 0,
|
getnameinfo(ifa->ifa_addr, sizeof(sockaddr_in), ip_buffer, NI_MAXHOST, nullptr, 0,
|
||||||
NI_NUMERICHOST);
|
NI_NUMERICHOST);
|
||||||
m_linkdata.ip_address = string(ip_buffer);
|
m_status.ip = string{ip_buffer};
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case AF_PACKET:
|
case AF_PACKET:
|
||||||
if (ifa->ifa_data == nullptr)
|
if (ifa->ifa_data == nullptr)
|
||||||
continue;
|
continue;
|
||||||
struct rtnl_link_stats* link_state =
|
struct rtnl_link_stats* link_state =
|
||||||
reinterpret_cast<struct rtnl_link_stats*>(ifa->ifa_data);
|
reinterpret_cast<decltype(link_state)>(ifa->ifa_data);
|
||||||
m_linkdata.previous = m_linkdata.current;
|
m_status.previous = m_status.current;
|
||||||
m_linkdata.current.transmitted = link_state->tx_bytes;
|
m_status.current.transmitted = link_state->tx_bytes;
|
||||||
m_linkdata.current.received = link_state->rx_bytes;
|
m_status.current.received = link_state->rx_bytes;
|
||||||
m_linkdata.current.time = chrono::system_clock::now();
|
m_status.current.time = chrono::system_clock::now();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
freeifaddrs(ifaddr);
|
freeifaddrs(ifaddr);
|
||||||
|
|
||||||
return match;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
string ip() {
|
/**
|
||||||
if (!test_interface())
|
* Check current connection state
|
||||||
throw network_error("Interface is not up");
|
*/
|
||||||
if (!query_interface())
|
virtual bool connected() const = 0;
|
||||||
throw network_error("Failed to query interface");
|
|
||||||
return m_linkdata.ip_address;
|
|
||||||
}
|
|
||||||
|
|
||||||
string downspeed(int minwidth = 3) {
|
/**
|
||||||
if (!query_interface())
|
* Run ping command to test internet connectivity
|
||||||
throw network_error("Failed to query interface");
|
*/
|
||||||
|
virtual bool ping() const {
|
||||||
float bytes_diff = m_linkdata.current.received - m_linkdata.previous.received;
|
try {
|
||||||
float time_diff =
|
auto exec = "ping -c 2 -W 2 -I " + m_interface + " " + string(CONNECTION_TEST_IP);
|
||||||
chrono::duration_cast<chrono::seconds>(m_linkdata.current.time - m_linkdata.previous.time)
|
auto ping = command_util::make_command(exec);
|
||||||
.count();
|
return ping && ping->exec(true) == EXIT_SUCCESS;
|
||||||
float speed = bytes_diff / time_diff;
|
} catch (const std::exception& err) {
|
||||||
|
return false;
|
||||||
speed /= 1000; // convert to KB
|
|
||||||
int suffix_n = 0;
|
|
||||||
vector<string> suffixes{"KB", "MB", "GB"};
|
|
||||||
|
|
||||||
while (speed >= 1000 && suffix_n < (int)suffixes.size() - 1) {
|
|
||||||
suffix_n++;
|
|
||||||
speed /= 1000;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return string_util::from_stream(stringstream() << std::setw(minwidth) << std::setfill(' ')
|
|
||||||
<< std::setprecision(0) << std::fixed << speed
|
|
||||||
<< " " << suffixes[suffix_n] << "/s");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
string upspeed(int minwidth = 3) {
|
/**
|
||||||
if (!query_interface())
|
* Get interface ip address
|
||||||
throw network_error("Failed to query interface");
|
*/
|
||||||
|
string ip() const {
|
||||||
|
return m_status.ip;
|
||||||
|
}
|
||||||
|
|
||||||
float bytes_diff = m_linkdata.current.transmitted - m_linkdata.previous.transmitted;
|
/**
|
||||||
float time_diff =
|
* Get download speed rate
|
||||||
chrono::duration_cast<chrono::seconds>(m_linkdata.current.time - m_linkdata.previous.time)
|
*/
|
||||||
.count();
|
string downspeed(int minwidth = 3) const {
|
||||||
float speed = bytes_diff / time_diff;
|
float bytes_diff = m_status.current.received - m_status.previous.received;
|
||||||
|
return format_speedrate(bytes_diff, minwidth);
|
||||||
|
}
|
||||||
|
|
||||||
speed /= 1000; // convert to KB
|
/**
|
||||||
int suffix_n = 0;
|
* Get upload speed rate
|
||||||
vector<string> suffixes{"KB", "MB", "GB"};
|
*/
|
||||||
|
string upspeed(int minwidth = 3) const {
|
||||||
while (speed >= 1000 && suffix_n < (int)suffixes.size() - 1) {
|
float bytes_diff = m_status.current.transmitted - m_status.previous.transmitted;
|
||||||
suffix_n++;
|
return format_speedrate(bytes_diff, minwidth);
|
||||||
speed /= 1000;
|
|
||||||
}
|
|
||||||
|
|
||||||
return string_util::from_stream(stringstream() << std::setw(minwidth) << std::setfill(' ')
|
|
||||||
<< std::setprecision(0) << std::fixed << speed
|
|
||||||
<< " " << suffixes[suffix_n] << "/s");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
unique_ptr<command_util::command> m_ping;
|
/**
|
||||||
|
* Test if the network interface is in a valid state
|
||||||
|
*/
|
||||||
|
bool test_interface(struct ifreq& request) const {
|
||||||
|
if ((ioctl(m_socketfd, SIOCGIFFLAGS, &request)) == -1)
|
||||||
|
return false;
|
||||||
|
if ((request.ifr_flags & IFF_UP) == 0)
|
||||||
|
return false;
|
||||||
|
if ((request.ifr_flags & IFF_RUNNING) == 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
auto operstate = file_util::get_contents("/sys/class/net/" + m_interface + "/operstate");
|
||||||
|
|
||||||
|
return operstate.compare(0, 2, "up") == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Format up- and download speed
|
||||||
|
*/
|
||||||
|
string format_speedrate(float bytes_diff, int minwidth) const {
|
||||||
|
const auto duration = m_status.current.time - m_status.previous.time;
|
||||||
|
float time_diff = chrono::duration_cast<chrono::seconds>(duration).count();
|
||||||
|
float speedrate = bytes_diff / (time_diff ? time_diff : 1);
|
||||||
|
|
||||||
|
vector<string> suffixes{"GB", "MB"};
|
||||||
|
string suffix{"KB"};
|
||||||
|
|
||||||
|
while ((speedrate /= 1000) > 999) {
|
||||||
|
suffix = suffixes.back();
|
||||||
|
suffixes.pop_back();
|
||||||
|
}
|
||||||
|
|
||||||
|
return string_util::from_stream(stringstream() << std::setw(minwidth) << std::setfill(' ')
|
||||||
|
<< std::setprecision(0) << std::fixed
|
||||||
|
<< speedrate << " " << suffix << "/s");
|
||||||
|
}
|
||||||
|
|
||||||
|
int m_socketfd = 0;
|
||||||
|
link_status m_status;
|
||||||
string m_interface;
|
string m_interface;
|
||||||
string m_ip;
|
|
||||||
struct ifreq m_data;
|
|
||||||
int m_fd = 0;
|
|
||||||
|
|
||||||
linkdata_t m_linkdata;
|
|
||||||
|
|
||||||
chrono::system_clock::time_point m_last_query;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// }}}
|
// }}}
|
||||||
@ -231,18 +218,56 @@ namespace net {
|
|||||||
|
|
||||||
class wired_network : public network {
|
class wired_network : public network {
|
||||||
public:
|
public:
|
||||||
explicit wired_network(string interface) : network(interface) {
|
explicit wired_network(string interface) : network(interface) {}
|
||||||
struct ethtool_cmd e;
|
|
||||||
e.cmd = ETHTOOL_GSET;
|
|
||||||
|
|
||||||
m_data.ifr_data = (caddr_t)&e;
|
/**
|
||||||
|
* Query device driver for information
|
||||||
|
*/
|
||||||
|
bool query() override {
|
||||||
|
if (!network::query())
|
||||||
|
return false;
|
||||||
|
|
||||||
if (ioctl(m_fd, SIOCETHTOOL, &m_data) == 0)
|
struct ethtool_cmd ethernet_data;
|
||||||
m_linkspeed = (e.speed == USHRT_MAX ? 0 : e.speed);
|
ethernet_data.cmd = ETHTOOL_GSET;
|
||||||
|
|
||||||
|
struct ifreq request;
|
||||||
|
strncpy(request.ifr_name, m_interface.c_str(), IFNAMSIZ - 1);
|
||||||
|
request.ifr_data = reinterpret_cast<caddr_t>(ðernet_data);
|
||||||
|
|
||||||
|
if (ioctl(m_socketfd, SIOCETHTOOL, &request) == -1)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
m_linkspeed = ethernet_data.speed;
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
string link_speed() {
|
/**
|
||||||
return string((m_linkspeed == 0 ? "???" : to_string(m_linkspeed)) + " Mbit/s");
|
* Check current connection state
|
||||||
|
*/
|
||||||
|
bool connected() const override {
|
||||||
|
struct ifreq request;
|
||||||
|
struct ethtool_value ethernet_data;
|
||||||
|
|
||||||
|
strncpy(request.ifr_name, m_interface.c_str(), IFNAMSIZ - 1);
|
||||||
|
ethernet_data.cmd = ETHTOOL_GLINK;
|
||||||
|
request.ifr_data = reinterpret_cast<caddr_t>(ðernet_data);
|
||||||
|
|
||||||
|
if (!network::test_interface(request))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (ioctl(m_socketfd, SIOCETHTOOL, &request) != -1)
|
||||||
|
return ethernet_data.data != 0;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* about the current connection
|
||||||
|
*/
|
||||||
|
string linkspeed() const {
|
||||||
|
return (m_linkspeed == 0 ? "???" : to_string(m_linkspeed)) + " Mbit/s";
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -252,182 +277,153 @@ namespace net {
|
|||||||
// }}}
|
// }}}
|
||||||
// class: wireless_network {{{
|
// class: wireless_network {{{
|
||||||
|
|
||||||
struct wireless_info {
|
|
||||||
std::bitset<5> flags;
|
|
||||||
string essid{IW_ESSID_MAX_SIZE + 1};
|
|
||||||
int quality = 0;
|
|
||||||
int quality_max = 0;
|
|
||||||
int quality_avg = 0;
|
|
||||||
int signal = 0;
|
|
||||||
int signal_max = 0;
|
|
||||||
int noise = 0;
|
|
||||||
int noise_max = 0;
|
|
||||||
int bitrate = 0;
|
|
||||||
double frequency = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
enum wireless_flags {
|
|
||||||
ESSID = 0,
|
|
||||||
QUALITY = 1,
|
|
||||||
SIGNAL = 2,
|
|
||||||
NOISE = 3,
|
|
||||||
FREQUENCY = 4,
|
|
||||||
};
|
|
||||||
|
|
||||||
class wireless_network : public network {
|
class wireless_network : public network {
|
||||||
public:
|
public:
|
||||||
wireless_network(string interface) : network(interface) {
|
wireless_network(string interface) : network(interface) {}
|
||||||
std::strcpy((char*)&m_iw.ifr_ifrn.ifrn_name, m_interface.c_str());
|
|
||||||
|
|
||||||
if (!m_info)
|
/**
|
||||||
m_info.reset(new wireless_info());
|
* Query the wireless device for information
|
||||||
}
|
* about the current connection
|
||||||
|
*/
|
||||||
|
bool query() override {
|
||||||
|
if (!network::query())
|
||||||
|
return false;
|
||||||
|
|
||||||
string essid() {
|
|
||||||
if (!query_interface())
|
|
||||||
return "";
|
|
||||||
if (!m_info->flags.test(wireless_flags::ESSID))
|
|
||||||
return "";
|
|
||||||
return m_info->essid;
|
|
||||||
}
|
|
||||||
|
|
||||||
float signal_quality() {
|
|
||||||
if (!query_interface())
|
|
||||||
return 0;
|
|
||||||
if (m_info->flags.test(wireless_flags::QUALITY))
|
|
||||||
return 2 * (signal_dbm() + 100);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
float signal_dbm() {
|
|
||||||
if (!query_interface())
|
|
||||||
return 0;
|
|
||||||
if (m_info->flags.test(wireless_flags::QUALITY))
|
|
||||||
return m_info->quality + m_info->noise - 256;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
bool query_interface() {
|
|
||||||
if ((chrono::system_clock::now() - m_last_query) < chrono::seconds(1))
|
|
||||||
return true;
|
|
||||||
|
|
||||||
network::query_interface();
|
|
||||||
|
|
||||||
auto ifname = m_interface.c_str();
|
|
||||||
auto socket_fd = iw_sockets_open();
|
auto socket_fd = iw_sockets_open();
|
||||||
|
|
||||||
if (socket_fd == -1)
|
if (socket_fd == -1)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
auto on_exit = scope_util::make_exit_handler<>([&]() { iw_sockets_close(socket_fd); });
|
struct iwreq req;
|
||||||
{
|
|
||||||
wireless_config wcfg;
|
|
||||||
|
|
||||||
if (iw_get_basic_config(socket_fd, ifname, &wcfg) == -1)
|
if (iw_get_ext(socket_fd, m_interface.c_str(), SIOCGIWMODE, &req) == -1)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// reset flags
|
// Ignore interfaces in ad-hoc mode
|
||||||
m_info->flags.none();
|
if (req.u.mode == IW_MODE_ADHOC)
|
||||||
|
return false;
|
||||||
|
|
||||||
if (wcfg.has_essid && wcfg.essid_on) {
|
query_essid(socket_fd);
|
||||||
m_info->essid = {wcfg.essid, 0, IW_ESSID_MAX_SIZE};
|
query_quality(socket_fd);
|
||||||
m_info->flags |= wireless_flags::ESSID;
|
|
||||||
|
iw_sockets_close(socket_fd);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check current connection state
|
||||||
|
*/
|
||||||
|
bool connected() const override {
|
||||||
|
struct ifreq request;
|
||||||
|
strncpy(request.ifr_name, m_interface.c_str(), IFNAMSIZ - 1);
|
||||||
|
|
||||||
|
if (!network::test_interface(request))
|
||||||
|
return false;
|
||||||
|
if (m_essid.empty())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ESSID reported by last query
|
||||||
|
*/
|
||||||
|
string essid() const {
|
||||||
|
return m_essid;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Signal strength percentage reported by last query
|
||||||
|
*/
|
||||||
|
int signal() const {
|
||||||
|
return m_signalstrength.percentage();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Link quality percentage reported by last query
|
||||||
|
*/
|
||||||
|
int quality() const {
|
||||||
|
return m_linkquality.percentage();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
/**
|
||||||
|
* Query for ESSID
|
||||||
|
*/
|
||||||
|
void query_essid(const int& socket_fd) {
|
||||||
|
char essid[IW_ESSID_MAX_SIZE + 1];
|
||||||
|
|
||||||
|
struct iwreq req;
|
||||||
|
req.u.essid.pointer = &essid;
|
||||||
|
req.u.essid.length = sizeof(essid);
|
||||||
|
req.u.essid.flags = 0;
|
||||||
|
|
||||||
|
if (iw_get_ext(socket_fd, m_interface.c_str(), SIOCGIWESSID, &req) != -1) {
|
||||||
|
m_essid = string{essid};
|
||||||
|
} else {
|
||||||
|
m_essid.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Query for device driver quality values
|
||||||
|
*/
|
||||||
|
void query_quality(const int& socket_fd) {
|
||||||
|
iwrange range;
|
||||||
|
iwstats stats;
|
||||||
|
|
||||||
|
// Fill range
|
||||||
|
if (iw_get_range_info(socket_fd, m_interface.c_str(), &range) == -1)
|
||||||
|
return;
|
||||||
|
// Fill stats
|
||||||
|
if (iw_get_stats(socket_fd, m_interface.c_str(), &stats, &range, 1) == -1)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Check if the driver supplies the quality value
|
||||||
|
if (stats.qual.updated & IW_QUAL_QUAL_INVALID)
|
||||||
|
return;
|
||||||
|
// Check if the driver supplies the quality level value
|
||||||
|
if (stats.qual.updated & IW_QUAL_LEVEL_INVALID)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Check if the link quality has been uodated
|
||||||
|
if (stats.qual.updated & IW_QUAL_QUAL_UPDATED) {
|
||||||
|
m_linkquality.val = stats.qual.qual;
|
||||||
|
m_linkquality.max = range.max_qual.qual;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the signal strength has been uodated
|
||||||
|
if (stats.qual.updated & IW_QUAL_LEVEL_UPDATED) {
|
||||||
|
m_signalstrength.val = stats.qual.level;
|
||||||
|
m_signalstrength.max = range.max_qual.level;
|
||||||
|
|
||||||
|
// Check if the values are defined in dBm
|
||||||
|
if (stats.qual.level > range.max_qual.level) {
|
||||||
|
m_signalstrength.val -= 0x100;
|
||||||
|
m_signalstrength.max -= 0x100;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (wcfg.has_freq) {
|
|
||||||
m_info->frequency = wcfg.freq;
|
|
||||||
m_info->flags |= wireless_flags::FREQUENCY;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (wcfg.mode == IW_MODE_ADHOC)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
iwrange range;
|
|
||||||
if (iw_get_range_info(socket_fd, ifname, &range) == -1)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
iwstats stats;
|
|
||||||
if (iw_get_stats(socket_fd, ifname, &stats, &range, 1) == -1)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (stats.qual.updated & IW_QUAL_RCPI) {
|
|
||||||
if (!(stats.qual.updated & IW_QUAL_QUAL_INVALID)) {
|
|
||||||
m_info->quality = stats.qual.qual;
|
|
||||||
m_info->quality_max = range.max_qual.qual;
|
|
||||||
m_info->quality_avg = range.avg_qual.qual;
|
|
||||||
m_info->flags |= wireless_flags::QUALITY;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (stats.qual.updated & IW_QUAL_RCPI) {
|
|
||||||
if (!(stats.qual.updated & IW_QUAL_LEVEL_INVALID)) {
|
|
||||||
m_info->signal = stats.qual.level / 2.0 - 110 + 0.5;
|
|
||||||
m_info->flags |= wireless_flags::SIGNAL;
|
|
||||||
}
|
|
||||||
if (!(stats.qual.updated & IW_QUAL_NOISE_INVALID)) {
|
|
||||||
m_info->noise = stats.qual.noise / 2.0 - 110 + 0.5;
|
|
||||||
m_info->flags |= wireless_flags::NOISE;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if ((stats.qual.updated & IW_QUAL_DBM) || stats.qual.level > range.max_qual.level) {
|
|
||||||
if (!(stats.qual.updated & IW_QUAL_LEVEL_INVALID)) {
|
|
||||||
m_info->signal = stats.qual.level;
|
|
||||||
if (m_info->signal > 63)
|
|
||||||
m_info->signal -= 256;
|
|
||||||
m_info->flags |= wireless_flags::SIGNAL;
|
|
||||||
}
|
|
||||||
if (!(stats.qual.updated & IW_QUAL_NOISE_INVALID)) {
|
|
||||||
m_info->noise = stats.qual.noise;
|
|
||||||
if (m_info->noise > 63)
|
|
||||||
m_info->noise -= 256;
|
|
||||||
m_info->flags |= wireless_flags::NOISE;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (!(stats.qual.updated & IW_QUAL_LEVEL_INVALID)) {
|
|
||||||
m_info->signal = stats.qual.level;
|
|
||||||
m_info->signal_max = range.max_qual.level;
|
|
||||||
m_info->flags |= wireless_flags::SIGNAL;
|
|
||||||
}
|
|
||||||
if (!(stats.qual.updated & IW_QUAL_NOISE_INVALID)) {
|
|
||||||
m_info->noise = stats.qual.noise;
|
|
||||||
m_info->noise_max = range.max_qual.noise;
|
|
||||||
m_info->flags |= wireless_flags::NOISE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (!(stats.qual.updated & IW_QUAL_QUAL_INVALID)) {
|
|
||||||
m_info->quality = stats.qual.qual;
|
|
||||||
m_info->flags |= wireless_flags::QUALITY;
|
|
||||||
}
|
|
||||||
if (!(stats.qual.updated & IW_QUAL_LEVEL_INVALID)) {
|
|
||||||
m_info->quality = stats.qual.level;
|
|
||||||
m_info->flags |= wireless_flags::SIGNAL;
|
|
||||||
}
|
|
||||||
if (!(stats.qual.updated & IW_QUAL_NOISE_INVALID)) {
|
|
||||||
m_info->quality = stats.qual.noise;
|
|
||||||
m_info->flags |= wireless_flags::NOISE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// struct iwreq wrq;
|
|
||||||
// if (iw_get_ext(socket_fd, ifname, SIOCGIWRATE, &wrq) != -1)
|
|
||||||
// m_info->bitrate = wrq.u.bitrate.value;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct iwreq m_iw;
|
|
||||||
shared_ptr<wireless_info> m_info;
|
shared_ptr<wireless_info> m_info;
|
||||||
|
string m_essid;
|
||||||
|
quality_range m_signalstrength;
|
||||||
|
quality_range m_linkquality;
|
||||||
};
|
};
|
||||||
|
|
||||||
// }}}
|
// }}}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test if interface with given name is a wireless device
|
||||||
|
*/
|
||||||
inline bool is_wireless_interface(string ifname) {
|
inline bool is_wireless_interface(string ifname) {
|
||||||
return file_util::exists("/sys/class/net/" + ifname + "/wireless");
|
return file_util::exists("/sys/class/net/" + ifname + "/wireless");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
using wireless_t = unique_ptr<wireless_network>;
|
||||||
|
using wired_t = unique_ptr<wired_network>;
|
||||||
}
|
}
|
||||||
|
|
||||||
LEMONBUDDY_NS_END
|
LEMONBUDDY_NS_END
|
||||||
|
@ -31,8 +31,6 @@
|
|||||||
#define PIPE_READ 0
|
#define PIPE_READ 0
|
||||||
#define PIPE_WRITE 1
|
#define PIPE_WRITE 1
|
||||||
|
|
||||||
#define LOG(m) std::cout << m << std::endl
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
#include "debug.hpp"
|
#include "debug.hpp"
|
||||||
#endif
|
#endif
|
||||||
|
@ -1,22 +1,17 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "adapters/net.hpp"
|
#include "adapters/net.hpp"
|
||||||
|
#include "components/config.hpp"
|
||||||
|
#include "drawtypes/animation.hpp"
|
||||||
#include "drawtypes/animation.hpp"
|
#include "drawtypes/animation.hpp"
|
||||||
#include "drawtypes/label.hpp"
|
#include "drawtypes/label.hpp"
|
||||||
#include "drawtypes/ramp.hpp"
|
#include "drawtypes/ramp.hpp"
|
||||||
#include "modules/meta.hpp"
|
#include "modules/meta.hpp"
|
||||||
|
|
||||||
#define DEFAULT_FORMAT_CONNECTED TAG_LABEL_CONNECTED
|
|
||||||
#define DEFAULT_FORMAT_DISCONNECTED TAG_LABEL_DISCONNECTED
|
|
||||||
#define DEFAULT_FORMAT_PACKETLOSS TAG_LABEL_CONNECTED
|
|
||||||
|
|
||||||
#define DEFAULT_LABEL_CONNECTED "%ifname% %local_ip%"
|
|
||||||
#define DEFAULT_LABEL_DISCONNECTED ""
|
|
||||||
#define DEFAULT_LABEL_PACKETLOSS ""
|
|
||||||
|
|
||||||
LEMONBUDDY_NS
|
LEMONBUDDY_NS
|
||||||
|
|
||||||
namespace modules {
|
namespace modules {
|
||||||
|
enum class connection_state { NONE = 0, CONNECTED, DISCONNECTED, PACKETLOSS };
|
||||||
|
|
||||||
class network_module : public timer_module<network_module> {
|
class network_module : public timer_module<network_module> {
|
||||||
public:
|
public:
|
||||||
@ -24,133 +19,119 @@ namespace modules {
|
|||||||
|
|
||||||
void setup() {
|
void setup() {
|
||||||
// Load configuration values
|
// Load configuration values
|
||||||
m_interface = m_conf.get<string>(name(), "interface");
|
REQ_CONFIG_VALUE(name(), m_interface, "interface");
|
||||||
|
GET_CONFIG_VALUE(name(), m_ping_nth_update, "ping-interval");
|
||||||
|
GET_CONFIG_VALUE(name(), m_udspeed_minwidth, "udspeed-minwidth");
|
||||||
|
|
||||||
m_interval = chrono::duration<double>(m_conf.get<float>(name(), "interval", 1));
|
m_interval = chrono::duration<double>(m_conf.get<float>(name(), "interval", 1));
|
||||||
m_ping_nth_update = m_conf.get<int>(name(), "ping-interval", 0);
|
|
||||||
m_udspeed_minwidth = m_conf.get<int>(name(), "udspeed-minwidth", m_udspeed_minwidth);
|
|
||||||
|
|
||||||
// Add formats
|
// Add formats
|
||||||
m_formatter->add(
|
m_formatter->add(
|
||||||
FORMAT_CONNECTED, DEFAULT_FORMAT_CONNECTED, {TAG_RAMP_SIGNAL, TAG_LABEL_CONNECTED});
|
FORMAT_CONNECTED, TAG_LABEL_CONNECTED, {TAG_RAMP_SIGNAL, TAG_RAMP_QUALITY, TAG_LABEL_CONNECTED});
|
||||||
m_formatter->add(FORMAT_DISCONNECTED, DEFAULT_FORMAT_DISCONNECTED, {TAG_LABEL_DISCONNECTED});
|
m_formatter->add(FORMAT_DISCONNECTED, TAG_LABEL_DISCONNECTED, {TAG_LABEL_DISCONNECTED});
|
||||||
|
|
||||||
// Create elements for format-connected
|
// Create elements for format-connected
|
||||||
if (m_formatter->has(TAG_RAMP_SIGNAL, FORMAT_CONNECTED))
|
if (m_formatter->has(TAG_RAMP_SIGNAL, FORMAT_CONNECTED))
|
||||||
m_ramp_signal = get_config_ramp(m_conf, name(), TAG_RAMP_SIGNAL);
|
m_ramp_signal = get_config_ramp(m_conf, name(), TAG_RAMP_SIGNAL);
|
||||||
|
if (m_formatter->has(TAG_RAMP_QUALITY, FORMAT_CONNECTED))
|
||||||
|
m_ramp_quality = get_config_ramp(m_conf, name(), TAG_RAMP_QUALITY);
|
||||||
if (m_formatter->has(TAG_LABEL_CONNECTED, FORMAT_CONNECTED)) {
|
if (m_formatter->has(TAG_LABEL_CONNECTED, FORMAT_CONNECTED)) {
|
||||||
m_label_connected =
|
m_label[connection_state::CONNECTED] =
|
||||||
get_optional_config_label(m_conf, name(), TAG_LABEL_CONNECTED, DEFAULT_LABEL_CONNECTED);
|
get_optional_config_label(m_conf, name(), TAG_LABEL_CONNECTED, "%ifname% %local_ip%");
|
||||||
m_label_connected_tokenized = m_label_connected->clone();
|
m_tokenized[connection_state::CONNECTED] =
|
||||||
|
m_label[connection_state::CONNECTED]->clone();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create elements for format-disconnected
|
// Create elements for format-disconnected
|
||||||
if (m_formatter->has(TAG_LABEL_DISCONNECTED, FORMAT_DISCONNECTED)) {
|
if (m_formatter->has(TAG_LABEL_DISCONNECTED, FORMAT_DISCONNECTED)) {
|
||||||
m_label_disconnected = get_optional_config_label(
|
m_label[connection_state::DISCONNECTED] =
|
||||||
m_conf, name(), TAG_LABEL_DISCONNECTED, DEFAULT_LABEL_DISCONNECTED);
|
get_optional_config_label(m_conf, name(), TAG_LABEL_DISCONNECTED, "");
|
||||||
m_label_disconnected->replace_token("%ifname%", m_interface);
|
m_label[connection_state::DISCONNECTED]->replace_token("%ifname%", m_interface);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create elements for format-packetloss if we are told to test connectivity
|
// Create elements for format-packetloss if we are told to test connectivity
|
||||||
if (m_ping_nth_update > 0) {
|
if (m_ping_nth_update > 0) {
|
||||||
m_formatter->add(FORMAT_PACKETLOSS, DEFAULT_FORMAT_PACKETLOSS,
|
m_formatter->add(FORMAT_PACKETLOSS, TAG_LABEL_CONNECTED,
|
||||||
{TAG_ANIMATION_PACKETLOSS, TAG_LABEL_PACKETLOSS, TAG_LABEL_CONNECTED});
|
{TAG_ANIMATION_PACKETLOSS, TAG_LABEL_PACKETLOSS, TAG_LABEL_CONNECTED});
|
||||||
|
|
||||||
if (m_formatter->has(TAG_LABEL_PACKETLOSS, FORMAT_PACKETLOSS)) {
|
if (m_formatter->has(TAG_LABEL_PACKETLOSS, FORMAT_PACKETLOSS)) {
|
||||||
m_label_packetloss = get_optional_config_label(
|
m_label[connection_state::PACKETLOSS] =
|
||||||
m_conf, name(), TAG_LABEL_PACKETLOSS, DEFAULT_LABEL_PACKETLOSS);
|
get_optional_config_label(m_conf, name(), TAG_LABEL_PACKETLOSS, "");
|
||||||
m_label_packetloss_tokenized = m_label_packetloss->clone();
|
m_tokenized[connection_state::PACKETLOSS] =
|
||||||
|
m_label[connection_state::PACKETLOSS]->clone();
|
||||||
}
|
}
|
||||||
if (m_formatter->has(TAG_ANIMATION_PACKETLOSS, FORMAT_PACKETLOSS))
|
if (m_formatter->has(TAG_ANIMATION_PACKETLOSS, FORMAT_PACKETLOSS))
|
||||||
m_animation_packetloss = get_config_animation(m_conf, name(), TAG_ANIMATION_PACKETLOSS);
|
m_animation_packetloss = get_config_animation(m_conf, name(), TAG_ANIMATION_PACKETLOSS);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get an intstance of the network interface
|
// Get an intstance of the network interface
|
||||||
if (net::is_wireless_interface(m_interface)) {
|
if (net::is_wireless_interface(m_interface))
|
||||||
m_wireless_network = make_unique<net::wireless_network>(m_interface);
|
m_wireless = net::wireless_t{new net::wireless_t::element_type(m_interface)};
|
||||||
} else {
|
else
|
||||||
m_wired_network = make_unique<net::wired_network>(m_interface);
|
m_wired = net::wired_t{new net::wired_t::element_type(m_interface)};
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void start() {
|
|
||||||
timer_module::start();
|
|
||||||
|
|
||||||
// We only need to start the subthread if the packetloss animation is used
|
// We only need to start the subthread if the packetloss animation is used
|
||||||
if (m_animation_packetloss)
|
if (m_animation_packetloss)
|
||||||
m_threads.emplace_back(thread(&network_module::subthread_routine, this));
|
m_threads.emplace_back(thread(&network_module::subthread_routine, this));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool update() {
|
bool update() {
|
||||||
string ip, essid, linkspeed;
|
net::network* network = m_wireless ? dynamic_cast<net::network*>(m_wireless.get())
|
||||||
int signal_quality = 0;
|
: dynamic_cast<net::network*>(m_wired.get());
|
||||||
|
|
||||||
net::network* network = nullptr;
|
if (!network->query()) {
|
||||||
|
m_log.warn("%s: Failed to query interface '%s'", name(), m_interface);
|
||||||
// Process data for wireless network interfaces
|
return false;
|
||||||
if (m_wireless_network) {
|
|
||||||
network = m_wireless_network.get();
|
|
||||||
|
|
||||||
try {
|
|
||||||
essid = m_wireless_network->essid();
|
|
||||||
signal_quality = m_wireless_network->signal_quality();
|
|
||||||
} catch (net::wireless_network_error& e) {
|
|
||||||
m_log.trace("%s: %s", name(), e.what());
|
|
||||||
}
|
|
||||||
|
|
||||||
m_signal_quality = signal_quality;
|
|
||||||
|
|
||||||
// Process data for wired network interfaces
|
|
||||||
} else if (m_wired_network) {
|
|
||||||
network = m_wired_network.get();
|
|
||||||
linkspeed = m_wired_network->link_speed();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (network != nullptr) {
|
try {
|
||||||
try {
|
if (m_wireless) {
|
||||||
ip = network->ip();
|
m_signal = m_wireless->signal();
|
||||||
} catch (net::network_error& e) {
|
m_quality = m_wireless->quality();
|
||||||
m_log.trace("%s: %s", name(), e.what());
|
|
||||||
}
|
|
||||||
|
|
||||||
m_connected = network->connected();
|
|
||||||
|
|
||||||
// Ignore the first run
|
|
||||||
if (m_counter == -1) {
|
|
||||||
m_counter = 0;
|
|
||||||
} else if (m_ping_nth_update > 0 && m_connected && (++m_counter % m_ping_nth_update) == 0) {
|
|
||||||
m_conseq_packetloss = !network->test();
|
|
||||||
m_counter = 0;
|
|
||||||
}
|
}
|
||||||
|
} catch (const net::network_error& err) {
|
||||||
|
m_log.warn("%s: Error getting interface data (%s)", name(), err.what());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_connected = network->connected();
|
||||||
|
|
||||||
|
// Ignore the first run
|
||||||
|
if (m_counter == -1) {
|
||||||
|
m_counter = 0;
|
||||||
|
} else if (m_ping_nth_update > 0 && m_connected && (++m_counter % m_ping_nth_update) == 0) {
|
||||||
|
m_packetloss = !network->ping();
|
||||||
|
m_counter = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto upspeed = network->upspeed(m_udspeed_minwidth);
|
||||||
|
auto downspeed = network->downspeed(m_udspeed_minwidth);
|
||||||
|
|
||||||
// Update label contents
|
// Update label contents
|
||||||
if (m_label_connected || m_label_packetloss) {
|
auto replace_tokens = [&](label_t& label) {
|
||||||
auto replace_tokens = [&](label_t label) {
|
label->replace_token("%ifname%", m_interface);
|
||||||
label->replace_token("%ifname%", m_interface);
|
label->replace_token("%local_ip%", network->ip());
|
||||||
label->replace_token("%local_ip%", !ip.empty() ? ip : "x.x.x.x");
|
label->replace_token("%upspeed%", upspeed);
|
||||||
|
label->replace_token("%downspeed%", downspeed);
|
||||||
|
|
||||||
if (m_wired_network) {
|
if (m_wired) {
|
||||||
label->replace_token("%linkspeed%", linkspeed);
|
label->replace_token("%linkspeed%", m_wired->linkspeed());
|
||||||
} else if (m_wireless_network) {
|
} else if (m_wireless) {
|
||||||
label->replace_token("%essid%", !essid.empty() ? essid : "UNKNOWN");
|
label->replace_token("%essid%", m_wireless->essid());
|
||||||
label->replace_token("%signal%", to_string(signal_quality) + "%");
|
label->replace_token("%signal%", to_string(m_signal) + "%");
|
||||||
}
|
label->replace_token("%quality%", to_string(m_quality) + "%");
|
||||||
|
|
||||||
auto upspeed = network->upspeed(m_udspeed_minwidth);
|
|
||||||
auto downspeed = network->downspeed(m_udspeed_minwidth);
|
|
||||||
|
|
||||||
label->replace_token("%upspeed%", upspeed);
|
|
||||||
label->replace_token("%downspeed%", downspeed);
|
|
||||||
};
|
|
||||||
|
|
||||||
if (m_label_connected) {
|
|
||||||
m_label_connected_tokenized->m_text = m_label_connected->m_text;
|
|
||||||
replace_tokens(m_label_connected_tokenized);
|
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
if (m_label_packetloss) {
|
if (m_label[connection_state::CONNECTED]) {
|
||||||
m_label_packetloss_tokenized->m_text = m_label_packetloss->m_text;
|
m_tokenized[connection_state::CONNECTED]->m_text =
|
||||||
replace_tokens(m_label_packetloss_tokenized);
|
m_label[connection_state::CONNECTED]->m_text;
|
||||||
}
|
replace_tokens(m_tokenized[connection_state::CONNECTED]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_label[connection_state::PACKETLOSS]) {
|
||||||
|
m_tokenized[connection_state::PACKETLOSS]->m_text =
|
||||||
|
m_label[connection_state::PACKETLOSS]->m_text;
|
||||||
|
replace_tokens(m_tokenized[connection_state::PACKETLOSS]);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -159,7 +140,7 @@ namespace modules {
|
|||||||
string get_format() {
|
string get_format() {
|
||||||
if (!m_connected)
|
if (!m_connected)
|
||||||
return FORMAT_DISCONNECTED;
|
return FORMAT_DISCONNECTED;
|
||||||
else if (m_conseq_packetloss && m_ping_nth_update > 0)
|
else if (m_packetloss && m_ping_nth_update > 0)
|
||||||
return FORMAT_PACKETLOSS;
|
return FORMAT_PACKETLOSS;
|
||||||
else
|
else
|
||||||
return FORMAT_CONNECTED;
|
return FORMAT_CONNECTED;
|
||||||
@ -167,15 +148,17 @@ namespace modules {
|
|||||||
|
|
||||||
bool build(builder* builder, string tag) {
|
bool build(builder* builder, string tag) {
|
||||||
if (tag == TAG_LABEL_CONNECTED)
|
if (tag == TAG_LABEL_CONNECTED)
|
||||||
builder->node(m_label_connected_tokenized);
|
builder->node(m_tokenized[connection_state::CONNECTED]);
|
||||||
else if (tag == TAG_LABEL_DISCONNECTED)
|
else if (tag == TAG_LABEL_DISCONNECTED)
|
||||||
builder->node(m_label_disconnected);
|
builder->node(m_label[connection_state::DISCONNECTED]);
|
||||||
else if (tag == TAG_LABEL_PACKETLOSS)
|
else if (tag == TAG_LABEL_PACKETLOSS)
|
||||||
builder->node(m_label_packetloss_tokenized);
|
builder->node(m_tokenized[connection_state::PACKETLOSS]);
|
||||||
else if (tag == TAG_ANIMATION_PACKETLOSS)
|
else if (tag == TAG_ANIMATION_PACKETLOSS)
|
||||||
builder->node(m_animation_packetloss->get());
|
builder->node(m_animation_packetloss->get());
|
||||||
else if (tag == TAG_RAMP_SIGNAL)
|
else if (tag == TAG_RAMP_SIGNAL)
|
||||||
builder->node(m_ramp_signal->get_by_percentage(m_signal_quality));
|
builder->node(m_ramp_signal->get_by_percentage(m_signal));
|
||||||
|
else if (tag == TAG_RAMP_QUALITY)
|
||||||
|
builder->node(m_ramp_quality->get_by_percentage(m_quality));
|
||||||
else
|
else
|
||||||
return false;
|
return false;
|
||||||
return true;
|
return true;
|
||||||
@ -185,13 +168,12 @@ namespace modules {
|
|||||||
void subthread_routine() {
|
void subthread_routine() {
|
||||||
this_thread::yield();
|
this_thread::yield();
|
||||||
|
|
||||||
const auto dur =
|
const chrono::milliseconds framerate{m_animation_packetloss->framerate()};
|
||||||
chrono::duration<double>(float(m_animation_packetloss->framerate()) / 1000.0f);
|
const auto dur = chrono::duration<double>(framerate);
|
||||||
|
|
||||||
while (enabled()) {
|
while (enabled()) {
|
||||||
if (m_connected && m_conseq_packetloss)
|
if (m_connected && m_packetloss)
|
||||||
broadcast();
|
broadcast();
|
||||||
|
|
||||||
sleep(dur);
|
sleep(dur);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -202,31 +184,31 @@ namespace modules {
|
|||||||
static constexpr auto FORMAT_CONNECTED = "format-connected";
|
static constexpr auto FORMAT_CONNECTED = "format-connected";
|
||||||
static constexpr auto FORMAT_PACKETLOSS = "format-packetloss";
|
static constexpr auto FORMAT_PACKETLOSS = "format-packetloss";
|
||||||
static constexpr auto FORMAT_DISCONNECTED = "format-disconnected";
|
static constexpr auto FORMAT_DISCONNECTED = "format-disconnected";
|
||||||
|
|
||||||
static constexpr auto TAG_RAMP_SIGNAL = "<ramp-signal>";
|
static constexpr auto TAG_RAMP_SIGNAL = "<ramp-signal>";
|
||||||
|
static constexpr auto TAG_RAMP_QUALITY = "<ramp-quality>";
|
||||||
static constexpr auto TAG_LABEL_CONNECTED = "<label-connected>";
|
static constexpr auto TAG_LABEL_CONNECTED = "<label-connected>";
|
||||||
static constexpr auto TAG_LABEL_DISCONNECTED = "<label-disconnected>";
|
static constexpr auto TAG_LABEL_DISCONNECTED = "<label-disconnected>";
|
||||||
static constexpr auto TAG_LABEL_PACKETLOSS = "<label-packetloss>";
|
static constexpr auto TAG_LABEL_PACKETLOSS = "<label-packetloss>";
|
||||||
static constexpr auto TAG_ANIMATION_PACKETLOSS = "<animation-packetloss>";
|
static constexpr auto TAG_ANIMATION_PACKETLOSS = "<animation-packetloss>";
|
||||||
|
|
||||||
unique_ptr<net::wired_network> m_wired_network;
|
net::wired_t m_wired;
|
||||||
unique_ptr<net::wireless_network> m_wireless_network;
|
net::wireless_t m_wireless;
|
||||||
|
|
||||||
ramp_t m_ramp_signal;
|
ramp_t m_ramp_signal;
|
||||||
|
ramp_t m_ramp_quality;
|
||||||
animation_t m_animation_packetloss;
|
animation_t m_animation_packetloss;
|
||||||
label_t m_label_connected;
|
map<connection_state, label_t> m_label;
|
||||||
label_t m_label_connected_tokenized;
|
map<connection_state, label_t> m_tokenized;
|
||||||
label_t m_label_disconnected;
|
|
||||||
label_t m_label_packetloss;
|
|
||||||
label_t m_label_packetloss_tokenized;
|
|
||||||
|
|
||||||
stateflag m_connected{false};
|
stateflag m_connected{false};
|
||||||
stateflag m_conseq_packetloss{false};
|
stateflag m_packetloss{false};
|
||||||
|
|
||||||
|
int m_signal = 0;
|
||||||
|
int m_quality = 0;
|
||||||
|
int m_counter = -1; // -1 to ignore the first run
|
||||||
|
|
||||||
string m_interface;
|
string m_interface;
|
||||||
int m_signal_quality;
|
int m_ping_nth_update = 0;
|
||||||
int m_ping_nth_update;
|
|
||||||
int m_counter = -1; // -1 to ignore the first run
|
|
||||||
int m_udspeed_minwidth = 3;
|
int m_udspeed_minwidth = 3;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user