Skip to content

Commit

Permalink
Network source will alert when network goes down
Browse files Browse the repository at this point in the history
Only transition from up to down is alerted.
If there are no initial network no alert will be triggered.
There is no "positive" alert from down to up, perhaps that is wanted..
  • Loading branch information
2hdddg committed Feb 9, 2024
1 parent 1ed6504 commit d2cc935
Show file tree
Hide file tree
Showing 5 changed files with 60 additions and 19 deletions.
58 changes: 47 additions & 11 deletions src/NetworkSource.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ static char *get_ip_str(const struct sockaddr *sa, char *s, size_t maxlen) {

return s;
}
std::shared_ptr<NetworkSource> NetworkSource::Create(MainLoop &mainLoop) {
std::shared_ptr<NetworkSource> NetworkSource::Create(std::shared_ptr<MainLoop> mainloop) {
auto sock = socket(PF_INET, SOCK_DGRAM, 0);
if (sock < 0) {
return nullptr;
Expand All @@ -47,12 +47,15 @@ std::shared_ptr<NetworkSource> NetworkSource::Create(MainLoop &mainLoop) {
spdlog::error("Failed to set timer: {}", strerror(errno));
return nullptr;
}
auto source = std::shared_ptr<NetworkSource>(new NetworkSource(sock, fd));
mainLoop.RegisterIoHandler(fd, "NetworkSource", source);
auto source = std::shared_ptr<NetworkSource>(new NetworkSource(mainloop, sock, fd));
mainloop->RegisterIoHandler(fd, "NetworkSource", source);
return source;
}

void NetworkSource::Initialize() { ReadState(); }
void NetworkSource::Initialize() {
ReadState();
m_drawn = m_published = false;
}

void NetworkSource::ReadState() {
char buf[8192] = {0};
Expand All @@ -65,7 +68,15 @@ void NetworkSource::ReadState() {
}
auto ifr = ifc.ifc_req;
auto nInterfaces = ifc.ifc_len / sizeof(struct ifreq);
Networks networks;
bool alerted = false;
bool changed = false;
// Note that only interfaces that are up is iterated here
// so to detect interfaces that were up but now is down, clear
// all interfaces first
for (auto &keyValue : m_networks) {
auto &network = keyValue.second;
network.isUp = false;
}
for (unsigned long i = 0; i < nInterfaces; i++) {
auto item = &ifr[i];
auto addr = &item->ifr_addr;
Expand All @@ -79,19 +90,44 @@ void NetworkSource::ReadState() {
}
// extended flags SIOCGIFPFLAGS
// SIOCGIWSTATS
NetworkState network = {};
NetworkState network = {.isAlerted = false};
network.isUp = (item->ifr_flags & IFF_UP) != 0;
// Get interface address
if (ioctl(m_socket, SIOCGIFADDR, item) < 0) {
continue;
}
network.interface = item->ifr_name;
network.address = get_ip_str(addr, ip, sizeof(ip));
networks.push_back(std::move(network));
if (m_networks.contains(item->ifr_name)) {
// Existing network. Might have changed from down -> up
// or changed address.
auto &existing = m_networks[item->ifr_name];
if (existing != network) {
changed = true;
m_networks[item->ifr_name] = std::move(network);
} else {
existing.isUp = true;
existing.isAlerted = false;
}
} else {
// New network
m_networks[item->ifr_name] = std::move(network);
changed = true;
// Is this an alert? A positive one perhaps.
}
}
// Check if there is any networks that has gone down
for (auto &keyValue : m_networks) {
auto &network = keyValue.second;
if (!network.isUp && !network.isAlerted) {
network.isAlerted = true;
alerted = true;
changed = true;
}
}
if (m_networks != networks) {
m_drawn = m_published = false;
m_networks = networks;
m_drawn = m_published = !changed;
if (alerted) {
spdlog::info("Network source is triggering alert");
m_mainloop->AlertAndWakeup();
}
}

Expand Down
8 changes: 5 additions & 3 deletions src/NetworkSource.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,18 @@

class NetworkSource : public Source, public IoHandler {
public:
static std::shared_ptr<NetworkSource> Create(MainLoop& mainLoop);
static std::shared_ptr<NetworkSource> Create(std::shared_ptr<MainLoop> mainloop);
void Initialize();
void ReadState();
virtual bool OnRead() override;
void Publish(const std::string_view sourceName, ScriptContext& scriptContext) override;
virtual ~NetworkSource() { close(m_timerfd); }

private:
NetworkSource(int socket, int timerfd) : Source(), m_socket(socket), m_timerfd(timerfd) {}
NetworkSource(std::shared_ptr<MainLoop> mainloop, int socket, int timerfd)
: Source(), m_mainloop(mainloop), m_socket(socket), m_timerfd(timerfd) {}
void ReadState();

std::shared_ptr<MainLoop> m_mainloop;
int m_socket;
int m_timerfd;
std::shared_ptr<ScriptContext> m_scriptContext;
Expand Down
6 changes: 4 additions & 2 deletions src/ScriptContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -379,10 +379,12 @@ void ScriptContextImpl::Publish(const std::string_view name, const KeyboardState
}
void ScriptContextImpl::Publish(const std::string_view name, const Networks& networks) {
auto networksTable = m_lua.create_table();
for (const auto& network : networks) {
for (const auto& keyValue : networks) {
const auto& interface = keyValue.first;
const auto& network = keyValue.second;
auto networkTable = m_lua.create_table();
networkTable["up"] = network.isUp;
networkTable["interface"] = network.interface;
networkTable["interface"] = interface;
networkTable["address"] = network.address;
networksTable.add(networkTable);
}
Expand Down
5 changes: 3 additions & 2 deletions src/ScriptContext.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#pragma once

#include <map>
#include <memory>

#include "src/Configuration.h"
Expand Down Expand Up @@ -61,15 +62,15 @@ struct KeyboardState {
};

struct NetworkState {
bool isAlerted;
bool isUp;
std::string interface;
std::string address;
// type (eth, wifi)
// wifi strength

auto operator<=>(const NetworkState& other) const = default;
};
using Networks = std::vector<NetworkState>;
using Networks = std::map<std::string, NetworkState>;

class ScriptContext {
public:
Expand Down
2 changes: 1 addition & 1 deletion src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ static void InitializeSource(const std::string& source, Sources& sources,
return;
}
if (source == "networks") {
auto networkSource = NetworkSource::Create(*mainLoop);
auto networkSource = NetworkSource::Create(mainLoop);
if (!networkSource) {
spdlog::error("Failed to initialize network source");
return;
Expand Down

0 comments on commit d2cc935

Please sign in to comment.