mirror of
https://github.com/polybar/polybar.git
synced 2026-02-10 06:55:53 +00:00
- use "#pragma once" instead of the regular include guard - fix errors and warnings reported by cppcheck
169 lines
3.9 KiB
C++
169 lines
3.9 KiB
C++
#include <arpa/inet.h>
|
|
#include <cerrno>
|
|
#include <cstdio>
|
|
#include <cstring>
|
|
#include <fstream>
|
|
#include <iostream>
|
|
#include <memory>
|
|
#include <netinet/in.h>
|
|
#include <sstream>
|
|
#include <string>
|
|
#include <sys/socket.h>
|
|
#include <signal.h>
|
|
|
|
#include "config.hpp"
|
|
#include "services/logger.hpp"
|
|
#include "interfaces/net.hpp"
|
|
#include "utils/io.hpp"
|
|
#include "utils/macros.hpp"
|
|
#include "utils/string.hpp"
|
|
|
|
using namespace net;
|
|
|
|
bool net::is_wireless_interface(const std::string& ifname) {
|
|
return io::file::exists("/sys/class/net/"+ ifname +"/wireless");
|
|
}
|
|
|
|
|
|
// Network
|
|
|
|
Network::Network(const std::string& interface)
|
|
: interface(interface)
|
|
{
|
|
if (if_nametoindex(this->interface.c_str()) == 0)
|
|
throw NetworkException("Invalid network interface \""+ this->interface +"\"");
|
|
|
|
if ((this->fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
|
|
throw NetworkException("Failed to open socket: "+ StrErrno());
|
|
|
|
std::memset(&this->data, 0, sizeof(this->data));
|
|
std::strncpy(this->data.ifr_name, this->interface.data(), IFNAMSIZ-1);
|
|
}
|
|
|
|
Network::~Network()
|
|
{
|
|
if (close(this->fd) == -1)
|
|
log_error("Failed to close Network socket FD: "+ StrErrno());
|
|
}
|
|
|
|
bool Network::test_interface()
|
|
{
|
|
if ((ioctl(this->fd, SIOCGIFFLAGS, &this->data)) == -1)
|
|
throw NetworkException(StrErrno());
|
|
return this->data.ifr_flags & IFF_UP;
|
|
}
|
|
|
|
bool Network::test_connection()
|
|
{
|
|
int status = EXIT_FAILURE;
|
|
|
|
try {
|
|
this->ping = std::make_unique<Command>(
|
|
"ping -c 2 -W 2 -I "+ this->interface +" " + std::string(CONNECTION_TEST_IP));
|
|
|
|
status = this->ping->exec(true);
|
|
|
|
this->ping.reset();
|
|
} catch (CommandException &e) {
|
|
log_error(e.what());
|
|
} catch (proc::ExecFailure &e) {
|
|
log_error(e.what());
|
|
}
|
|
|
|
return (status == EXIT_SUCCESS);
|
|
}
|
|
|
|
bool Network::test()
|
|
{
|
|
try {
|
|
return this->test_interface() && this->test_connection();
|
|
} catch (NetworkException &e) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
bool Network::connected()
|
|
{
|
|
try {
|
|
return this->test_interface() &&
|
|
io::file::get_contents("/sys/class/net/"+ this->interface +"/carrier")[0] == '1';
|
|
} catch (NetworkException &e) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
std::string Network::get_ip()
|
|
{
|
|
if (!this->test_interface())
|
|
throw NetworkException("Interface is not up");
|
|
|
|
this->data.ifr_addr.sa_family = AF_INET;
|
|
|
|
if (ioctl(this->fd, SIOCGIFADDR, &this->data) == -1)
|
|
throw NetworkException(StrErrno());
|
|
|
|
return inet_ntoa(((struct sockaddr_in *) &this->data.ifr_addr)->sin_addr);
|
|
}
|
|
|
|
|
|
// WiredNetwork
|
|
|
|
WiredNetwork::WiredNetwork(const std::string& interface) : Network(interface)
|
|
{
|
|
struct ethtool_cmd e;
|
|
|
|
e.cmd = ETHTOOL_GSET;
|
|
|
|
this->data.ifr_data = (caddr_t) &e;
|
|
|
|
if (ioctl(this->fd, SIOCETHTOOL, &this->data) == 0)
|
|
this->linkspeed = (e.speed == USHRT_MAX ? 0 : e.speed);
|
|
}
|
|
|
|
std::string WiredNetwork::get_link_speed() {
|
|
return std::string((this->linkspeed == 0 ? "???" : std::to_string(this->linkspeed)) +" Mbit/s");
|
|
}
|
|
|
|
|
|
// WirelessNetwork
|
|
|
|
WirelessNetwork::WirelessNetwork(const std::string& interface) : Network(interface) {
|
|
std::strcpy((char *) &this->iw.ifr_ifrn.ifrn_name, this->interface.c_str());
|
|
}
|
|
|
|
std::string WirelessNetwork::get_essid()
|
|
{
|
|
char essid[IW_ESSID_MAX_SIZE+1];
|
|
|
|
std::memset(&essid, 0, IW_ESSID_MAX_SIZE + 1);
|
|
|
|
this->iw.u.essid.pointer = &essid;
|
|
this->iw.u.essid.length = sizeof(essid);
|
|
|
|
if (ioctl(this->fd, SIOCGIWESSID, &this->iw) == -1)
|
|
throw WirelessNetworkException(StrErrno());
|
|
|
|
return string::trim(essid, ' ');
|
|
}
|
|
|
|
float WirelessNetwork::get_signal_quality()
|
|
{
|
|
auto dbm = this->get_signal_dbm();
|
|
return 2 * (dbm + 100);
|
|
}
|
|
|
|
float WirelessNetwork::get_signal_dbm()
|
|
{
|
|
this->iw.u.data.pointer = (iw_statistics *) std::malloc(sizeof(iw_statistics));
|
|
this->iw.u.data.length = sizeof(iw_statistics);
|
|
|
|
if (ioctl(this->fd, SIOCGIWSTATS, &this->iw) == -1)
|
|
throw WirelessNetworkException(StrErrno());
|
|
|
|
auto signal = ((iw_statistics *) this->iw.u.data.pointer)->qual.level - 256;
|
|
|
|
std::free(this->iw.u.data.pointer);
|
|
|
|
return signal;
|
|
}
|