#pragma once #include #include "event_bus.h" #include "service.h" #include "services/clock_service.h" #include "services/storage_service.h" #include "services/wifi_service.h" #include "settings.h" #include "wg_config.h" namespace roro { // The WireGuard tunnel (issue #8, docs/milestones/N1.md): one peer, IPv4, over whatever Wi-Fi the // device is on. The protocol is the `esphome/wireguard` library's; this decides when the tunnel // is up, takes lwIP's lock around every call into it (the library takes none), and puts the // tunnel's DNS servers in and out. // // It starts once Wi-Fi is connected and the clock is set: a handshake carries the time, and a // server refuses one older than the last it saw from this key. class VpnService : public Service { public: enum class State { NoConfig, Off, WaitingWifi, WaitingClock, Resolving, Trying, Up }; VpnService(Settings& settings, WifiService& wifi, ClockService& clock, EventBus& bus) : settings_(settings), wifi_(wifi), clock_(clock), bus_(bus) {} const char* name() const override { return "vpn"; } void start() override; void stop() override { takeDown(); } void tick(uint32_t nowMs) override; State state() const { return state_; } const char* stateText() const; bool configured() const { return configured_; } const net::WgConfig& config() const { return config_; } // its keys are for the library only bool wanted() const { return wanted_; } // On or off, until the next restart; `seconds`: on for that long, then off by itself (for // trying a configuration from afar, when a wrong one would cut the connection it was sent over). void want(bool on, uint32_t seconds = 0); // A `.conf`'s text, or the file itself. "" or why it wasn't taken. A tunnel that is up starts // again with the new one. std::string import(const std::string& confText); std::string importFile(StorageService& storage, const std::string& path); void forget(); bool dnsThroughIt() const; // the tunnel's DNS servers are the ones in use int64_t lastHandshake() const { return lastHandshake_; } // UTC seconds, 0: none yet const std::string& lastError() const { return error_; } private: struct Tunnel; // the library's structures, kept out of this header void bringUp(); void takeDown(); void loadConfig(); void keepDns(); // puts the tunnel's servers back in if a DHCP renewal replaced them Settings& settings_; WifiService& wifi_; ClockService& clock_; EventBus& bus_; net::WgConfig config_; bool configured_ = false, wanted_ = false, announced_ = false; State state_ = State::NoConfig; Tunnel* tunnel_ = nullptr; uint32_t untilMs_ = 0, retryMs_ = 0; bool timed_ = false; int64_t lastHandshake_ = 0; std::string error_; }; } // namespace roro