diff --git a/CMakeLists.txt b/CMakeLists.txt index 8a833d43..76912dce 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,5 @@ cmake_minimum_required(VERSION 3.13) -project(owgw VERSION 2.6.0) +project(owgw VERSION 2.7.0) set(CMAKE_CXX_STANDARD 17) @@ -105,7 +105,7 @@ add_executable( owgw src/storage/storage_tables.cpp src/RESTAPI/RESTAPI_routers.cpp src/Daemon.cpp src/Daemon.h - src/WS_Server.cpp src/WS_Server.h + src/AP_WS_Server.cpp src/AP_WS_Server.h src/StorageService.cpp src/StorageService.h src/DeviceRegistry.cpp src/DeviceRegistry.h src/CommandManager.cpp src/CommandManager.h @@ -118,7 +118,7 @@ add_executable( owgw src/TelemetryStream.cpp src/TelemetryStream.h src/framework/ConfigurationValidator.cpp src/framework/ConfigurationValidator.h src/ConfigurationCache.h - src/CapabilitiesCache.h src/FindCountry.h src/rttys/RTTYS_server.cpp src/rttys/RTTYS_server.h src/rttys/RTTYS_device.cpp src/rttys/RTTYS_device.h src/rttys/RTTYS_ClientConnection.cpp src/rttys/RTTYS_ClientConnection.h src/rttys/RTTYS_WebServer.cpp src/rttys/RTTYS_WebServer.h src/RESTAPI/RESTAPI_device_helper.h src/SDKcalls.cpp src/SDKcalls.h src/StateUtils.cpp src/StateUtils.h src/WS_ReactorPool.h src/WS_Connection.h src/WS_Connection.cpp src/TelemetryClient.h src/TelemetryClient.cpp src/RESTAPI/RESTAPI_iptocountry_handler.cpp src/RESTAPI/RESTAPI_iptocountry_handler.h src/framework/ow_constants.h src/GwWebSocketClient.cpp src/GwWebSocketClient.h src/framework/WebSocketClientNotifications.h src/RADIUS_proxy_server.cpp src/RADIUS_proxy_server.h src/RESTAPI/RESTAPI_radiusProxyConfig_handler.cpp src/RESTAPI/RESTAPI_radiusProxyConfig_handler.h src/ParseWifiScan.h src/RADIUS_helpers.h src/VenueBroadcaster.h src/sdks/sdk_prov.h) + src/CapabilitiesCache.h src/FindCountry.h src/rttys/RTTYS_server.cpp src/rttys/RTTYS_server.h src/rttys/RTTYS_device.cpp src/rttys/RTTYS_device.h src/rttys/RTTYS_ClientConnection.cpp src/rttys/RTTYS_ClientConnection.h src/rttys/RTTYS_WebServer.cpp src/rttys/RTTYS_WebServer.h src/RESTAPI/RESTAPI_device_helper.h src/SDKcalls.cpp src/SDKcalls.h src/StateUtils.cpp src/StateUtils.h src/WS_ReactorPool.h src/AP_WS_Connection.h src/AP_WS_Connection.cpp src/TelemetryClient.h src/TelemetryClient.cpp src/RESTAPI/RESTAPI_iptocountry_handler.cpp src/RESTAPI/RESTAPI_iptocountry_handler.h src/framework/ow_constants.h src/GwWebSocketClient.cpp src/GwWebSocketClient.h src/framework/WebSocketClientNotifications.h src/RADIUS_proxy_server.cpp src/RADIUS_proxy_server.h src/RESTAPI/RESTAPI_radiusProxyConfig_handler.cpp src/RESTAPI/RESTAPI_radiusProxyConfig_handler.h src/ParseWifiScan.h src/RADIUS_helpers.h src/VenueBroadcaster.h src/sdks/sdk_prov.h) if(NOT SMALL_BUILD) diff --git a/build b/build index c663e4d0..e440e5c8 100644 --- a/build +++ b/build @@ -1 +1 @@ -151 \ No newline at end of file +3 \ No newline at end of file diff --git a/src/WS_Connection.cpp b/src/AP_WS_Connection.cpp similarity index 91% rename from src/WS_Connection.cpp rename to src/AP_WS_Connection.cpp index 592e5c51..8d53caa6 100644 --- a/src/WS_Connection.cpp +++ b/src/AP_WS_Connection.cpp @@ -2,7 +2,7 @@ // Created by stephane bourque on 2022-02-03. // -#include "WS_Connection.h" +#include "AP_WS_Connection.h" #include "Poco/Net/SecureStreamSocketImpl.h" #include "Poco/Net/SecureServerSocketImpl.h" @@ -17,30 +17,34 @@ #include "Poco/zlib.h" -#include "WS_Server.h" -#include "StorageService.h" +#include "AP_WS_Server.h" +#include "CentralConfig.h" #include "CommandManager.h" -#include "StateUtils.h" #include "ConfigurationCache.h" #include "Daemon.h" -#include "TelemetryStream.h" -#include "CentralConfig.h" #include "FindCountry.h" +#include "StateUtils.h" +#include "StorageService.h" +#include "TelemetryStream.h" #include "VenueBroadcaster.h" #include "framework/WebSocketClientNotifications.h" +#include "Poco/Net/WebSocketImpl.h" #include "RADIUS_proxy_server.h" namespace OpenWifi { - void WSConnection::LogException(const Poco::Exception &E) { + void AP_WS_Connection::LogException(const Poco::Exception &E) { Logger().information(fmt::format("EXCEPTION({}): {}", CId_, E.displayText())); } - void WSConnection::CompleteStartup() { + void AP_WS_Connection::CompleteStartup() { + std::lock_guard Guard(Mutex_); try { - auto SS = dynamic_cast(Socket_.impl()); + auto SockImpl = dynamic_cast(WS_->impl()); + auto SS = dynamic_cast(SockImpl->streamSocketImpl()); + while (true) { auto V = SS->completeHandshake(); if (V == 1) @@ -60,7 +64,7 @@ namespace OpenWifi { try { Poco::Crypto::X509Certificate PeerCert(SS->peerCertificate()); - if (WebSocketServer()->ValidateCertificate(CId_, PeerCert)) { + if (AP_WS_Server()->ValidateCertificate(CId_, PeerCert)) { CN_ = Poco::trim(Poco::toLower(PeerCert.commonName())); CertValidation_ = GWObjects::MISMATCH_SERIAL; poco_trace(Logger(),fmt::format("{}: Valid certificate: CN={}", CId_, CN_)); @@ -74,7 +78,7 @@ namespace OpenWifi { poco_error(Logger(),fmt::format("{}: No certificates available..", CId_)); } - if (WebSocketServer::IsSim(CN_) && !WebSocketServer()->IsSimEnabled()) { + if (AP_WS_Server::IsSim(CN_) && !AP_WS_Server()->IsSimEnabled()) { Logger().debug(fmt::format( "CONNECTION({}): Sim Device {} is not allowed. Disconnecting.", CId_, CN_)); delete this; @@ -89,32 +93,20 @@ namespace OpenWifi { CId_, CN_)); return delete this; } - auto Params = Poco::AutoPtr(new Poco::Net::HTTPServerParams); - Poco::Net::HTTPServerSession Session(Socket_, Params); - Poco::Net::HTTPServerResponseImpl Response(Session); - Poco::Net::HTTPServerRequestImpl Request(Response, Session, Params); - - auto now = OpenWifi::Now(); - Response.setDate(now); - Response.setVersion(Request.getVersion()); - Response.setKeepAlive(Params->getKeepAlive() && Request.getKeepAlive() && - Session.canKeepAlive()); - WS_ = std::make_unique(Request, Response); WS_->setMaxPayloadSize(BufSize); auto TS = Poco::Timespan(360, 0); - WS_->setReceiveTimeout(TS); WS_->setNoDelay(true); WS_->setKeepAlive(true); Reactor_.addEventHandler(*WS_, - Poco::NObserver( - *this, &WSConnection::OnSocketReadable)); + Poco::NObserver( + *this, &AP_WS_Connection::OnSocketReadable)); Reactor_.addEventHandler(*WS_, - Poco::NObserver( - *this, &WSConnection::OnSocketShutdown)); - Reactor_.addEventHandler(*WS_, Poco::NObserver( - *this, &WSConnection::OnSocketError)); + Poco::NObserver( + *this, &AP_WS_Connection::OnSocketShutdown)); + Reactor_.addEventHandler(*WS_, Poco::NObserver( + *this, &AP_WS_Connection::OnSocketError)); Registered_ = true; poco_debug(Logger(),fmt::format("CONNECTION({}): completed.", CId_)); return; @@ -154,13 +146,13 @@ namespace OpenWifi { return delete this; } - WSConnection::WSConnection(Poco::Net::StreamSocket &socket, [[maybe_unused]] Poco::Net::SocketReactor &reactor) - : Logger_(WebSocketServer()->Logger()) , - Socket_(socket), - Reactor_(ReactorThreadPool()->NextReactor()) - { - std::thread T([=]() { CompleteStartup(); }); - T.detach(); + AP_WS_Connection::AP_WS_Connection(Poco::Net::HTTPServerRequest &request, + Poco::Net::HTTPServerResponse &response) + : Logger_(AP_WS_Server()->Logger()) , + Reactor_(AP_WS_Server()->NextReactor()) + { + WS_ = std::make_unique(request,response); + CompleteStartup(); } static void NotifyKafkaDisconnect(const std::string & SerialNumber) { @@ -178,7 +170,7 @@ namespace OpenWifi { } } - WSConnection::~WSConnection() { + AP_WS_Connection::~AP_WS_Connection() { poco_debug(Logger(),fmt::format("{}: Removing connection for {}.", CId_, SerialNumber_)); if (ConnectionId_) @@ -186,19 +178,17 @@ namespace OpenWifi { if (Registered_ && WS_) { Reactor_.removeEventHandler(*WS_, - Poco::NObserver( - *this, &WSConnection::OnSocketReadable)); + Poco::NObserver( + *this, &AP_WS_Connection::OnSocketReadable)); Reactor_.removeEventHandler(*WS_, - Poco::NObserver( - *this, &WSConnection::OnSocketShutdown)); + Poco::NObserver( + *this, &AP_WS_Connection::OnSocketShutdown)); Reactor_.removeEventHandler(*WS_, - Poco::NObserver( - *this, &WSConnection::OnSocketError)); + Poco::NObserver( + *this, &AP_WS_Connection::OnSocketError)); (*WS_).close(); - Socket_.shutdown(); } else if (WS_) { (*WS_).close(); - Socket_.shutdown(); } if (KafkaManager()->Enabled() && !SerialNumber_.empty()) { @@ -210,7 +200,7 @@ namespace OpenWifi { WebSocketClientNotificationDeviceDisconnected(SerialNumber_); } - bool WSConnection::LookForUpgrade(const uint64_t UUID, uint64_t & UpgradedUUID) { + bool AP_WS_Connection::LookForUpgrade(const uint64_t UUID, uint64_t & UpgradedUUID) { // A UUID of zero means ignore updates for that connection. if (UUID == 0) @@ -276,11 +266,11 @@ namespace OpenWifi { return false; } - void WSConnection::ProcessJSONRPCResult(Poco::JSON::Object::Ptr Doc) { + void AP_WS_Connection::ProcessJSONRPCResult(Poco::JSON::Object::Ptr Doc) { CommandManager()->PostCommandResult(SerialNumber_, *Doc); } - void WSConnection::ProcessJSONRPCEvent(Poco::JSON::Object::Ptr &Doc) { + void AP_WS_Connection::ProcessJSONRPCEvent(Poco::JSON::Object::Ptr &Doc) { auto Method = Doc->get(uCentralProtocol::METHOD).toString(); auto EventType = uCentralProtocol::Events::EventFromString(Method); @@ -373,7 +363,7 @@ namespace OpenWifi { CId_ = SerialNumber_ + "@" + CId_; // We need to verify the certificate if we have one if ((!CN_.empty() && Utils::SerialNumberMatch(CN_, SerialNumber_)) || - WebSocketServer()->IsSimSerialNumber(CN_)) { + AP_WS_Server()->IsSimSerialNumber(CN_)) { CertValidation_ = GWObjects::VERIFIED; poco_information(Logger(), fmt::format("CONNECT({}): Fully validated and authenticated device.", CId_)); } else { @@ -774,7 +764,7 @@ namespace OpenWifi { } } - bool WSConnection::StartTelemetry() { + bool AP_WS_Connection::StartTelemetry() { // std::cout << "Start telemetry for " << SerialNumber_ << std::endl; poco_information(Logger(), fmt::format("TELEMETRY({}): Starting.", CId_)); Poco::JSON::Object StartMessage; @@ -797,7 +787,7 @@ namespace OpenWifi { return true; } - bool WSConnection::StopTelemetry() { + bool AP_WS_Connection::StopTelemetry() { // std::cout << "Stop telemetry for " << SerialNumber_ << std::endl; poco_information(Logger(), fmt::format("TELEMETRY({}): Stopping.", CId_)); Poco::JSON::Object StopMessage; @@ -817,14 +807,14 @@ namespace OpenWifi { return true; } - void WSConnection::UpdateCounts() { + void AP_WS_Connection::UpdateCounts() { if (Conn_) { Conn_->Conn_.kafkaClients = TelemetryKafkaRefCount_; Conn_->Conn_.webSocketClients = TelemetryWebSocketRefCount_; } } - bool WSConnection::SetWebSocketTelemetryReporting(uint64_t Interval, + bool AP_WS_Connection::SetWebSocketTelemetryReporting(uint64_t Interval, uint64_t LifeTime) { std::lock_guard G(Mutex_); TelemetryWebSocketRefCount_++; @@ -839,7 +829,7 @@ namespace OpenWifi { return true; } - bool WSConnection::SetKafkaTelemetryReporting(uint64_t Interval, uint64_t LifeTime) { + bool AP_WS_Connection::SetKafkaTelemetryReporting(uint64_t Interval, uint64_t LifeTime) { std::lock_guard G(Mutex_); TelemetryKafkaRefCount_++; TelemetryInterval_ = TelemetryInterval_ ? std::min(Interval, TelemetryInterval_) : Interval; @@ -853,7 +843,7 @@ namespace OpenWifi { return true; } - bool WSConnection::StopWebSocketTelemetry() { + bool AP_WS_Connection::StopWebSocketTelemetry() { std::lock_guard G(Mutex_); if (TelemetryWebSocketRefCount_) TelemetryWebSocketRefCount_--; @@ -865,7 +855,7 @@ namespace OpenWifi { return true; } - bool WSConnection::StopKafkaTelemetry() { + bool AP_WS_Connection::StopKafkaTelemetry() { std::lock_guard G(Mutex_); if (TelemetryKafkaRefCount_) TelemetryKafkaRefCount_--; @@ -877,19 +867,19 @@ namespace OpenWifi { return true; } - void WSConnection::OnSocketShutdown([[maybe_unused]] const Poco::AutoPtr &pNf) { + void AP_WS_Connection::OnSocketShutdown([[maybe_unused]] const Poco::AutoPtr &pNf) { std::lock_guard Guard(Mutex_); poco_trace(Logger(), fmt::format("SOCKET-SHUTDOWN({}): Closing.", CId_)); delete this; } - void WSConnection::OnSocketError([[maybe_unused]] const Poco::AutoPtr &pNf) { + void AP_WS_Connection::OnSocketError([[maybe_unused]] const Poco::AutoPtr &pNf) { std::lock_guard Guard(Mutex_); poco_trace(Logger(), fmt::format("SOCKET-ERROR({}): Closing.", CId_)); delete this; } - void WSConnection::OnSocketReadable([[maybe_unused]] const Poco::AutoPtr &pNf) { + void AP_WS_Connection::OnSocketReadable([[maybe_unused]] const Poco::AutoPtr &pNf) { std::lock_guard Guard(Mutex_); try { ProcessIncomingFrame(); @@ -914,7 +904,7 @@ namespace OpenWifi { return ""; } - void WSConnection::ProcessIncomingFrame() { + void AP_WS_Connection::ProcessIncomingFrame() { // bool MustDisconnect=false; Poco::Buffer IncomingFrame(0); @@ -1082,7 +1072,7 @@ namespace OpenWifi { delete this; } - bool WSConnection::Send(const std::string &Payload) { + bool AP_WS_Connection::Send(const std::string &Payload) { std::lock_guard Guard(Mutex_); size_t BytesSent = WS_->sendFrame(Payload.c_str(), (int)Payload.size()); @@ -1103,7 +1093,7 @@ namespace OpenWifi { return ofs.str(); } - bool WSConnection::SendRadiusAuthenticationData(const unsigned char * buffer, std::size_t size) { + bool AP_WS_Connection::SendRadiusAuthenticationData(const unsigned char * buffer, std::size_t size) { Poco::JSON::Object Answer; Answer.set(uCentralProtocol::RADIUS,uCentralProtocol::RADIUSAUTH); Answer.set(uCentralProtocol::RADIUSDATA, Base64Encode(buffer,size)); @@ -1113,7 +1103,7 @@ namespace OpenWifi { return Send(Payload.str()); } - bool WSConnection::SendRadiusAccountingData(const unsigned char * buffer, std::size_t size) { + bool AP_WS_Connection::SendRadiusAccountingData(const unsigned char * buffer, std::size_t size) { Poco::JSON::Object Answer; Answer.set(uCentralProtocol::RADIUS,uCentralProtocol::RADIUSACCT); Answer.set(uCentralProtocol::RADIUSDATA, Base64Encode(buffer,size)); @@ -1123,7 +1113,7 @@ namespace OpenWifi { return Send(Payload.str()); } - bool WSConnection::SendRadiusCoAData(const unsigned char * buffer, std::size_t size) { + bool AP_WS_Connection::SendRadiusCoAData(const unsigned char * buffer, std::size_t size) { Poco::JSON::Object Answer; Answer.set(uCentralProtocol::RADIUS,uCentralProtocol::RADIUSCOA); Answer.set(uCentralProtocol::RADIUSDATA, Base64Encode(buffer,size)); @@ -1133,7 +1123,7 @@ namespace OpenWifi { return Send(Payload.str()); } - void WSConnection::ProcessIncomingRadiusData(const Poco::JSON::Object::Ptr &Doc) { + void AP_WS_Connection::ProcessIncomingRadiusData(const Poco::JSON::Object::Ptr &Doc) { if( Doc->has(uCentralProtocol::RADIUSDATA)) { auto Type = Doc->get(uCentralProtocol::RADIUS).toString(); if(Type==uCentralProtocol::RADIUSACCT) { diff --git a/src/WS_Connection.h b/src/AP_WS_Connection.h similarity index 95% rename from src/WS_Connection.h rename to src/AP_WS_Connection.h index 09d18e1d..7cc1d6b1 100644 --- a/src/WS_Connection.h +++ b/src/AP_WS_Connection.h @@ -17,11 +17,12 @@ namespace OpenWifi { -class WSConnection { +class AP_WS_Connection { static constexpr int BufSize = 128000; public: - WSConnection(Poco::Net::StreamSocket& Socket, Poco::Net::SocketReactor& Reactor); - ~WSConnection(); + AP_WS_Connection(Poco::Net::HTTPServerRequest &request, + Poco::Net::HTTPServerResponse &response); + ~AP_WS_Connection(); void ProcessJSONRPCEvent(Poco::JSON::Object::Ptr & Doc); void ProcessJSONRPCResult(Poco::JSON::Object::Ptr Doc); @@ -64,7 +65,6 @@ class WSConnection { private: std::recursive_mutex Mutex_; Poco::Logger &Logger_; - Poco::Net::StreamSocket Socket_; Poco::Net::SocketReactor & Reactor_; std::unique_ptr WS_; std::string SerialNumber_; diff --git a/src/AP_WS_Server.cpp b/src/AP_WS_Server.cpp new file mode 100644 index 00000000..c828bcd9 --- /dev/null +++ b/src/AP_WS_Server.cpp @@ -0,0 +1,102 @@ +// +// License type: BSD 3-Clause License +// License copy: https://github.com/Telecominfraproject/wlan-cloud-ucentralgw/blob/master/LICENSE +// +// Created by Stephane Bourque on 2021-03-04. +// Arilia Wireless Inc. +// + +#include "Poco/Net/HTTPHeaderStream.h" +#include "Poco/JSON/Array.h" +#include "Poco/Net/Context.h" + +#include "AP_WS_Server.h" +#include "ConfigurationCache.h" +#include "TelemetryStream.h" +#include + +namespace OpenWifi { + + void AP_WS_RequestHandler::handleRequest(Poco::Net::HTTPServerRequest &request, + Poco::Net::HTTPServerResponse &response) { + try { + new AP_WS_Connection(request,response); + } catch (...) { + Logger_.warning("Exception during WS creation"); + } + }; + + bool AP_WS_Server::ValidateCertificate(const std::string & ConnectionId, const Poco::Crypto::X509Certificate & Certificate) { + if(IsCertOk()) { + Logger().debug(fmt::format("CERTIFICATE({}): issuer='{}' cn='{}'", ConnectionId, Certificate.issuerName(),Certificate.commonName())); + if(!Certificate.issuedBy(*IssuerCert_)) { + Logger().debug(fmt::format("CERTIFICATE({}): issuer mismatch. Local='{}' Incoming='{}'", ConnectionId, IssuerCert_->issuerName(), Certificate.issuerName())); + return false; + } + return true; + } + return false; + } + + int AP_WS_Server::Start() { + + for(const auto & Svr : ConfigServersList_ ) { + Logger().notice(fmt::format("Starting: {}:{} Keyfile:{} CertFile: {}", Svr.Address(), + Svr.Port(), Svr.KeyFile(), Svr.CertFile())); + + Svr.LogCert(Logger()); + if (!Svr.RootCA().empty()) + Svr.LogCas(Logger()); + + auto Sock{Svr.CreateSecureSocket(Logger())}; + + if (!IsCertOk()) { + IssuerCert_ = std::make_unique(Svr.IssuerCertFile()); + Logger().information( + fmt::format("Certificate Issuer Name:{}", IssuerCert_->issuerName())); + } + + auto WebServerHttpParams = new Poco::Net::HTTPServerParams; + WebServerHttpParams->setMaxThreads(50); + WebServerHttpParams->setMaxQueued(200); + WebServerHttpParams->setKeepAlive(true); + + auto NewWebServer = std::make_unique( + new AP_WS_RequestHandlerFactory(Logger()), Sock, WebServerHttpParams); + WebServers_.push_back(std::move(NewWebServer)); + } + + for(auto &server:WebServers_) + server->start(); + + ReactorThread_.start(Reactor_); + + auto ProvString = MicroService::instance().ConfigGetString("autoprovisioning.process","default"); + if(ProvString!="default") { + auto Tokens = Poco::StringTokenizer(ProvString, ","); + for (const auto &i : Tokens) { + if (i == "prov") + LookAtProvisioning_ = true; + else + UseDefaultConfig_ = true; + } + } else { + UseDefaultConfig_ = true; + } + + SimulatorId_ = MicroService::instance().ConfigGetString("simulatorid",""); + SimulatorEnabled_ = !SimulatorId_.empty(); + + Utils::SetThreadName(ReactorThread_,"device-reactor"); + + return 0; + } + + void AP_WS_Server::Stop() { + Logger().notice("Stopping reactors..."); + // ReactorPool_.Stop(); + Reactor_.stop(); + ReactorThread_.join(); + } + +} //namespace \ No newline at end of file diff --git a/src/AP_WS_Server.h b/src/AP_WS_Server.h new file mode 100644 index 00000000..284d4e68 --- /dev/null +++ b/src/AP_WS_Server.h @@ -0,0 +1,107 @@ +// +// License type: BSD 3-Clause License +// License copy: https://github.com/Telecominfraproject/wlan-cloud-ucentralgw/blob/master/LICENSE +// +// Created by Stephane Bourque on 2021-03-04. +// Arilia Wireless Inc. +// + +#pragma once + +#include +#include +#include +#include + +#include "framework/MicroService.h" + +#include "Poco/AutoPtr.h" +#include "Poco/Net/SocketReactor.h" +#include "Poco/Net/ParallelSocketAcceptor.h" +#include "Poco/Net/SocketAcceptor.h" + +#include "AP_WS_Connection.h" +#include "WS_ReactorPool.h" + +namespace OpenWifi { + + class AP_WS_RequestHandler : public Poco::Net::HTTPRequestHandler { + public: + explicit AP_WS_RequestHandler(Poco::Logger &L) + : Logger_(L) { + }; + + void handleRequest(Poco::Net::HTTPServerRequest &request, + Poco::Net::HTTPServerResponse &response) override; + private: + Poco::Logger &Logger_; + }; + + class AP_WS_RequestHandlerFactory : public Poco::Net::HTTPRequestHandlerFactory { + public: + inline explicit AP_WS_RequestHandlerFactory(Poco::Logger &L) + : Logger_(L) { + } + + inline Poco::Net::HTTPRequestHandler * + createRequestHandler(const Poco::Net::HTTPServerRequest &request) override { + if (request.find("Upgrade") != request.end() && + Poco::icompare(request["Upgrade"], "websocket") == 0) { + Poco::Thread::current()->setName("AP_CONN_INIT"); + return new AP_WS_RequestHandler(Logger_); + } else { + return nullptr; + } + } + private: + Poco::Logger &Logger_; + }; + + class AP_WS_Server : public SubSystemServer { + public: + static auto instance() { + static auto instance_ = new AP_WS_Server; + return instance_; + } + + int Start() override; + void Stop() override; + bool IsCertOk() { return IssuerCert_!= nullptr; } + bool ValidateCertificate(const std::string & ConnectionId, const Poco::Crypto::X509Certificate & Certificate); + // Poco::Net::SocketReactor & GetNextReactor() { return ReactorPool_.NextReactor(); } + + inline bool IsSimSerialNumber(const std::string & SerialNumber) const { + return IsSim(SerialNumber) && SerialNumber == SimulatorId_; + } + + inline static bool IsSim(const std::string & SerialNumber) { + return SerialNumber.substr(0,6) == "53494d"; + } + + inline bool IsSimEnabled() const { + return SimulatorEnabled_; + } + + inline bool UseProvisioning() const { return LookAtProvisioning_; } + inline bool UseDefaults() const { return UseDefaultConfig_; } + + [[nodiscard]] inline Poco::Net::SocketReactor & NextReactor() { return Reactor_; } + + private: + std::unique_ptr IssuerCert_; + std::list> WebServers_; + Poco::Net::SocketReactor Reactor_; + Poco::Thread ReactorThread_; + std::string SimulatorId_; + bool LookAtProvisioning_ = false; + bool UseDefaultConfig_ = true; + bool SimulatorEnabled_=false; + + AP_WS_Server() noexcept: + SubSystemServer("WebSocketServer", "WS-SVR", "ucentral.websocket") { + } + }; + + inline auto AP_WS_Server() { return AP_WS_Server::instance(); } + +} //namespace \ No newline at end of file diff --git a/src/Daemon.cpp b/src/Daemon.cpp index b8ba6d2e..69f579fa 100644 --- a/src/Daemon.cpp +++ b/src/Daemon.cpp @@ -10,22 +10,22 @@ #include "Poco/Util/Option.h" #include "Poco/Environment.h" +#include "AP_WS_Server.h" #include "CommandManager.h" #include "Daemon.h" #include "DeviceRegistry.h" #include "FileUploader.h" +#include "FindCountry.h" #include "OUIServer.h" +#include "RADIUS_proxy_server.h" #include "SerialNumberCache.h" #include "StorageArchiver.h" #include "StorageService.h" #include "TelemetryStream.h" -#include "WS_Server.h" +#include "VenueBroadcaster.h" #include "framework/ConfigurationValidator.h" #include "framework/MicroService.h" -#include "FindCountry.h" #include "rttys/RTTYS_server.h" -#include "RADIUS_proxy_server.h" -#include "VenueBroadcaster.h" namespace OpenWifi { class Daemon *Daemon::instance() { @@ -47,7 +47,7 @@ namespace OpenWifi { StorageArchiver(), TelemetryStream(), RTTYS_server(), - WebSocketServer(), + AP_WS_Server(), RADIUS_proxy_server(), VenueBroadcaster() }); diff --git a/src/DeviceRegistry.cpp b/src/DeviceRegistry.cpp index aefc0642..9b1937ed 100644 --- a/src/DeviceRegistry.cpp +++ b/src/DeviceRegistry.cpp @@ -9,8 +9,8 @@ #include "Poco/JSON/Object.h" #include "Poco/JSON/Parser.h" +#include "AP_WS_Server.h" #include "DeviceRegistry.h" -#include "WS_Server.h" #include "OUIServer.h" namespace OpenWifi { @@ -87,7 +87,7 @@ namespace OpenWifi { } } - std::shared_ptr DeviceRegistry::Register(uint64_t SerialNumber, WSConnection *Ptr, uint64_t & ConnectionId ) + std::shared_ptr DeviceRegistry::Register(uint64_t SerialNumber, AP_WS_Connection *Ptr, uint64_t & ConnectionId ) { std::lock_guard Guard(Mutex_); diff --git a/src/DeviceRegistry.h b/src/DeviceRegistry.h index c34b1b7c..9c116d1b 100644 --- a/src/DeviceRegistry.h +++ b/src/DeviceRegistry.h @@ -17,11 +17,11 @@ namespace OpenWifi { - class WSConnection; + class AP_WS_Connection; class DeviceRegistry : public SubSystemServer { public: struct ConnectionEntry { - WSConnection * WSConn_ = nullptr; + AP_WS_Connection * WSConn_ = nullptr; GWObjects::ConnectionState Conn_; std::string LastStats; GWObjects::HealthCheck LastHealthcheck; @@ -66,7 +66,7 @@ namespace OpenWifi { } void SetHealthcheck(uint64_t SerialNumber, const GWObjects::HealthCheck &H); - std::shared_ptr Register(uint64_t SerialNumber, WSConnection *Conn, uint64_t & ConnectionId); + std::shared_ptr Register(uint64_t SerialNumber, AP_WS_Connection *Conn, uint64_t & ConnectionId); inline void UnRegister(const std::string & SerialNumber, uint64_t ConnectionId) { return UnRegister(Utils::SerialNumberToInt(SerialNumber),ConnectionId); diff --git a/src/ParseWifiScan.h b/src/ParseWifiScan.h index 331d3c10..2c3236b0 100644 --- a/src/ParseWifiScan.h +++ b/src/ParseWifiScan.h @@ -1737,91 +1737,112 @@ namespace OpenWifi { std::ostringstream ofs; Obj->stringify(ofs); - nlohmann::json D = nlohmann::json::parse(ofs.str()); - std::cout << "Start of parsing wifi" << std::endl; - if (D.contains("status")) { - auto Status = D["status"]; - if (Status.contains("scan") && Status["scan"].is_array()) { - nlohmann::json ScanArray = Status["scan"]; - nlohmann::json ParsedScan = nlohmann::json::array(); - for (auto &scan_entry : ScanArray) { - if (scan_entry.contains("ies") && scan_entry["ies"].is_array()) { - auto ies = scan_entry["ies"]; - nlohmann::json new_ies=nlohmann::json::array(); - for (auto &ie : ies) { - try { - if (ie.contains("type") && ie.contains("data")) { - uint64_t ie_type = ie["type"]; - std::string ie_data = ie["data"]; - // std::cout << "TYPE:" << ie_type << " DATA:" << ie_data << std::endl; - auto data = Base64Decode2Vec(ie_data); - if (ie_type == ieee80211_eid::WLAN_EID_COUNTRY) { - new_ies.push_back(WFS_WLAN_EID_COUNTRY(data)); - } else if (ie_type == ieee80211_eid::WLAN_EID_SUPP_RATES) { - new_ies.push_back(WFS_WLAN_EID_SUPP_RATES(data)); - } else if (ie_type == ieee80211_eid::WLAN_EID_FH_PARAMS) { - new_ies.push_back(WFS_WLAN_EID_FH_PARAMS(data)); - } else if (ie_type == ieee80211_eid::WLAN_EID_DS_PARAMS) { - new_ies.push_back(WFS_WLAN_EID_DS_PARAMS(data)); - } else if (ie_type == ieee80211_eid::WLAN_EID_TIM) { - new_ies.push_back(WFS_WLAN_EID_TIM(data)); - } else if (ie_type == ieee80211_eid::WLAN_EID_QBSS_LOAD) { - new_ies.push_back(WFS_WLAN_EID_QBSS_LOAD(data)); - } else if (ie_type == ieee80211_eid::WLAN_EID_PWR_CONSTRAINT) { - new_ies.push_back(WFS_WLAN_EID_PWR_CONSTRAINT(data)); - } else if (ie_type == ieee80211_eid::WLAN_EID_ERP_INFO) { - new_ies.push_back(WFS_WLAN_EID_ERP_INFO(data)); - } else if (ie_type == ieee80211_eid::WLAN_EID_SUPPORTED_REGULATORY_CLASSES) { - new_ies.push_back(WFS_WLAN_EID_SUPPORTED_REGULATORY_CLASSES(data)); - } else if (ie_type == ieee80211_eid::WLAN_EID_HT_CAPABILITY) { - new_ies.push_back(WFS_WLAN_EID_HT_CAPABILITY(data)); - } else if (ie_type == ieee80211_eid::WLAN_EID_EXT_SUPP_RATES) { - new_ies.push_back(WFS_WLAN_EID_EXT_SUPP_RATES(data)); - } else if (ie_type == ieee80211_eid::WLAN_EID_TX_POWER_ENVELOPE) { - new_ies.push_back(WFS_WLAN_EID_TX_POWER_ENVELOPE(data)); - } else if (ie_type == ieee80211_eid::WLAN_EID_VHT_CAPABILITY) { - new_ies.push_back(WFS_WLAN_EID_VHT_CAPABILITY(data)); - } else if (ie_type == ieee80211_eid::WLAN_EID_RRM_ENABLED_CAPABILITIES) { - new_ies.push_back(WFS_WLAN_EID_RRM_ENABLED_CAPABILITIES(data)); - } else if (ie_type == ieee80211_eid::WLAN_EID_EXT_CAPABILITY) { - new_ies.push_back(WFS_WLAN_EID_EXT_CAPABILITY(data)); - } else if (ie_type == ieee80211_eid::WLAN_EID_TPC_REPORT) { - new_ies.push_back(WFS_WLAN_EID_TPC_REPORT(data)); - } else if (ie_type == ieee80211_eid::WLAN_EID_RSN) { - new_ies.push_back(WFS_WLAN_EID_RSN(data)); - } else if (ie_type == ieee80211_eid::WLAN_EID_VENDOR_SPECIFIC) { - new_ies.push_back(WFS_WLAN_EID_VENDOR_SPECIFIC(data)); - } else if (ie_type == ieee80211_eid::WLAN_EID_EXTENSION) { - new_ies.push_back(WFS_WLAN_EID_EXTENSION(data)); + try { + nlohmann::json D = nlohmann::json::parse(ofs.str()); + std::cout << "Start of parsing wifi" << std::endl; + if (D.contains("status")) { + auto Status = D["status"]; + if (Status.contains("scan") && Status["scan"].is_array()) { + nlohmann::json ScanArray = Status["scan"]; + nlohmann::json ParsedScan = nlohmann::json::array(); + for (auto &scan_entry : ScanArray) { + if (scan_entry.contains("ies") && scan_entry["ies"].is_array()) { + auto ies = scan_entry["ies"]; + nlohmann::json new_ies = nlohmann::json::array(); + for (auto &ie : ies) { + try { + if (ie.contains("type") && ie.contains("data")) { + uint64_t ie_type = ie["type"]; + std::string ie_data = ie["data"]; + // std::cout << "TYPE:" << ie_type << " DATA:" << ie_data << std::endl; + auto data = Base64Decode2Vec(ie_data); + if (ie_type == ieee80211_eid::WLAN_EID_COUNTRY) { + new_ies.push_back(WFS_WLAN_EID_COUNTRY(data)); + } else if (ie_type == ieee80211_eid::WLAN_EID_SUPP_RATES) { + new_ies.push_back(WFS_WLAN_EID_SUPP_RATES(data)); + } else if (ie_type == ieee80211_eid::WLAN_EID_FH_PARAMS) { + new_ies.push_back(WFS_WLAN_EID_FH_PARAMS(data)); + } else if (ie_type == ieee80211_eid::WLAN_EID_DS_PARAMS) { + new_ies.push_back(WFS_WLAN_EID_DS_PARAMS(data)); + } else if (ie_type == ieee80211_eid::WLAN_EID_TIM) { + new_ies.push_back(WFS_WLAN_EID_TIM(data)); + } else if (ie_type == ieee80211_eid::WLAN_EID_QBSS_LOAD) { + new_ies.push_back(WFS_WLAN_EID_QBSS_LOAD(data)); + } else if (ie_type == + ieee80211_eid::WLAN_EID_PWR_CONSTRAINT) { + new_ies.push_back(WFS_WLAN_EID_PWR_CONSTRAINT(data)); + } else if (ie_type == ieee80211_eid::WLAN_EID_ERP_INFO) { + new_ies.push_back(WFS_WLAN_EID_ERP_INFO(data)); + } else if (ie_type == + ieee80211_eid:: + WLAN_EID_SUPPORTED_REGULATORY_CLASSES) { + new_ies.push_back( + WFS_WLAN_EID_SUPPORTED_REGULATORY_CLASSES(data)); + } else if (ie_type == + ieee80211_eid::WLAN_EID_HT_CAPABILITY) { + new_ies.push_back(WFS_WLAN_EID_HT_CAPABILITY(data)); + } else if (ie_type == + ieee80211_eid::WLAN_EID_EXT_SUPP_RATES) { + new_ies.push_back(WFS_WLAN_EID_EXT_SUPP_RATES(data)); + } else if (ie_type == + ieee80211_eid::WLAN_EID_TX_POWER_ENVELOPE) { + new_ies.push_back(WFS_WLAN_EID_TX_POWER_ENVELOPE(data)); + } else if (ie_type == + ieee80211_eid::WLAN_EID_VHT_CAPABILITY) { + new_ies.push_back(WFS_WLAN_EID_VHT_CAPABILITY(data)); + } else if (ie_type == + ieee80211_eid:: + WLAN_EID_RRM_ENABLED_CAPABILITIES) { + new_ies.push_back( + WFS_WLAN_EID_RRM_ENABLED_CAPABILITIES(data)); + } else if (ie_type == + ieee80211_eid::WLAN_EID_EXT_CAPABILITY) { + new_ies.push_back(WFS_WLAN_EID_EXT_CAPABILITY(data)); + } else if (ie_type == ieee80211_eid::WLAN_EID_TPC_REPORT) { + new_ies.push_back(WFS_WLAN_EID_TPC_REPORT(data)); + } else if (ie_type == ieee80211_eid::WLAN_EID_RSN) { + new_ies.push_back(WFS_WLAN_EID_RSN(data)); + } else if (ie_type == + ieee80211_eid::WLAN_EID_VENDOR_SPECIFIC) { + new_ies.push_back(WFS_WLAN_EID_VENDOR_SPECIFIC(data)); + } else if (ie_type == ieee80211_eid::WLAN_EID_EXTENSION) { + new_ies.push_back(WFS_WLAN_EID_EXTENSION(data)); + } else { + std::cout + << "Skipping IE: no parsing available: " << ie_type + << std::endl; + new_ies.push_back(ie); + } } else { - std::cout - << "Skipping IE: no parsing available: " << ie_type - << std::endl; + std::cout << "Skipping IE: no data and type" << std::endl; new_ies.push_back(ie); } - } else { - std::cout << "Skipping IE: no data and type" << std::endl; + } catch (...) { + std::cout << "Skipping IE: exception" << std::endl; + Logger.information(fmt::format("Error parsing IEs")); new_ies.push_back(ie); } - } catch (...) { - std::cout << "Skipping IE: exception" << std::endl; - Logger.information(fmt::format("Error parsing IEs")); - new_ies.push_back(ie); } + scan_entry["ies"] = new_ies; + ParsedScan.push_back(scan_entry); + } else { + std::cout << "Skipping scan" << std::endl; + ParsedScan.push_back(scan_entry); } - scan_entry["ies"] = new_ies; - ParsedScan.push_back(scan_entry); - } else { - std::cout << "Skipping scan" << std::endl; - ParsedScan.push_back(scan_entry); } + Status["scan"] = ParsedScan; + D["status"] = Status; } - Status["scan"] = ParsedScan; - D["status"] = Status; } + Result << to_string(D); + std::cout << "End of parsing wifi" << std::endl; + return true; + } catch (const Poco::Exception &E) { + Logger.log(E); + Logger.error(fmt::format("Failure to parse WifiScan.")); + } catch (...) { + Logger.error(fmt::format("Failure to parse WifiScan.")); } - Result << to_string(D); - std::cout << "End of parsing wifi" << std::endl; return false; } diff --git a/src/RESTAPI/RESTAPI_device_commandHandler.cpp b/src/RESTAPI/RESTAPI_device_commandHandler.cpp index 8e232bf4..bc9c3760 100644 --- a/src/RESTAPI/RESTAPI_device_commandHandler.cpp +++ b/src/RESTAPI/RESTAPI_device_commandHandler.cpp @@ -11,19 +11,19 @@ #include "Poco/JSON/Parser.h" +#include "AP_WS_Server.h" #include "CentralConfig.h" #include "DeviceRegistry.h" #include "FileUploader.h" -#include "RESTObjects/RESTAPI_GWobjects.h" -#include "RESTAPI_device_commandHandler.h" -#include "StorageService.h" #include "RESTAPI_RPC.h" +#include "RESTAPI_device_commandHandler.h" +#include "RESTObjects/RESTAPI_GWobjects.h" +#include "StorageService.h" #include "TelemetryStream.h" -#include "framework/ow_constants.h" -#include "framework/KafkaTopics.h" #include "framework/ConfigurationValidator.h" +#include "framework/KafkaTopics.h" +#include "framework/ow_constants.h" #include "rttys/RTTYS_server.h" -#include "WS_Server.h" namespace OpenWifi { diff --git a/src/TelemetryClient.cpp b/src/TelemetryClient.cpp index e93ab06e..ad9514b8 100644 --- a/src/TelemetryClient.cpp +++ b/src/TelemetryClient.cpp @@ -6,10 +6,10 @@ #include "Poco/Net/SSLException.h" +#include "AP_WS_Connection.h" +#include "DeviceRegistry.h" #include "TelemetryClient.h" #include "TelemetryStream.h" -#include "DeviceRegistry.h" -#include "WS_Connection.h" namespace OpenWifi { diff --git a/src/WS_Server.cpp b/src/WS_Server.cpp deleted file mode 100644 index cd784aa0..00000000 --- a/src/WS_Server.cpp +++ /dev/null @@ -1,84 +0,0 @@ -// -// License type: BSD 3-Clause License -// License copy: https://github.com/Telecominfraproject/wlan-cloud-ucentralgw/blob/master/LICENSE -// -// Created by Stephane Bourque on 2021-03-04. -// Arilia Wireless Inc. -// - -#include "Poco/Net/HTTPHeaderStream.h" -#include "Poco/JSON/Array.h" -#include "Poco/Net/Context.h" - -#include "ConfigurationCache.h" -#include "TelemetryStream.h" -#include "WS_Server.h" -#include - -namespace OpenWifi { - -bool WebSocketServer::ValidateCertificate(const std::string & ConnectionId, const Poco::Crypto::X509Certificate & Certificate) { - if(IsCertOk()) { - Logger().debug(fmt::format("CERTIFICATE({}): issuer='{}' cn='{}'", ConnectionId, Certificate.issuerName(),Certificate.commonName())); - if(!Certificate.issuedBy(*IssuerCert_)) { - Logger().debug(fmt::format("CERTIFICATE({}): issuer mismatch. Local='{}' Incoming='{}'", ConnectionId, IssuerCert_->issuerName(), Certificate.issuerName())); - return false; - } - return true; - } - return false; -} - -int WebSocketServer::Start() { - // ReactorPool_.Start("DeviceReactorPool_"); - for(const auto & Svr : ConfigServersList_ ) { - Logger().notice( fmt::format("Starting: {}:{} Keyfile:{} CertFile: {}", - Svr.Address(), - Svr.Port(), - Svr.KeyFile(),Svr.CertFile())); - - Svr.LogCert(Logger()); - if(!Svr.RootCA().empty()) - Svr.LogCas(Logger()); - - auto Sock{Svr.CreateSecureSocket(Logger())}; - - if(!IsCertOk()) { - IssuerCert_ = std::make_unique(Svr.IssuerCertFile()); - Logger().information( fmt::format("Certificate Issuer Name:{}",IssuerCert_->issuerName())); - } - auto NewSocketAcceptor = std::make_unique(Sock, Reactor_); // , 2 /*Poco::Environment::processorCount()*2) */ ); - Acceptors_.push_back(std::move(NewSocketAcceptor)); - } - - auto ProvString = MicroService::instance().ConfigGetString("autoprovisioning.process","default"); - if(ProvString!="default") { - auto Tokens = Poco::StringTokenizer(ProvString, ","); - for (const auto &i : Tokens) { - if (i == "prov") - LookAtProvisioning_ = true; - else - UseDefaultConfig_ = true; - } - } else { - UseDefaultConfig_ = true; - } - - SimulatorId_ = MicroService::instance().ConfigGetString("simulatorid",""); - SimulatorEnabled_ = !SimulatorId_.empty(); - - ReactorThread_.setStackSize(3000000); - ReactorThread_.start(Reactor_); - Utils::SetThreadName(ReactorThread_,"device-reactor"); - - return 0; -} - -void WebSocketServer::Stop() { - Logger().notice("Stopping reactors..."); - // ReactorPool_.Stop(); - Reactor_.stop(); - ReactorThread_.join(); -} - -} //namespace \ No newline at end of file diff --git a/src/WS_Server.h b/src/WS_Server.h deleted file mode 100644 index c29059e1..00000000 --- a/src/WS_Server.h +++ /dev/null @@ -1,76 +0,0 @@ -// -// License type: BSD 3-Clause License -// License copy: https://github.com/Telecominfraproject/wlan-cloud-ucentralgw/blob/master/LICENSE -// -// Created by Stephane Bourque on 2021-03-04. -// Arilia Wireless Inc. -// - -#pragma once - -#include -#include -#include -#include - -#include "framework/MicroService.h" - -#include "Poco/AutoPtr.h" -#include "Poco/Net/SocketReactor.h" -#include "Poco/Net/ParallelSocketAcceptor.h" -#include "Poco/Net/SocketAcceptor.h" - -#include "WS_Connection.h" -#include "WS_ReactorPool.h" - -namespace OpenWifi { - -class WebSocketServer : public SubSystemServer { - public: - static auto instance() { - static auto instance_ = new WebSocketServer; - return instance_; - } - - int Start() override; - void Stop() override; - bool IsCertOk() { return IssuerCert_!= nullptr; } - bool ValidateCertificate(const std::string & ConnectionId, const Poco::Crypto::X509Certificate & Certificate); - // Poco::Net::SocketReactor & GetNextReactor() { return ReactorPool_.NextReactor(); } - - inline bool IsSimSerialNumber(const std::string & SerialNumber) const { - return IsSim(SerialNumber) && SerialNumber == SimulatorId_; - } - - inline static bool IsSim(const std::string & SerialNumber) { - return SerialNumber.substr(0,6) == "53494d"; - } - - inline bool IsSimEnabled() const { - return SimulatorEnabled_; - } - - inline bool UseProvisioning() const { return LookAtProvisioning_; } - inline bool UseDefaults() const { return UseDefaultConfig_; } - - private: - std::unique_ptr IssuerCert_; - // typedef std::unique_ptr> ws_server_reactor_type_t; - typedef Poco::Net::SocketAcceptor ws_server_reactor_type_t; - std::vector> Acceptors_; - Poco::Net::SocketReactor Reactor_; - Poco::Thread ReactorThread_; - std::string SimulatorId_; - bool LookAtProvisioning_ = false; - bool UseDefaultConfig_ = true; - bool SimulatorEnabled_=false; - - WebSocketServer() noexcept: - SubSystemServer("WebSocketServer", "WS-SVR", "ucentral.websocket") { - - } -}; - -inline auto WebSocketServer() { return WebSocketServer::instance(); } - -} //namespace \ No newline at end of file diff --git a/src/storage/storage_device.cpp b/src/storage/storage_device.cpp index 99ab5bfc..c91e33a5 100644 --- a/src/storage/storage_device.cpp +++ b/src/storage/storage_device.cpp @@ -6,21 +6,21 @@ // Arilia Wireless Inc. // +#include "AP_WS_Server.h" +#include "CapabilitiesCache.h" #include "CentralConfig.h" #include "ConfigurationCache.h" #include "Daemon.h" #include "DeviceRegistry.h" +#include "FindCountry.h" #include "OUIServer.h" #include "Poco/Data/RecordSet.h" #include "Poco/Net/IPAddress.h" +#include "SDKcalls.h" #include "SerialNumberCache.h" +#include "StateUtils.h" #include "StorageService.h" #include "framework/MicroService.h" -#include "CapabilitiesCache.h" -#include "FindCountry.h" -#include "WS_Server.h" -#include "SDKcalls.h" -#include "StateUtils.h" namespace OpenWifi { @@ -326,7 +326,7 @@ namespace OpenWifi { bool Found = false; std::string FoundConfig; - if(WebSocketServer()->UseProvisioning()) { + if(AP_WS_Server()->UseProvisioning()) { if(SDKCalls::GetProvisioningConfiguration(SerialNumber, FoundConfig)) { if(FoundConfig != "none") { Found = true; @@ -337,7 +337,7 @@ namespace OpenWifi { } } - if (!Found && WebSocketServer()->UseDefaults() && FindDefaultConfigurationForModel(Compat, DefConfig)) { + if (!Found && AP_WS_Server()->UseDefaults() && FindDefaultConfigurationForModel(Compat, DefConfig)) { Config::Config NewConfig(DefConfig.Configuration); NewConfig.SetUUID(Now); D.Configuration = NewConfig.get();