mirror of
				https://github.com/Telecominfraproject/wlan-cloud-ucentralgw.git
				synced 2025-11-04 04:37:46 +00:00 
			
		
		
		
	Compare commits
	
		
			115 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					915a2c936d | ||
| 
						 | 
					e1bf6a9ab7 | ||
| 
						 | 
					58fc925a2f | ||
| 
						 | 
					3dda87b41f | ||
| 
						 | 
					a5fe59086a | ||
| 
						 | 
					c66b936c1e | ||
| 
						 | 
					0e763cf034 | ||
| 
						 | 
					eb441d71aa | ||
| 
						 | 
					082153a229 | ||
| 
						 | 
					25a03ca801 | ||
| 
						 | 
					0d549137de | ||
| 
						 | 
					40e814cab8 | ||
| 
						 | 
					e40d53f3e5 | ||
| 
						 | 
					607507ce9a | ||
| 
						 | 
					b3ec5b1e81 | ||
| 
						 | 
					c52d3c92f6 | ||
| 
						 | 
					d1216a8ac4 | ||
| 
						 | 
					c27f0390f8 | ||
| 
						 | 
					052d379e2b | ||
| 
						 | 
					4eda1b813f | ||
| 
						 | 
					5364adf509 | ||
| 
						 | 
					3b5580a525 | ||
| 
						 | 
					644918fa14 | ||
| 
						 | 
					8cdd398a6e | ||
| 
						 | 
					9f7f4683df | ||
| 
						 | 
					1c6e35fa8b | ||
| 
						 | 
					af17823df0 | ||
| 
						 | 
					0cff2163bb | ||
| 
						 | 
					0a5fe39bde | ||
| 
						 | 
					c42feca957 | ||
| 
						 | 
					d3c5b17733 | ||
| 
						 | 
					30bc8e8283 | ||
| 
						 | 
					336c94a25a | ||
| 
						 | 
					84f42e5a7d | ||
| 
						 | 
					17752fdefe | ||
| 
						 | 
					ef300b0349 | ||
| 
						 | 
					9c4ecb6165 | ||
| 
						 | 
					efd099b6fa | ||
| 
						 | 
					15805dcaf6 | ||
| 
						 | 
					e5ed1750cc | ||
| 
						 | 
					87d74568f2 | ||
| 
						 | 
					0cca3caa9b | ||
| 
						 | 
					1d22e1153f | ||
| 
						 | 
					f3ccc49647 | ||
| 
						 | 
					46fb410108 | ||
| 
						 | 
					fc680a6bc4 | ||
| 
						 | 
					246f9c8aad | ||
| 
						 | 
					3f06f00a88 | ||
| 
						 | 
					0288d905b7 | ||
| 
						 | 
					135b63c021 | ||
| 
						 | 
					12e07fa65f | ||
| 
						 | 
					567c2d1514 | ||
| 
						 | 
					b9bd768ca6 | ||
| 
						 | 
					f2dec010ee | ||
| 
						 | 
					329d8d4441 | ||
| 
						 | 
					d4dbbeb54b | ||
| 
						 | 
					b1c6884d49 | ||
| 
						 | 
					3ffa35bb14 | ||
| 
						 | 
					bd06722948 | ||
| 
						 | 
					8c70ec5280 | ||
| 
						 | 
					6c13d845f1 | ||
| 
						 | 
					77cc0b250b | ||
| 
						 | 
					a3c424d8fe | ||
| 
						 | 
					3f834a967b | ||
| 
						 | 
					4120aefcd4 | ||
| 
						 | 
					909ee66ef0 | ||
| 
						 | 
					c3ad34d84b | ||
| 
						 | 
					fbb9f40529 | ||
| 
						 | 
					5f6300bb17 | ||
| 
						 | 
					0bcfb26579 | ||
| 
						 | 
					5b199bc4f5 | ||
| 
						 | 
					4c6fb85542 | ||
| 
						 | 
					63993789ca | ||
| 
						 | 
					cc9d4c5f68 | ||
| 
						 | 
					50fa1de62c | ||
| 
						 | 
					14ef6608d6 | ||
| 
						 | 
					8e48d30d6a | ||
| 
						 | 
					46c6321674 | ||
| 
						 | 
					77f67fe545 | ||
| 
						 | 
					ceda1fc8f6 | ||
| 
						 | 
					5b1a4fb9c0 | ||
| 
						 | 
					2ddc0d3117 | ||
| 
						 | 
					2cfc6c30e9 | ||
| 
						 | 
					0318b475f5 | ||
| 
						 | 
					c5c2dc1a1e | ||
| 
						 | 
					7b899adb88 | ||
| 
						 | 
					aa472ed79e | ||
| 
						 | 
					1778912264 | ||
| 
						 | 
					142bc4f271 | ||
| 
						 | 
					a01d006d4e | ||
| 
						 | 
					135a195081 | ||
| 
						 | 
					ef7cb883fb | ||
| 
						 | 
					2e361a41d7 | ||
| 
						 | 
					84281ec58e | ||
| 
						 | 
					3560871f44 | ||
| 
						 | 
					b072f1e2ab | ||
| 
						 | 
					72173ed4b5 | ||
| 
						 | 
					ff53d4ba2e | ||
| 
						 | 
					81721b4a61 | ||
| 
						 | 
					3619be1832 | ||
| 
						 | 
					a8fc823b94 | ||
| 
						 | 
					a8a33013be | ||
| 
						 | 
					9560f908a6 | ||
| 
						 | 
					8400b8cfcb | ||
| 
						 | 
					82897f5b76 | ||
| 
						 | 
					4b472fd112 | ||
| 
						 | 
					ecb6312f0f | ||
| 
						 | 
					0aba846277 | ||
| 
						 | 
					5be884ef98 | ||
| 
						 | 
					10c890a196 | ||
| 
						 | 
					0974abd510 | ||
| 
						 | 
					8dbbfc3298 | ||
| 
						 | 
					c981ae14ee | ||
| 
						 | 
					97547068d7 | ||
| 
						 | 
					16cc443786 | 
@@ -175,7 +175,7 @@ add_executable( owgw
 | 
				
			|||||||
        src/SDKcalls.cpp
 | 
					        src/SDKcalls.cpp
 | 
				
			||||||
        src/SDKcalls.h
 | 
					        src/SDKcalls.h
 | 
				
			||||||
        src/StateUtils.cpp src/StateUtils.h
 | 
					        src/StateUtils.cpp src/StateUtils.h
 | 
				
			||||||
        src/AP_WS_ReactorPool.h
 | 
					        src/AP_WS_Reactor_Pool.h
 | 
				
			||||||
        src/AP_WS_Connection.h
 | 
					        src/AP_WS_Connection.h
 | 
				
			||||||
        src/AP_WS_Connection.cpp
 | 
					        src/AP_WS_Connection.cpp
 | 
				
			||||||
        src/TelemetryClient.h src/TelemetryClient.cpp
 | 
					        src/TelemetryClient.h src/TelemetryClient.cpp
 | 
				
			||||||
@@ -211,7 +211,8 @@ add_executable( owgw
 | 
				
			|||||||
        src/RegulatoryInfo.cpp src/RegulatoryInfo.h
 | 
					        src/RegulatoryInfo.cpp src/RegulatoryInfo.h
 | 
				
			||||||
        src/RADIUSSessionTracker.cpp src/RADIUSSessionTracker.h
 | 
					        src/RADIUSSessionTracker.cpp src/RADIUSSessionTracker.h
 | 
				
			||||||
        src/libs/Scheduler.h src/libs/InterruptableSleep.h src/libs/ctpl_stl.h src/libs/Cron.h
 | 
					        src/libs/Scheduler.h src/libs/InterruptableSleep.h src/libs/ctpl_stl.h src/libs/Cron.h
 | 
				
			||||||
        src/GenericScheduler.cpp src/GenericScheduler.h src/framework/default_device_types.h src/AP_WS_Process_rebootLog.cpp src/AP_WS_ConfigAutoUpgrader.cpp src/AP_WS_ConfigAutoUpgrader.h src/RESTAPI/RESTAPI_default_firmwares.cpp src/RESTAPI/RESTAPI_default_firmwares.h src/RESTAPI/RESTAPI_default_firmware.cpp src/RESTAPI/RESTAPI_default_firmware.h src/storage/storage_def_firmware.cpp src/firmware_revision_cache.h src/sdks/sdk_fms.h)
 | 
					        src/GenericScheduler.cpp src/GenericScheduler.h src/framework/default_device_types.h src/AP_WS_Process_rebootLog.cpp src/AP_WS_ConfigAutoUpgrader.cpp src/AP_WS_ConfigAutoUpgrader.h src/RESTAPI/RESTAPI_default_firmwares.cpp src/RESTAPI/RESTAPI_default_firmwares.h src/RESTAPI/RESTAPI_default_firmware.cpp src/RESTAPI/RESTAPI_default_firmware.h src/storage/storage_def_firmware.cpp src/firmware_revision_cache.h src/sdks/sdk_fms.h
 | 
				
			||||||
 | 
					        src/AP_WS_LookForUpgrade.cpp)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
if(NOT SMALL_BUILD)
 | 
					if(NOT SMALL_BUILD)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -145,7 +145,7 @@ storage.type.sqlite.db = devices.db
 | 
				
			|||||||
storage.type.sqlite.idletime = 120
 | 
					storage.type.sqlite.idletime = 120
 | 
				
			||||||
storage.type.sqlite.maxsessions = 128
 | 
					storage.type.sqlite.maxsessions = 128
 | 
				
			||||||
 | 
					
 | 
				
			||||||
storage.type.postgresql.maxsessions = 64
 | 
					storage.type.postgresql.maxsessions = 250
 | 
				
			||||||
storage.type.postgresql.idletime = 60
 | 
					storage.type.postgresql.idletime = 60
 | 
				
			||||||
storage.type.postgresql.host = ${STORAGE_TYPE_POSTGRESQL_HOST}
 | 
					storage.type.postgresql.host = ${STORAGE_TYPE_POSTGRESQL_HOST}
 | 
				
			||||||
storage.type.postgresql.username = ${STORAGE_TYPE_POSTGRESQL_USERNAME}
 | 
					storage.type.postgresql.username = ${STORAGE_TYPE_POSTGRESQL_USERNAME}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -36,22 +36,20 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
namespace OpenWifi {
 | 
					namespace OpenWifi {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define DBL                                                                                        \
 | 
					 | 
				
			||||||
	{                                                                                              \
 | 
					 | 
				
			||||||
		std::cout << __LINE__ << "  ID: " << ConnectionId_ << "  Ser: " << SerialNumber_           \
 | 
					 | 
				
			||||||
				  << std::endl;                                                                    \
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	void AP_WS_Connection::LogException(const Poco::Exception &E) {
 | 
						void AP_WS_Connection::LogException(const Poco::Exception &E) {
 | 
				
			||||||
		poco_information(Logger_, fmt::format("EXCEPTION({}): {}", CId_, E.displayText()));
 | 
							poco_information(Logger_, fmt::format("EXCEPTION({}): {}", CId_, E.displayText()));
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	AP_WS_Connection::AP_WS_Connection(Poco::Net::HTTPServerRequest &request,
 | 
						AP_WS_Connection::AP_WS_Connection(Poco::Net::HTTPServerRequest &request,
 | 
				
			||||||
									   Poco::Net::HTTPServerResponse &response,
 | 
														   Poco::Net::HTTPServerResponse &response,
 | 
				
			||||||
									   uint64_t connection_id, Poco::Logger &L,
 | 
														   uint64_t session_id, Poco::Logger &L,
 | 
				
			||||||
									   Poco::Net::SocketReactor &R)
 | 
														   std::pair<std::shared_ptr<Poco::Net::SocketReactor>, std::shared_ptr<LockedDbSession>> R)
 | 
				
			||||||
		: Logger_(L), Reactor_(R) {
 | 
							: Logger_(L) {
 | 
				
			||||||
		State_.sessionId = connection_id;
 | 
					
 | 
				
			||||||
 | 
							Reactor_ = R.first;
 | 
				
			||||||
 | 
							DbSession_ = R.second;
 | 
				
			||||||
 | 
							State_.sessionId = session_id;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		WS_ = std::make_unique<Poco::Net::WebSocket>(request, response);
 | 
							WS_ = std::make_unique<Poco::Net::WebSocket>(request, response);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		auto TS = Poco::Timespan(360, 0);
 | 
							auto TS = Poco::Timespan(360, 0);
 | 
				
			||||||
@@ -61,29 +59,89 @@ namespace OpenWifi {
 | 
				
			|||||||
		WS_->setNoDelay(false);
 | 
							WS_->setNoDelay(false);
 | 
				
			||||||
		WS_->setKeepAlive(true);
 | 
							WS_->setKeepAlive(true);
 | 
				
			||||||
		WS_->setBlocking(false);
 | 
							WS_->setBlocking(false);
 | 
				
			||||||
 | 
					 | 
				
			||||||
		Reactor_.addEventHandler(*WS_,
 | 
					 | 
				
			||||||
								 Poco::NObserver<AP_WS_Connection, Poco::Net::ReadableNotification>(
 | 
					 | 
				
			||||||
									 *this, &AP_WS_Connection::OnSocketReadable));
 | 
					 | 
				
			||||||
		Reactor_.addEventHandler(*WS_,
 | 
					 | 
				
			||||||
								 Poco::NObserver<AP_WS_Connection, Poco::Net::ShutdownNotification>(
 | 
					 | 
				
			||||||
									 *this, &AP_WS_Connection::OnSocketShutdown));
 | 
					 | 
				
			||||||
		Reactor_.addEventHandler(*WS_,
 | 
					 | 
				
			||||||
								 Poco::NObserver<AP_WS_Connection, Poco::Net::ErrorNotification>(
 | 
					 | 
				
			||||||
									 *this, &AP_WS_Connection::OnSocketError));
 | 
					 | 
				
			||||||
		Registered_ = true;
 | 
					 | 
				
			||||||
		Valid_ = true;
 | 
					 | 
				
			||||||
		uuid_ = MicroServiceRandom(std::numeric_limits<std::uint64_t>::max()-1);
 | 
							uuid_ = MicroServiceRandom(std::numeric_limits<std::uint64_t>::max()-1);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						void AP_WS_Connection::Start() {
 | 
				
			||||||
 | 
							Registered_ = true;
 | 
				
			||||||
 | 
							LastContact_ = Utils::Now();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							Reactor_->addEventHandler(*WS_,
 | 
				
			||||||
 | 
													  Poco::NObserver<AP_WS_Connection, Poco::Net::ReadableNotification>(
 | 
				
			||||||
 | 
														  *this, &AP_WS_Connection::OnSocketReadable));
 | 
				
			||||||
 | 
							Reactor_->addEventHandler(*WS_,
 | 
				
			||||||
 | 
													  Poco::NObserver<AP_WS_Connection, Poco::Net::ShutdownNotification>(
 | 
				
			||||||
 | 
														  *this, &AP_WS_Connection::OnSocketShutdown));
 | 
				
			||||||
 | 
							Reactor_->addEventHandler(*WS_,
 | 
				
			||||||
 | 
													  Poco::NObserver<AP_WS_Connection, Poco::Net::ErrorNotification>(
 | 
				
			||||||
 | 
														  *this, &AP_WS_Connection::OnSocketError));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						AP_WS_Connection::~AP_WS_Connection() {
 | 
				
			||||||
 | 
					//		poco_information(Logger_, fmt::format("DESTRUCTOR({}): 0 - Session={} Connection closed.", SerialNumber_,
 | 
				
			||||||
 | 
					//											  State_.sessionId));
 | 
				
			||||||
 | 
							std::lock_guard G(ConnectionMutex_);
 | 
				
			||||||
 | 
					//		poco_information(Logger_, fmt::format("DESTRUCTOR({}): 1 - Session={} Connection closed.", SerialNumber_,
 | 
				
			||||||
 | 
					//											  State_.sessionId));
 | 
				
			||||||
 | 
							EndConnection(false);
 | 
				
			||||||
 | 
							poco_debug(Logger_, fmt::format("TERMINATION({}): Session={}, Connection removed.", SerialNumber_,
 | 
				
			||||||
 | 
																  State_.sessionId));
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						static void NotifyKafkaDisconnect(const std::string &SerialNumber, std::uint64_t uuid) {
 | 
				
			||||||
 | 
							try {
 | 
				
			||||||
 | 
								Poco::JSON::Object Disconnect;
 | 
				
			||||||
 | 
								Poco::JSON::Object Details;
 | 
				
			||||||
 | 
								Details.set(uCentralProtocol::SERIALNUMBER, SerialNumber);
 | 
				
			||||||
 | 
								Details.set(uCentralProtocol::TIMESTAMP, Utils::Now());
 | 
				
			||||||
 | 
								Details.set(uCentralProtocol::UUID,uuid);
 | 
				
			||||||
 | 
								Disconnect.set(uCentralProtocol::DISCONNECTION, Details);
 | 
				
			||||||
 | 
								KafkaManager()->PostMessage(KafkaTopics::CONNECTION, SerialNumber, Disconnect);
 | 
				
			||||||
 | 
							} catch (...) {
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						void AP_WS_Connection::EndConnection(bool Clean) {
 | 
				
			||||||
 | 
							bool expectedValue=false;
 | 
				
			||||||
 | 
							if (Dead_.compare_exchange_strong(expectedValue,true,std::memory_order_release,std::memory_order_relaxed)) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if(!SerialNumber_.empty() && State_.LastContact!=0) {
 | 
				
			||||||
 | 
									StorageService()->SetDeviceLastRecordedContact(SerialNumber_, State_.LastContact);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if (Registered_) {
 | 
				
			||||||
 | 
									Registered_ = false;
 | 
				
			||||||
 | 
									Reactor_->removeEventHandler(
 | 
				
			||||||
 | 
										*WS_, Poco::NObserver<AP_WS_Connection, Poco::Net::ReadableNotification>(
 | 
				
			||||||
 | 
												  *this, &AP_WS_Connection::OnSocketReadable));
 | 
				
			||||||
 | 
									Reactor_->removeEventHandler(
 | 
				
			||||||
 | 
										*WS_, Poco::NObserver<AP_WS_Connection, Poco::Net::ShutdownNotification>(
 | 
				
			||||||
 | 
												  *this, &AP_WS_Connection::OnSocketShutdown));
 | 
				
			||||||
 | 
									Reactor_->removeEventHandler(
 | 
				
			||||||
 | 
										*WS_, Poco::NObserver<AP_WS_Connection, Poco::Net::ErrorNotification>(
 | 
				
			||||||
 | 
												  *this, &AP_WS_Connection::OnSocketError));
 | 
				
			||||||
 | 
									Registered_=false;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								WS_->close();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if(!SerialNumber_.empty()) {
 | 
				
			||||||
 | 
									DeviceDisconnectionCleanup(SerialNumber_, uuid_);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if(Clean)
 | 
				
			||||||
 | 
									AP_WS_Server()->EndSession(State_.sessionId, SerialNumberInt_);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	bool AP_WS_Connection::ValidatedDevice() {
 | 
						bool AP_WS_Connection::ValidatedDevice() {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if(Dead_)
 | 
				
			||||||
 | 
								return false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (DeviceValidated_)
 | 
							if (DeviceValidated_)
 | 
				
			||||||
			return true;
 | 
								return true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (!Valid_)
 | 
					 | 
				
			||||||
			return false;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		std::lock_guard Lock(ConnectionMutex_);
 | 
					 | 
				
			||||||
		try {
 | 
							try {
 | 
				
			||||||
			auto SockImpl = dynamic_cast<Poco::Net::WebSocketImpl *>(WS_->impl());
 | 
								auto SockImpl = dynamic_cast<Poco::Net::WebSocketImpl *>(WS_->impl());
 | 
				
			||||||
			auto SS =
 | 
								auto SS =
 | 
				
			||||||
@@ -98,7 +156,6 @@ namespace OpenWifi {
 | 
				
			|||||||
				poco_warning(Logger_, fmt::format("TLS-CONNECTION({}): Session={} Connection is "
 | 
									poco_warning(Logger_, fmt::format("TLS-CONNECTION({}): Session={} Connection is "
 | 
				
			||||||
												  "NOT secure. Device is not allowed.",
 | 
																	  "NOT secure. Device is not allowed.",
 | 
				
			||||||
												  CId_, State_.sessionId));
 | 
																	  CId_, State_.sessionId));
 | 
				
			||||||
				EndConnection();
 | 
					 | 
				
			||||||
				return false;
 | 
									return false;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -111,7 +168,6 @@ namespace OpenWifi {
 | 
				
			|||||||
					Logger_,
 | 
										Logger_,
 | 
				
			||||||
					fmt::format("TLS-CONNECTION({}): Session={} No certificates available..", CId_,
 | 
										fmt::format("TLS-CONNECTION({}): Session={} No certificates available..", CId_,
 | 
				
			||||||
								State_.sessionId));
 | 
													State_.sessionId));
 | 
				
			||||||
				EndConnection();
 | 
					 | 
				
			||||||
				return false;
 | 
									return false;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -122,11 +178,19 @@ namespace OpenWifi {
 | 
				
			|||||||
							 fmt::format("TLS-CONNECTION({}): Session={} Device certificate is not "
 | 
												 fmt::format("TLS-CONNECTION({}): Session={} Device certificate is not "
 | 
				
			||||||
										 "valid. Device is not allowed.",
 | 
															 "valid. Device is not allowed.",
 | 
				
			||||||
										 CId_, State_.sessionId));
 | 
															 CId_, State_.sessionId));
 | 
				
			||||||
				EndConnection();
 | 
					 | 
				
			||||||
				return false;
 | 
									return false;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			CN_ = Poco::trim(Poco::toLower(PeerCert.commonName()));
 | 
								CN_ = Poco::trim(Poco::toLower(PeerCert.commonName()));
 | 
				
			||||||
 | 
								if(!Utils::ValidSerialNumber(CN_)) {
 | 
				
			||||||
 | 
									poco_trace(Logger_,
 | 
				
			||||||
 | 
											   fmt::format("TLS-CONNECTION({}): Session={} Invalid serial number: CN={}", CId_,
 | 
				
			||||||
 | 
														   State_.sessionId, CN_));
 | 
				
			||||||
 | 
									return false;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								SerialNumber_ = CN_;
 | 
				
			||||||
 | 
								SerialNumberInt_ = Utils::SerialNumberToInt(SerialNumber_);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			State_.VerifiedCertificate = GWObjects::VALID_CERTIFICATE;
 | 
								State_.VerifiedCertificate = GWObjects::VALID_CERTIFICATE;
 | 
				
			||||||
			poco_trace(Logger_,
 | 
								poco_trace(Logger_,
 | 
				
			||||||
					   fmt::format("TLS-CONNECTION({}): Session={} Valid certificate: CN={}", CId_,
 | 
										   fmt::format("TLS-CONNECTION({}): Session={} Valid certificate: CN={}", CId_,
 | 
				
			||||||
@@ -136,31 +200,27 @@ namespace OpenWifi {
 | 
				
			|||||||
				poco_warning(Logger_, fmt::format("TLS-CONNECTION({}): Session={} Sim Device {} is "
 | 
									poco_warning(Logger_, fmt::format("TLS-CONNECTION({}): Session={} Sim Device {} is "
 | 
				
			||||||
												  "not allowed. Disconnecting.",
 | 
																	  "not allowed. Disconnecting.",
 | 
				
			||||||
												  CId_, State_.sessionId, CN_));
 | 
																	  CId_, State_.sessionId, CN_));
 | 
				
			||||||
				EndConnection();
 | 
					 | 
				
			||||||
				return false;
 | 
									return false;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if(AP_WS_Server::IsSim(CN_)) {
 | 
								if(AP_WS_Server::IsSim(SerialNumber_)) {
 | 
				
			||||||
				State_.VerifiedCertificate = GWObjects::SIMULATED;
 | 
									State_.VerifiedCertificate = GWObjects::SIMULATED;
 | 
				
			||||||
				Simulated_ = true;
 | 
									Simulated_ = true;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			std::string reason, author;
 | 
								std::string reason, author;
 | 
				
			||||||
			std::uint64_t created;
 | 
								std::uint64_t created;
 | 
				
			||||||
			if (!CN_.empty() && StorageService()->IsBlackListed(CN_, reason, author, created)) {
 | 
								if (!CN_.empty() && StorageService()->IsBlackListed(SerialNumberInt_, reason, author, created)) {
 | 
				
			||||||
				DeviceBlacklistedKafkaEvent KE(Utils::SerialNumberToInt(CN_), Utils::Now(), reason, author, created, CId_);
 | 
									DeviceBlacklistedKafkaEvent KE(Utils::SerialNumberToInt(CN_), Utils::Now(), reason, author, created, CId_);
 | 
				
			||||||
				poco_warning(
 | 
									poco_warning(
 | 
				
			||||||
					Logger_,
 | 
										Logger_,
 | 
				
			||||||
					fmt::format(
 | 
										fmt::format(
 | 
				
			||||||
						"TLS-CONNECTION({}): Session={} Device {} is black listed. Disconnecting.",
 | 
											"TLS-CONNECTION({}): Session={} Device {} is black listed. Disconnecting.",
 | 
				
			||||||
						CId_, State_.sessionId, CN_));
 | 
											CId_, State_.sessionId, CN_));
 | 
				
			||||||
				EndConnection();
 | 
					 | 
				
			||||||
				return false;
 | 
									return false;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			State_.certificateExpiryDate = PeerCert.expiresOn().timestamp().epochTime();
 | 
								State_.certificateExpiryDate = PeerCert.expiresOn().timestamp().epochTime();
 | 
				
			||||||
			SerialNumber_ = CN_;
 | 
					 | 
				
			||||||
			SerialNumberInt_ = Utils::SerialNumberToInt(SerialNumber_);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
			poco_trace(Logger_,
 | 
								poco_trace(Logger_,
 | 
				
			||||||
					   fmt::format("TLS-CONNECTION({}): Session={} CN={} Completed. (t={})", CId_,
 | 
										   fmt::format("TLS-CONNECTION({}): Session={} CN={} Completed. (t={})", CId_,
 | 
				
			||||||
@@ -224,149 +284,14 @@ namespace OpenWifi {
 | 
				
			|||||||
		return false;
 | 
							return false;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	static void NotifyKafkaDisconnect(const std::string &SerialNumber, std::uint64_t uuid) {
 | 
						void AP_WS_Connection::DeviceDisconnectionCleanup(const std::string &SerialNumber, std::uint64_t uuid) {
 | 
				
			||||||
		try {
 | 
					 | 
				
			||||||
			Poco::JSON::Object Disconnect;
 | 
					 | 
				
			||||||
			Poco::JSON::Object Details;
 | 
					 | 
				
			||||||
			Details.set(uCentralProtocol::SERIALNUMBER, SerialNumber);
 | 
					 | 
				
			||||||
			Details.set(uCentralProtocol::TIMESTAMP, Utils::Now());
 | 
					 | 
				
			||||||
			Details.set(uCentralProtocol::UUID,uuid);
 | 
					 | 
				
			||||||
			Disconnect.set(uCentralProtocol::DISCONNECTION, Details);
 | 
					 | 
				
			||||||
			KafkaManager()->PostMessage(KafkaTopics::CONNECTION, SerialNumber, Disconnect);
 | 
					 | 
				
			||||||
		} catch (...) {
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	AP_WS_Connection::~AP_WS_Connection() {
 | 
					 | 
				
			||||||
		Valid_ = false;
 | 
					 | 
				
			||||||
		EndConnection();
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	void DeviceDisconnectionCleanup(const std::string &SerialNumber, std::uint64_t uuid) {
 | 
					 | 
				
			||||||
		if (KafkaManager()->Enabled()) {
 | 
							if (KafkaManager()->Enabled()) {
 | 
				
			||||||
			NotifyKafkaDisconnect(SerialNumber, uuid);
 | 
								NotifyKafkaDisconnect(SerialNumber, uuid);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		RADIUSSessionTracker()->DeviceDisconnect(SerialNumber);
 | 
							RADIUSSessionTracker()->DeviceDisconnect(SerialNumber);
 | 
				
			||||||
	}
 | 
							GWWebSocketNotifications::SingleDevice_t N;
 | 
				
			||||||
 | 
							N.content.serialNumber = SerialNumber;
 | 
				
			||||||
	void AP_WS_Connection::EndConnection(bool DeleteSession) {
 | 
							GWWebSocketNotifications::DeviceDisconnected(N);
 | 
				
			||||||
    	Valid_ = false;
 | 
					 | 
				
			||||||
		if (!Dead_.test_and_set()) {
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			if(!SerialNumber_.empty() && State_.LastContact!=0) {
 | 
					 | 
				
			||||||
				StorageService()->SetDeviceLastRecordedContact(SerialNumber_, State_.LastContact);
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			if (Registered_) {
 | 
					 | 
				
			||||||
				Registered_ = false;
 | 
					 | 
				
			||||||
				Reactor_.removeEventHandler(
 | 
					 | 
				
			||||||
					*WS_, Poco::NObserver<AP_WS_Connection, Poco::Net::ReadableNotification>(
 | 
					 | 
				
			||||||
							  *this, &AP_WS_Connection::OnSocketReadable));
 | 
					 | 
				
			||||||
				Reactor_.removeEventHandler(
 | 
					 | 
				
			||||||
					*WS_, Poco::NObserver<AP_WS_Connection, Poco::Net::ShutdownNotification>(
 | 
					 | 
				
			||||||
							  *this, &AP_WS_Connection::OnSocketShutdown));
 | 
					 | 
				
			||||||
				Reactor_.removeEventHandler(
 | 
					 | 
				
			||||||
					*WS_, Poco::NObserver<AP_WS_Connection, Poco::Net::ErrorNotification>(
 | 
					 | 
				
			||||||
							  *this, &AP_WS_Connection::OnSocketError));
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			WS_->close();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			if(!SerialNumber_.empty()) {
 | 
					 | 
				
			||||||
				std::thread	Cleanup(DeviceDisconnectionCleanup,SerialNumber_, uuid_);
 | 
					 | 
				
			||||||
				Cleanup.detach();
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			bool SessionDeleted = false;
 | 
					 | 
				
			||||||
			if(DeleteSession)
 | 
					 | 
				
			||||||
				SessionDeleted = AP_WS_Server()->EndSession(State_.sessionId, SerialNumberInt_);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			if (SessionDeleted || !DeleteSession) {
 | 
					 | 
				
			||||||
				GWWebSocketNotifications::SingleDevice_t N;
 | 
					 | 
				
			||||||
				N.content.serialNumber = SerialNumber_;
 | 
					 | 
				
			||||||
				GWWebSocketNotifications::DeviceDisconnected(N);
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	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)
 | 
					 | 
				
			||||||
			return false;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		uint64_t GoodConfig = ConfigurationCache().CurrentConfig(SerialNumberInt_);
 | 
					 | 
				
			||||||
		if (GoodConfig && (GoodConfig == UUID || GoodConfig == State_.PendingUUID)) {
 | 
					 | 
				
			||||||
			UpgradedUUID = UUID;
 | 
					 | 
				
			||||||
			return false;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		GWObjects::Device D;
 | 
					 | 
				
			||||||
		if (StorageService()->GetDevice(SerialNumber_, D)) {
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			if(D.pendingUUID!=0 && UUID==D.pendingUUID) {
 | 
					 | 
				
			||||||
				//	so we sent an upgrade to a device, and now it is completing now...
 | 
					 | 
				
			||||||
				UpgradedUUID = D.pendingUUID;
 | 
					 | 
				
			||||||
				StorageService()->CompleteDeviceConfigurationChange(SerialNumber_);
 | 
					 | 
				
			||||||
				return true;
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			//	This is the case where the cache is empty after a restart. So GoodConfig will 0. If
 | 
					 | 
				
			||||||
			// the device already 	has the right UUID, we just return.
 | 
					 | 
				
			||||||
			if (D.UUID == UUID) {
 | 
					 | 
				
			||||||
				UpgradedUUID = UUID;
 | 
					 | 
				
			||||||
				ConfigurationCache().Add(SerialNumberInt_, UUID);
 | 
					 | 
				
			||||||
				return false;
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			Config::Config Cfg(D.Configuration);
 | 
					 | 
				
			||||||
			if (UUID > D.UUID) {
 | 
					 | 
				
			||||||
				//	so we have a problem, the device has a newer config than we have. So we need to
 | 
					 | 
				
			||||||
				// make sure our config 	is newer.
 | 
					 | 
				
			||||||
				D.UUID = UUID + 2;
 | 
					 | 
				
			||||||
				UpgradedUUID = D.UUID;
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			Cfg.SetUUID(D.UUID);
 | 
					 | 
				
			||||||
			D.Configuration = Cfg.get();
 | 
					 | 
				
			||||||
			State_.PendingUUID = UpgradedUUID = D.UUID;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			GWObjects::CommandDetails Cmd;
 | 
					 | 
				
			||||||
			Cmd.SerialNumber = SerialNumber_;
 | 
					 | 
				
			||||||
			Cmd.UUID = MicroServiceCreateUUID();
 | 
					 | 
				
			||||||
			Cmd.SubmittedBy = uCentralProtocol::SUBMITTED_BY_SYSTEM;
 | 
					 | 
				
			||||||
			Cmd.Status = uCentralProtocol::PENDING;
 | 
					 | 
				
			||||||
			Cmd.Command = uCentralProtocol::CONFIGURE;
 | 
					 | 
				
			||||||
			Poco::JSON::Parser P;
 | 
					 | 
				
			||||||
			auto ParsedConfig = P.parse(D.Configuration).extract<Poco::JSON::Object::Ptr>();
 | 
					 | 
				
			||||||
			Poco::JSON::Object Params;
 | 
					 | 
				
			||||||
			Params.set(uCentralProtocol::SERIAL, SerialNumber_);
 | 
					 | 
				
			||||||
			Params.set(uCentralProtocol::UUID, D.UUID);
 | 
					 | 
				
			||||||
			Params.set(uCentralProtocol::WHEN, 0);
 | 
					 | 
				
			||||||
			Params.set(uCentralProtocol::CONFIG, ParsedConfig);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			std::ostringstream O;
 | 
					 | 
				
			||||||
			Poco::JSON::Stringifier::stringify(Params, O);
 | 
					 | 
				
			||||||
			Cmd.Details = O.str();
 | 
					 | 
				
			||||||
			poco_information(Logger_,
 | 
					 | 
				
			||||||
							 fmt::format("CFG-UPGRADE({}): Current ID: {}, newer configuration {}.",
 | 
					 | 
				
			||||||
										 CId_, UUID, D.UUID));
 | 
					 | 
				
			||||||
			bool Sent;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			StorageService()->AddCommand(SerialNumber_, Cmd,
 | 
					 | 
				
			||||||
										 Storage::CommandExecutionType::COMMAND_EXECUTED);
 | 
					 | 
				
			||||||
			CommandManager()->PostCommand(
 | 
					 | 
				
			||||||
				CommandManager()->Next_RPC_ID(), APCommands::to_apcommand(Cmd.Command.c_str()),
 | 
					 | 
				
			||||||
				SerialNumber_, Cmd.Command, Params, Cmd.UUID, Sent, false, false);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			GWWebSocketNotifications::SingleDeviceConfigurationChange_t Notification;
 | 
					 | 
				
			||||||
			Notification.content.serialNumber = D.SerialNumber;
 | 
					 | 
				
			||||||
			Notification.content.oldUUID = UUID;
 | 
					 | 
				
			||||||
			Notification.content.newUUID = UpgradedUUID;
 | 
					 | 
				
			||||||
			GWWebSocketNotifications::DeviceConfigurationChange(Notification);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			return true;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		return false;
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	void AP_WS_Connection::ProcessJSONRPCResult(Poco::JSON::Object::Ptr Doc) {
 | 
						void AP_WS_Connection::ProcessJSONRPCResult(Poco::JSON::Object::Ptr Doc) {
 | 
				
			||||||
@@ -447,7 +372,7 @@ namespace OpenWifi {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
		std::string reason, author;
 | 
							std::string reason, author;
 | 
				
			||||||
		std::uint64_t created;
 | 
							std::uint64_t created;
 | 
				
			||||||
		if (StorageService()->IsBlackListed(Serial, reason, author, created)) {
 | 
							if (StorageService()->IsBlackListed(SerialNumberInt_, reason, author, created)) {
 | 
				
			||||||
			DeviceBlacklistedKafkaEvent KE(Utils::SerialNumberToInt(CN_), Utils::Now(), reason, author, created, CId_);
 | 
								DeviceBlacklistedKafkaEvent KE(Utils::SerialNumberToInt(CN_), Utils::Now(), reason, author, created, CId_);
 | 
				
			||||||
			Poco::Exception E(
 | 
								Poco::Exception E(
 | 
				
			||||||
				fmt::format("BLACKLIST({}): device is blacklisted and not allowed to connect.",
 | 
									fmt::format("BLACKLIST({}): device is blacklisted and not allowed to connect.",
 | 
				
			||||||
@@ -578,17 +503,17 @@ namespace OpenWifi {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	bool AP_WS_Connection::SetWebSocketTelemetryReporting(
 | 
						bool AP_WS_Connection::SetWebSocketTelemetryReporting(
 | 
				
			||||||
		uint64_t RPCID, uint64_t Interval, uint64_t LifeTime,
 | 
							std::uint64_t RPCID, std::uint64_t Interval, std::uint64_t LifeTime,
 | 
				
			||||||
		const std::vector<std::string> &TelemetryTypes) {
 | 
							const std::vector<std::string> &TelemetryTypes) {
 | 
				
			||||||
		std::unique_lock Lock(TelemetryMutex_);
 | 
							std::unique_lock Lock(TelemetryMutex_);
 | 
				
			||||||
		TelemetryWebSocketRefCount_++;
 | 
							TelemetryWebSocketRefCount_++;
 | 
				
			||||||
		TelemetryInterval_ = TelemetryInterval_
 | 
							TelemetryInterval_ = TelemetryInterval_
 | 
				
			||||||
								 ? (Interval < TelemetryInterval_ ? Interval : TelemetryInterval_)
 | 
													 ? (Interval < (std::uint64_t)TelemetryInterval_ ? Interval : (std::uint64_t )TelemetryInterval_)
 | 
				
			||||||
								 : Interval;
 | 
													 : Interval;
 | 
				
			||||||
		auto TelemetryWebSocketTimer = LifeTime + Utils::Now();
 | 
							auto TelemetryWebSocketTimer = LifeTime + Utils::Now();
 | 
				
			||||||
		TelemetryWebSocketTimer_ = TelemetryWebSocketTimer > TelemetryWebSocketTimer_
 | 
							TelemetryWebSocketTimer_ = TelemetryWebSocketTimer > (std::uint64_t)TelemetryWebSocketTimer_
 | 
				
			||||||
									   ? TelemetryWebSocketTimer
 | 
														   ? (std::uint64_t)TelemetryWebSocketTimer
 | 
				
			||||||
									   : TelemetryWebSocketTimer_;
 | 
														   : (std::uint64_t)TelemetryWebSocketTimer_;
 | 
				
			||||||
		UpdateCounts();
 | 
							UpdateCounts();
 | 
				
			||||||
		if (!TelemetryReporting_) {
 | 
							if (!TelemetryReporting_) {
 | 
				
			||||||
			TelemetryReporting_ = true;
 | 
								TelemetryReporting_ = true;
 | 
				
			||||||
@@ -604,11 +529,11 @@ namespace OpenWifi {
 | 
				
			|||||||
		std::unique_lock Lock(TelemetryMutex_);
 | 
							std::unique_lock Lock(TelemetryMutex_);
 | 
				
			||||||
		TelemetryKafkaRefCount_++;
 | 
							TelemetryKafkaRefCount_++;
 | 
				
			||||||
		TelemetryInterval_ = TelemetryInterval_
 | 
							TelemetryInterval_ = TelemetryInterval_
 | 
				
			||||||
								 ? (Interval < TelemetryInterval_ ? Interval : TelemetryInterval_)
 | 
													 ? (Interval < (std::uint64_t)TelemetryInterval_ ? (std::uint64_t)Interval : (std::uint64_t)TelemetryInterval_)
 | 
				
			||||||
								 : Interval;
 | 
													 : Interval;
 | 
				
			||||||
		auto TelemetryKafkaTimer = LifeTime + Utils::Now();
 | 
							auto TelemetryKafkaTimer = LifeTime + Utils::Now();
 | 
				
			||||||
		TelemetryKafkaTimer_ =
 | 
							TelemetryKafkaTimer_ =
 | 
				
			||||||
			TelemetryKafkaTimer > TelemetryKafkaTimer_ ? TelemetryKafkaTimer : TelemetryKafkaTimer_;
 | 
								TelemetryKafkaTimer > (std::uint64_t)TelemetryKafkaTimer_ ? (std::uint64_t)TelemetryKafkaTimer : (std::uint64_t)TelemetryKafkaTimer_;
 | 
				
			||||||
		UpdateCounts();
 | 
							UpdateCounts();
 | 
				
			||||||
		if (!TelemetryReporting_) {
 | 
							if (!TelemetryReporting_) {
 | 
				
			||||||
			TelemetryReporting_ = true;
 | 
								TelemetryReporting_ = true;
 | 
				
			||||||
@@ -644,49 +569,50 @@ namespace OpenWifi {
 | 
				
			|||||||
	void AP_WS_Connection::OnSocketShutdown(
 | 
						void AP_WS_Connection::OnSocketShutdown(
 | 
				
			||||||
		[[maybe_unused]] const Poco::AutoPtr<Poco::Net::ShutdownNotification> &pNf) {
 | 
							[[maybe_unused]] const Poco::AutoPtr<Poco::Net::ShutdownNotification> &pNf) {
 | 
				
			||||||
		poco_trace(Logger_, fmt::format("SOCKET-SHUTDOWN({}): Closing.", CId_));
 | 
							poco_trace(Logger_, fmt::format("SOCKET-SHUTDOWN({}): Closing.", CId_));
 | 
				
			||||||
 | 
							std::lock_guard	G(ConnectionMutex_);
 | 
				
			||||||
		return EndConnection();
 | 
							return EndConnection();
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	void AP_WS_Connection::OnSocketError(
 | 
						void AP_WS_Connection::OnSocketError(
 | 
				
			||||||
		[[maybe_unused]] const Poco::AutoPtr<Poco::Net::ErrorNotification> &pNf) {
 | 
							[[maybe_unused]] const Poco::AutoPtr<Poco::Net::ErrorNotification> &pNf) {
 | 
				
			||||||
		poco_trace(Logger_, fmt::format("SOCKET-ERROR({}): Closing.", CId_));
 | 
							poco_trace(Logger_, fmt::format("SOCKET-ERROR({}): Closing.", CId_));
 | 
				
			||||||
 | 
							std::lock_guard	G(ConnectionMutex_);
 | 
				
			||||||
		return EndConnection();
 | 
							return EndConnection();
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	void AP_WS_Connection::OnSocketReadable(
 | 
						void AP_WS_Connection::OnSocketReadable(
 | 
				
			||||||
		[[maybe_unused]] const Poco::AutoPtr<Poco::Net::ReadableNotification> &pNf) {
 | 
							[[maybe_unused]] const Poco::AutoPtr<Poco::Net::ReadableNotification> &pNf) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (!Valid_)
 | 
							if (Dead_) //	we are dead, so we do not process anything.
 | 
				
			||||||
			return;
 | 
								return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (!AP_WS_Server()->Running())
 | 
							std::lock_guard	DeviceLock(ConnectionMutex_);
 | 
				
			||||||
			return EndConnection();
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (!ValidatedDevice())
 | 
							State_.LastContact = LastContact_ = Utils::Now();
 | 
				
			||||||
			return;
 | 
							if (AP_WS_Server()->Running() && (DeviceValidated_ || ValidatedDevice())) {
 | 
				
			||||||
 | 
								try {
 | 
				
			||||||
		try {
 | 
									return ProcessIncomingFrame();
 | 
				
			||||||
			return ProcessIncomingFrame();
 | 
								} catch (const Poco::Exception &E) {
 | 
				
			||||||
		} catch (const Poco::Exception &E) {
 | 
									Logger_.log(E);
 | 
				
			||||||
			Logger_.log(E);
 | 
								} catch (const std::exception &E) {
 | 
				
			||||||
			return EndConnection();
 | 
									std::string W = E.what();
 | 
				
			||||||
		} catch (const std::exception &E) {
 | 
									poco_information(
 | 
				
			||||||
			std::string W = E.what();
 | 
										Logger_, fmt::format("std::exception caught: {}. Connection terminated with {}",
 | 
				
			||||||
			poco_information(
 | 
															 W, CId_));
 | 
				
			||||||
				Logger_,
 | 
								} catch (...) {
 | 
				
			||||||
				fmt::format("std::exception caught: {}. Connection terminated with {}", W, CId_));
 | 
									poco_information(
 | 
				
			||||||
			return EndConnection();
 | 
										Logger_, fmt::format("Unknown exception for {}. Connection terminated.", CId_));
 | 
				
			||||||
		} catch (...) {
 | 
								}
 | 
				
			||||||
			poco_information(Logger_,
 | 
					 | 
				
			||||||
							 fmt::format("Unknown exception for {}. Connection terminated.", CId_));
 | 
					 | 
				
			||||||
			return EndConnection();
 | 
					 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
							EndConnection();
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	void AP_WS_Connection::ProcessIncomingFrame() {
 | 
						void AP_WS_Connection::ProcessIncomingFrame() {
 | 
				
			||||||
		Poco::Buffer<char> IncomingFrame(0);
 | 
							Poco::Buffer<char> IncomingFrame(0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							bool	KillConnection=false;
 | 
				
			||||||
		try {
 | 
							try {
 | 
				
			||||||
			int Op, flags;
 | 
								int 	Op, flags;
 | 
				
			||||||
			auto IncomingSize = WS_->receiveFrame(IncomingFrame, flags);
 | 
								auto IncomingSize = WS_->receiveFrame(IncomingFrame, flags);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			Op = flags & Poco::Net::WebSocket::FRAME_OP_BITMASK;
 | 
								Op = flags & Poco::Net::WebSocket::FRAME_OP_BITMASK;
 | 
				
			||||||
@@ -706,83 +632,81 @@ namespace OpenWifi {
 | 
				
			|||||||
			State_.LastContact = Utils::Now();
 | 
								State_.LastContact = Utils::Now();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			switch (Op) {
 | 
								switch (Op) {
 | 
				
			||||||
			case Poco::Net::WebSocket::FRAME_OP_PING: {
 | 
									case Poco::Net::WebSocket::FRAME_OP_PING: {
 | 
				
			||||||
				poco_trace(Logger_, fmt::format("WS-PING({}): received. PONG sent back.", CId_));
 | 
										poco_trace(Logger_, fmt::format("WS-PING({}): received. PONG sent back.", CId_));
 | 
				
			||||||
				WS_->sendFrame("", 0,
 | 
										WS_->sendFrame("", 0,
 | 
				
			||||||
							   (int)Poco::Net::WebSocket::FRAME_OP_PONG |
 | 
													   (int)Poco::Net::WebSocket::FRAME_OP_PONG |
 | 
				
			||||||
								   (int)Poco::Net::WebSocket::FRAME_FLAG_FIN);
 | 
														   (int)Poco::Net::WebSocket::FRAME_FLAG_FIN);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				if (KafkaManager()->Enabled()) {
 | 
										if (KafkaManager()->Enabled()) {
 | 
				
			||||||
					Poco::JSON::Object PingObject;
 | 
											Poco::JSON::Object PingObject;
 | 
				
			||||||
					Poco::JSON::Object PingDetails;
 | 
											Poco::JSON::Object PingDetails;
 | 
				
			||||||
					PingDetails.set(uCentralProtocol::FIRMWARE, State_.Firmware);
 | 
											PingDetails.set(uCentralProtocol::FIRMWARE, State_.Firmware);
 | 
				
			||||||
					PingDetails.set(uCentralProtocol::SERIALNUMBER, SerialNumber_);
 | 
											PingDetails.set(uCentralProtocol::SERIALNUMBER, SerialNumber_);
 | 
				
			||||||
					PingDetails.set(uCentralProtocol::COMPATIBLE, Compatible_);
 | 
											PingDetails.set(uCentralProtocol::COMPATIBLE, Compatible_);
 | 
				
			||||||
					PingDetails.set(uCentralProtocol::CONNECTIONIP, CId_);
 | 
											PingDetails.set(uCentralProtocol::CONNECTIONIP, CId_);
 | 
				
			||||||
					PingDetails.set(uCentralProtocol::TIMESTAMP, Utils::Now());
 | 
											PingDetails.set(uCentralProtocol::TIMESTAMP, Utils::Now());
 | 
				
			||||||
					PingDetails.set(uCentralProtocol::UUID, uuid_);
 | 
											PingDetails.set(uCentralProtocol::UUID, uuid_);
 | 
				
			||||||
					PingDetails.set("locale", State_.locale);
 | 
											PingDetails.set("locale", State_.locale);
 | 
				
			||||||
					PingObject.set(uCentralProtocol::PING, PingDetails);
 | 
											PingObject.set(uCentralProtocol::PING, PingDetails);
 | 
				
			||||||
					poco_trace(Logger_,fmt::format("Sending PING for {}", SerialNumber_));
 | 
											poco_trace(Logger_,fmt::format("Sending PING for {}", SerialNumber_));
 | 
				
			||||||
					KafkaManager()->PostMessage(KafkaTopics::CONNECTION, SerialNumber_,PingObject);
 | 
											KafkaManager()->PostMessage(KafkaTopics::CONNECTION, SerialNumber_,PingObject);
 | 
				
			||||||
				}
 | 
										}
 | 
				
			||||||
				return;
 | 
									} break;
 | 
				
			||||||
			} break;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
			case Poco::Net::WebSocket::FRAME_OP_PONG: {
 | 
									case Poco::Net::WebSocket::FRAME_OP_PONG: {
 | 
				
			||||||
				poco_trace(Logger_, fmt::format("PONG({}): received and ignored.", CId_));
 | 
										poco_trace(Logger_, fmt::format("PONG({}): received and ignored.", CId_));
 | 
				
			||||||
				return;
 | 
									} break;
 | 
				
			||||||
			} break;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
			case Poco::Net::WebSocket::FRAME_OP_TEXT: {
 | 
									case Poco::Net::WebSocket::FRAME_OP_TEXT: {
 | 
				
			||||||
				poco_trace(Logger_,
 | 
										poco_trace(Logger_,
 | 
				
			||||||
						   fmt::format("FRAME({}): Frame received (length={}, flags={}). Msg={}",
 | 
												   fmt::format("FRAME({}): Frame received (length={}, flags={}). Msg={}",
 | 
				
			||||||
									   CId_, IncomingSize, flags, IncomingFrame.begin()));
 | 
															   CId_, IncomingSize, flags, IncomingFrame.begin()));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				Poco::JSON::Parser parser;
 | 
										Poco::JSON::Parser parser;
 | 
				
			||||||
				auto ParsedMessage = parser.parse(IncomingFrame.begin());
 | 
										auto ParsedMessage = parser.parse(IncomingFrame.begin());
 | 
				
			||||||
				auto IncomingJSON = ParsedMessage.extract<Poco::JSON::Object::Ptr>();
 | 
										auto IncomingJSON = ParsedMessage.extract<Poco::JSON::Object::Ptr>();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				if (IncomingJSON->has(uCentralProtocol::JSONRPC)) {
 | 
										if (IncomingJSON->has(uCentralProtocol::JSONRPC)) {
 | 
				
			||||||
					if (IncomingJSON->has(uCentralProtocol::METHOD) &&
 | 
											if (IncomingJSON->has(uCentralProtocol::METHOD) &&
 | 
				
			||||||
						IncomingJSON->has(uCentralProtocol::PARAMS)) {
 | 
												IncomingJSON->has(uCentralProtocol::PARAMS)) {
 | 
				
			||||||
						ProcessJSONRPCEvent(IncomingJSON);
 | 
												ProcessJSONRPCEvent(IncomingJSON);
 | 
				
			||||||
					} else if (IncomingJSON->has(uCentralProtocol::RESULT) &&
 | 
											} else if (IncomingJSON->has(uCentralProtocol::RESULT) &&
 | 
				
			||||||
							   IncomingJSON->has(uCentralProtocol::ID)) {
 | 
													   IncomingJSON->has(uCentralProtocol::ID)) {
 | 
				
			||||||
						poco_trace(Logger_, fmt::format("RPC-RESULT({}): payload: {}", CId_,
 | 
												poco_trace(Logger_, fmt::format("RPC-RESULT({}): payload: {}", CId_,
 | 
				
			||||||
														IncomingFrame.begin()));
 | 
																				IncomingFrame.begin()));
 | 
				
			||||||
						ProcessJSONRPCResult(IncomingJSON);
 | 
												ProcessJSONRPCResult(IncomingJSON);
 | 
				
			||||||
 | 
											} else {
 | 
				
			||||||
 | 
												poco_warning(
 | 
				
			||||||
 | 
													Logger_,
 | 
				
			||||||
 | 
													fmt::format("INVALID-PAYLOAD({}): Payload is not JSON-RPC 2.0: {}",
 | 
				
			||||||
 | 
																CId_, IncomingFrame.begin()));
 | 
				
			||||||
 | 
											}
 | 
				
			||||||
 | 
										} else if (IncomingJSON->has(uCentralProtocol::RADIUS)) {
 | 
				
			||||||
 | 
											ProcessIncomingRadiusData(IncomingJSON);
 | 
				
			||||||
					} else {
 | 
										} else {
 | 
				
			||||||
 | 
											std::ostringstream iS;
 | 
				
			||||||
 | 
											IncomingJSON->stringify(iS);
 | 
				
			||||||
						poco_warning(
 | 
											poco_warning(
 | 
				
			||||||
							Logger_,
 | 
												Logger_,
 | 
				
			||||||
							fmt::format("INVALID-PAYLOAD({}): Payload is not JSON-RPC 2.0: {}",
 | 
												fmt::format("FRAME({}): illegal transaction header, missing 'jsonrpc': {}",
 | 
				
			||||||
										CId_, IncomingFrame.begin()));
 | 
															CId_, iS.str()));
 | 
				
			||||||
 | 
											Errors_++;
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
				} else if (IncomingJSON->has(uCentralProtocol::RADIUS)) {
 | 
									} break;
 | 
				
			||||||
					ProcessIncomingRadiusData(IncomingJSON);
 | 
					
 | 
				
			||||||
				} else {
 | 
									case Poco::Net::WebSocket::FRAME_OP_CLOSE: {
 | 
				
			||||||
					std::ostringstream iS;
 | 
										poco_information(Logger_,
 | 
				
			||||||
					IncomingJSON->stringify(iS);
 | 
														 fmt::format("CLOSE({}): Device is closing its connection.", CId_));
 | 
				
			||||||
					std::cout << iS.str() << std::endl;
 | 
										KillConnection=true;
 | 
				
			||||||
					poco_warning(
 | 
									} break;
 | 
				
			||||||
						Logger_,
 | 
					
 | 
				
			||||||
						fmt::format("FRAME({}): illegal transaction header, missing 'jsonrpc'",
 | 
									default: {
 | 
				
			||||||
									CId_));
 | 
										poco_warning(Logger_, fmt::format("UNKNOWN({}): unknown WS Frame operation: {}",
 | 
				
			||||||
 | 
																		  CId_, std::to_string(Op)));
 | 
				
			||||||
					Errors_++;
 | 
										Errors_++;
 | 
				
			||||||
 | 
										return;
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
				return;
 | 
					 | 
				
			||||||
			} break;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			case Poco::Net::WebSocket::FRAME_OP_CLOSE: {
 | 
					 | 
				
			||||||
				poco_information(Logger_,
 | 
					 | 
				
			||||||
								 fmt::format("CLOSE({}): Device is closing its connection.", CId_));
 | 
					 | 
				
			||||||
				return EndConnection();
 | 
					 | 
				
			||||||
			} break;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			default: {
 | 
					 | 
				
			||||||
				poco_warning(Logger_, fmt::format("UNKNOWN({}): unknown WS Frame operation: {}",
 | 
					 | 
				
			||||||
												  CId_, std::to_string(Op)));
 | 
					 | 
				
			||||||
			} break;
 | 
					 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		} catch (const Poco::Net::ConnectionResetException &E) {
 | 
							} catch (const Poco::Net::ConnectionResetException &E) {
 | 
				
			||||||
			poco_warning(Logger_,
 | 
								poco_warning(Logger_,
 | 
				
			||||||
@@ -790,21 +714,21 @@ namespace OpenWifi {
 | 
				
			|||||||
									 CId_, E.displayText(),
 | 
														 CId_, E.displayText(),
 | 
				
			||||||
									 IncomingFrame.begin() == nullptr ? "" : IncomingFrame.begin(),
 | 
														 IncomingFrame.begin() == nullptr ? "" : IncomingFrame.begin(),
 | 
				
			||||||
									 State_.sessionId));
 | 
														 State_.sessionId));
 | 
				
			||||||
			return EndConnection();
 | 
								KillConnection=true;
 | 
				
			||||||
		} catch (const Poco::JSON::JSONException &E) {
 | 
							} catch (const Poco::JSON::JSONException &E) {
 | 
				
			||||||
			poco_warning(Logger_,
 | 
								poco_warning(Logger_,
 | 
				
			||||||
						 fmt::format("JSONException({}): Text:{} Payload:{} Session:{}", CId_,
 | 
											 fmt::format("JSONException({}): Text:{} Payload:{} Session:{}", CId_,
 | 
				
			||||||
									 E.displayText(),
 | 
														 E.displayText(),
 | 
				
			||||||
									 IncomingFrame.begin() == nullptr ? "" : IncomingFrame.begin(),
 | 
														 IncomingFrame.begin() == nullptr ? "" : IncomingFrame.begin(),
 | 
				
			||||||
									 State_.sessionId));
 | 
														 State_.sessionId));
 | 
				
			||||||
			return EndConnection();
 | 
								KillConnection=true;
 | 
				
			||||||
		} catch (const Poco::Net::WebSocketException &E) {
 | 
							} catch (const Poco::Net::WebSocketException &E) {
 | 
				
			||||||
			poco_warning(Logger_,
 | 
								poco_warning(Logger_,
 | 
				
			||||||
						 fmt::format("WebSocketException({}): Text:{} Payload:{} Session:{}", CId_,
 | 
											 fmt::format("WebSocketException({}): Text:{} Payload:{} Session:{}", CId_,
 | 
				
			||||||
									 E.displayText(),
 | 
														 E.displayText(),
 | 
				
			||||||
									 IncomingFrame.begin() == nullptr ? "" : IncomingFrame.begin(),
 | 
														 IncomingFrame.begin() == nullptr ? "" : IncomingFrame.begin(),
 | 
				
			||||||
									 State_.sessionId));
 | 
														 State_.sessionId));
 | 
				
			||||||
			return EndConnection();
 | 
								KillConnection=true;
 | 
				
			||||||
		} catch (const Poco::Net::SSLConnectionUnexpectedlyClosedException &E) {
 | 
							} catch (const Poco::Net::SSLConnectionUnexpectedlyClosedException &E) {
 | 
				
			||||||
			poco_warning(
 | 
								poco_warning(
 | 
				
			||||||
				Logger_,
 | 
									Logger_,
 | 
				
			||||||
@@ -813,54 +737,54 @@ namespace OpenWifi {
 | 
				
			|||||||
					CId_, E.displayText(),
 | 
										CId_, E.displayText(),
 | 
				
			||||||
					IncomingFrame.begin() == nullptr ? "" : IncomingFrame.begin(),
 | 
										IncomingFrame.begin() == nullptr ? "" : IncomingFrame.begin(),
 | 
				
			||||||
					State_.sessionId));
 | 
										State_.sessionId));
 | 
				
			||||||
			return EndConnection();
 | 
								KillConnection=true;
 | 
				
			||||||
		} catch (const Poco::Net::SSLException &E) {
 | 
							} catch (const Poco::Net::SSLException &E) {
 | 
				
			||||||
			poco_warning(Logger_,
 | 
								poco_warning(Logger_,
 | 
				
			||||||
						 fmt::format("SSLException({}): Text:{} Payload:{} Session:{}", CId_,
 | 
											 fmt::format("SSLException({}): Text:{} Payload:{} Session:{}", CId_,
 | 
				
			||||||
									 E.displayText(),
 | 
														 E.displayText(),
 | 
				
			||||||
									 IncomingFrame.begin() == nullptr ? "" : IncomingFrame.begin(),
 | 
														 IncomingFrame.begin() == nullptr ? "" : IncomingFrame.begin(),
 | 
				
			||||||
									 State_.sessionId));
 | 
														 State_.sessionId));
 | 
				
			||||||
			return EndConnection();
 | 
								KillConnection=true;
 | 
				
			||||||
		} catch (const Poco::Net::NetException &E) {
 | 
							} catch (const Poco::Net::NetException &E) {
 | 
				
			||||||
			poco_warning(Logger_,
 | 
								poco_warning(Logger_,
 | 
				
			||||||
						 fmt::format("NetException({}): Text:{} Payload:{} Session:{}", CId_,
 | 
											 fmt::format("NetException({}): Text:{} Payload:{} Session:{}", CId_,
 | 
				
			||||||
									 E.displayText(),
 | 
														 E.displayText(),
 | 
				
			||||||
									 IncomingFrame.begin() == nullptr ? "" : IncomingFrame.begin(),
 | 
														 IncomingFrame.begin() == nullptr ? "" : IncomingFrame.begin(),
 | 
				
			||||||
									 State_.sessionId));
 | 
														 State_.sessionId));
 | 
				
			||||||
			return EndConnection();
 | 
								KillConnection=true;
 | 
				
			||||||
		} catch (const Poco::IOException &E) {
 | 
							} catch (const Poco::IOException &E) {
 | 
				
			||||||
			poco_warning(Logger_,
 | 
								poco_warning(Logger_,
 | 
				
			||||||
						 fmt::format("IOException({}): Text:{} Payload:{} Session:{}", CId_,
 | 
											 fmt::format("IOException({}): Text:{} Payload:{} Session:{}", CId_,
 | 
				
			||||||
									 E.displayText(),
 | 
														 E.displayText(),
 | 
				
			||||||
									 IncomingFrame.begin() == nullptr ? "" : IncomingFrame.begin(),
 | 
														 IncomingFrame.begin() == nullptr ? "" : IncomingFrame.begin(),
 | 
				
			||||||
									 State_.sessionId));
 | 
														 State_.sessionId));
 | 
				
			||||||
			return EndConnection();
 | 
								KillConnection=true;
 | 
				
			||||||
		} catch (const Poco::Exception &E) {
 | 
							} catch (const Poco::Exception &E) {
 | 
				
			||||||
			poco_warning(Logger_,
 | 
								poco_warning(Logger_,
 | 
				
			||||||
						 fmt::format("Exception({}): Text:{} Payload:{} Session:{}", CId_,
 | 
											 fmt::format("Exception({}): Text:{} Payload:{} Session:{}", CId_,
 | 
				
			||||||
									 E.displayText(),
 | 
														 E.displayText(),
 | 
				
			||||||
									 IncomingFrame.begin() == nullptr ? "" : IncomingFrame.begin(),
 | 
														 IncomingFrame.begin() == nullptr ? "" : IncomingFrame.begin(),
 | 
				
			||||||
									 State_.sessionId));
 | 
														 State_.sessionId));
 | 
				
			||||||
			return EndConnection();
 | 
								KillConnection=true;
 | 
				
			||||||
		} catch (const std::exception &E) {
 | 
							} catch (const std::exception &E) {
 | 
				
			||||||
			poco_warning(Logger_,
 | 
								poco_warning(Logger_,
 | 
				
			||||||
						 fmt::format("std::exception({}): Text:{} Payload:{} Session:{}", CId_,
 | 
											 fmt::format("std::exception({}): Text:{} Payload:{} Session:{}", CId_,
 | 
				
			||||||
									 E.what(),
 | 
														 E.what(),
 | 
				
			||||||
									 IncomingFrame.begin() == nullptr ? "" : IncomingFrame.begin(),
 | 
														 IncomingFrame.begin() == nullptr ? "" : IncomingFrame.begin(),
 | 
				
			||||||
									 State_.sessionId));
 | 
														 State_.sessionId));
 | 
				
			||||||
			return EndConnection();
 | 
								KillConnection=true;
 | 
				
			||||||
		} catch (...) {
 | 
							} catch (...) {
 | 
				
			||||||
			poco_error(Logger_, fmt::format("UnknownException({}): Device must be disconnected. "
 | 
								poco_error(Logger_, fmt::format("UnknownException({}): Device must be disconnected. "
 | 
				
			||||||
											"Unknown exception.  Session:{}",
 | 
																"Unknown exception.  Session:{}",
 | 
				
			||||||
											CId_, State_.sessionId));
 | 
																CId_, State_.sessionId));
 | 
				
			||||||
			return EndConnection();
 | 
								KillConnection=true;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (Errors_ < 10)
 | 
							if (!KillConnection && Errors_ < 10)
 | 
				
			||||||
			return;
 | 
								return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		poco_warning(Logger_, fmt::format("DISCONNECTING({}): Too many errors", CId_));
 | 
							poco_warning(Logger_, fmt::format("DISCONNECTING({}): ConnectionException: {} Errors: {}", CId_, KillConnection, Errors_ ));
 | 
				
			||||||
		return EndConnection();
 | 
							EndConnection();
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	bool AP_WS_Connection::Send(const std::string &Payload) {
 | 
						bool AP_WS_Connection::Send(const std::string &Payload) {
 | 
				
			||||||
@@ -972,4 +896,36 @@ namespace OpenWifi {
 | 
				
			|||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						void AP_WS_Connection::SetLastStats(const std::string &LastStats) {
 | 
				
			||||||
 | 
							RawLastStats_ = LastStats;
 | 
				
			||||||
 | 
							try {
 | 
				
			||||||
 | 
								Poco::JSON::Parser P;
 | 
				
			||||||
 | 
								auto Stats = P.parse(LastStats).extract<Poco::JSON::Object::Ptr>();
 | 
				
			||||||
 | 
								hasGPS_ = Stats->isObject("gps");
 | 
				
			||||||
 | 
								auto Unit = Stats->getObject("unit");
 | 
				
			||||||
 | 
								auto Memory = Unit->getObject("memory");
 | 
				
			||||||
 | 
								std::uint64_t TotalMemory = Memory->get("total");
 | 
				
			||||||
 | 
								std::uint64_t FreeMemory = Memory->get("free");
 | 
				
			||||||
 | 
								if (TotalMemory > 0) {
 | 
				
			||||||
 | 
									memory_used_ =
 | 
				
			||||||
 | 
										(100.0 * ((double)TotalMemory - (double)FreeMemory)) / (double)TotalMemory;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								if (Unit->isArray("load")) {
 | 
				
			||||||
 | 
									Poco::JSON::Array::Ptr Load = Unit->getArray("load");
 | 
				
			||||||
 | 
									if (Load->size() > 1) {
 | 
				
			||||||
 | 
										cpu_load_ = Load->get(1);
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								if (Unit->isArray("temperature")) {
 | 
				
			||||||
 | 
									Poco::JSON::Array::Ptr Temperature = Unit->getArray("temperature");
 | 
				
			||||||
 | 
									if (Temperature->size() > 1) {
 | 
				
			||||||
 | 
										temperature_ = Temperature->get(0);
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							} catch (const Poco::Exception &E) {
 | 
				
			||||||
 | 
								poco_error(Logger_, "Failed to parse last stats: " + E.displayText());
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
} // namespace OpenWifi
 | 
					} // namespace OpenWifi
 | 
				
			||||||
@@ -14,8 +14,10 @@
 | 
				
			|||||||
#include "Poco/Net/SocketReactor.h"
 | 
					#include "Poco/Net/SocketReactor.h"
 | 
				
			||||||
#include "Poco/Net/StreamSocket.h"
 | 
					#include "Poco/Net/StreamSocket.h"
 | 
				
			||||||
#include "Poco/Net/WebSocket.h"
 | 
					#include "Poco/Net/WebSocket.h"
 | 
				
			||||||
 | 
					#include <Poco/Data/Session.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "RESTObjects/RESTAPI_GWobjects.h"
 | 
					#include "RESTObjects/RESTAPI_GWobjects.h"
 | 
				
			||||||
 | 
					#include <AP_WS_Reactor_Pool.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace OpenWifi {
 | 
					namespace OpenWifi {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -25,16 +27,17 @@ namespace OpenWifi {
 | 
				
			|||||||
	  public:
 | 
						  public:
 | 
				
			||||||
		explicit AP_WS_Connection(Poco::Net::HTTPServerRequest &request,
 | 
							explicit AP_WS_Connection(Poco::Net::HTTPServerRequest &request,
 | 
				
			||||||
								  Poco::Net::HTTPServerResponse &response, uint64_t connection_id,
 | 
													  Poco::Net::HTTPServerResponse &response, uint64_t connection_id,
 | 
				
			||||||
								  Poco::Logger &L, Poco::Net::SocketReactor &R);
 | 
													  Poco::Logger &L, std::pair<std::shared_ptr<Poco::Net::SocketReactor>, std::shared_ptr<LockedDbSession>> R);
 | 
				
			||||||
		~AP_WS_Connection();
 | 
							~AP_WS_Connection();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		void EndConnection(bool DeleteSession=true);
 | 
							void EndConnection(bool Clean = true);
 | 
				
			||||||
		void ProcessJSONRPCEvent(Poco::JSON::Object::Ptr &Doc);
 | 
							void ProcessJSONRPCEvent(Poco::JSON::Object::Ptr &Doc);
 | 
				
			||||||
		void ProcessJSONRPCResult(Poco::JSON::Object::Ptr Doc);
 | 
							void ProcessJSONRPCResult(Poco::JSON::Object::Ptr Doc);
 | 
				
			||||||
		void ProcessIncomingFrame();
 | 
							void ProcessIncomingFrame();
 | 
				
			||||||
		void ProcessIncomingRadiusData(const Poco::JSON::Object::Ptr &Doc);
 | 
							void ProcessIncomingRadiusData(const Poco::JSON::Object::Ptr &Doc);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		[[nodiscard]] bool Send(const std::string &Payload);
 | 
							[[nodiscard]] bool Send(const std::string &Payload);
 | 
				
			||||||
 | 
							[[nodiscard]] inline bool MustBeSecureRTTY() const { return RTTYMustBeSecure_; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		bool SendRadiusAuthenticationData(const unsigned char *buffer, std::size_t size);
 | 
							bool SendRadiusAuthenticationData(const unsigned char *buffer, std::size_t size);
 | 
				
			||||||
		bool SendRadiusAccountingData(const unsigned char *buffer, std::size_t size);
 | 
							bool SendRadiusAccountingData(const unsigned char *buffer, std::size_t size);
 | 
				
			||||||
@@ -43,10 +46,7 @@ namespace OpenWifi {
 | 
				
			|||||||
		void OnSocketReadable(const Poco::AutoPtr<Poco::Net::ReadableNotification> &pNf);
 | 
							void OnSocketReadable(const Poco::AutoPtr<Poco::Net::ReadableNotification> &pNf);
 | 
				
			||||||
		void OnSocketShutdown(const Poco::AutoPtr<Poco::Net::ShutdownNotification> &pNf);
 | 
							void OnSocketShutdown(const Poco::AutoPtr<Poco::Net::ShutdownNotification> &pNf);
 | 
				
			||||||
		void OnSocketError(const Poco::AutoPtr<Poco::Net::ErrorNotification> &pNf);
 | 
							void OnSocketError(const Poco::AutoPtr<Poco::Net::ErrorNotification> &pNf);
 | 
				
			||||||
		bool LookForUpgrade(uint64_t UUID, uint64_t &UpgradedUUID);
 | 
							bool LookForUpgrade(Poco::Data::Session &Session, uint64_t UUID, uint64_t &UpgradedUUID);
 | 
				
			||||||
		static bool ExtractBase64CompressedData(const std::string &CompressedData,
 | 
					 | 
				
			||||||
												std::string &UnCompressedData,
 | 
					 | 
				
			||||||
												uint64_t compress_sz);
 | 
					 | 
				
			||||||
		void LogException(const Poco::Exception &E);
 | 
							void LogException(const Poco::Exception &E);
 | 
				
			||||||
		inline Poco::Logger &Logger() { return Logger_; }
 | 
							inline Poco::Logger &Logger() { return Logger_; }
 | 
				
			||||||
		bool SetWebSocketTelemetryReporting(uint64_t RPCID, uint64_t interval,
 | 
							bool SetWebSocketTelemetryReporting(uint64_t RPCID, uint64_t interval,
 | 
				
			||||||
@@ -59,82 +59,34 @@ namespace OpenWifi {
 | 
				
			|||||||
		bool StopKafkaTelemetry(uint64_t RPCID);
 | 
							bool StopKafkaTelemetry(uint64_t RPCID);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		inline void GetLastStats(std::string &LastStats) {
 | 
							inline void GetLastStats(std::string &LastStats) {
 | 
				
			||||||
			std::lock_guard G(ConnectionMutex_);
 | 
								if(!Dead_) {
 | 
				
			||||||
			LastStats = RawLastStats_;
 | 
									std::lock_guard G(ConnectionMutex_);
 | 
				
			||||||
		}
 | 
									LastStats = RawLastStats_;
 | 
				
			||||||
 | 
					 | 
				
			||||||
		inline void SetLastStats(const std::string &LastStats) {
 | 
					 | 
				
			||||||
			std::lock_guard G(ConnectionMutex_);
 | 
					 | 
				
			||||||
			RawLastStats_ = LastStats;
 | 
					 | 
				
			||||||
			try {
 | 
					 | 
				
			||||||
				Poco::JSON::Parser P;
 | 
					 | 
				
			||||||
				auto Stats = P.parse(LastStats).extract<Poco::JSON::Object::Ptr>();
 | 
					 | 
				
			||||||
				hasGPS = Stats->isObject("gps");
 | 
					 | 
				
			||||||
				auto Unit = Stats->getObject("unit");
 | 
					 | 
				
			||||||
				auto Memory = Unit->getObject("memory");
 | 
					 | 
				
			||||||
				std::uint64_t TotalMemory = Memory->get("total");
 | 
					 | 
				
			||||||
				std::uint64_t FreeMemory = Memory->get("free");
 | 
					 | 
				
			||||||
				if(TotalMemory>0) {
 | 
					 | 
				
			||||||
					memory_used_ =
 | 
					 | 
				
			||||||
						(100.0 * ((double)TotalMemory - (double)FreeMemory)) / (double)TotalMemory;
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
				if(Unit->isArray("load")) {
 | 
					 | 
				
			||||||
					Poco::JSON::Array::Ptr Load = Unit->getArray("load");
 | 
					 | 
				
			||||||
					if(Load->size()>1) {
 | 
					 | 
				
			||||||
						cpu_load_ = Load->get(1);
 | 
					 | 
				
			||||||
					}
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
				if(Unit->isArray("temperature")) {
 | 
					 | 
				
			||||||
					Poco::JSON::Array::Ptr Temperature = Unit->getArray("temperature");
 | 
					 | 
				
			||||||
					if(Temperature->size()>1) {
 | 
					 | 
				
			||||||
						temperature_ = Temperature->get(0);
 | 
					 | 
				
			||||||
					}
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
			} catch (...) {
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		inline void SetLastHealthCheck(const GWObjects::HealthCheck &H) {
 | 
					 | 
				
			||||||
			std::lock_guard G(ConnectionMutex_);
 | 
					 | 
				
			||||||
			RawLastHealthcheck_ = H;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		inline void GetLastHealthCheck(GWObjects::HealthCheck &H) {
 | 
							inline void GetLastHealthCheck(GWObjects::HealthCheck &H) {
 | 
				
			||||||
			std::lock_guard G(ConnectionMutex_);
 | 
								if(!Dead_) {
 | 
				
			||||||
			H = RawLastHealthcheck_;
 | 
									std::lock_guard G(ConnectionMutex_);
 | 
				
			||||||
 | 
									H = RawLastHealthcheck_;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		inline void GetState(GWObjects::ConnectionState &State) const {
 | 
							inline void GetState(GWObjects::ConnectionState &State) {
 | 
				
			||||||
			std::lock_guard G(ConnectionMutex_);
 | 
								if(!Dead_) {
 | 
				
			||||||
			State = State_;
 | 
									std::lock_guard G(ConnectionMutex_);
 | 
				
			||||||
 | 
									State = State_;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		inline bool HasGPS() { return hasGPS; }
 | 
							[[nodiscard]] inline bool HasGPS() const { return hasGPS_; }
 | 
				
			||||||
 | 
							[[nodiscard]] bool ValidatedDevice();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		inline void GetRestrictions(GWObjects::DeviceRestrictions &R) const {
 | 
							inline void GetRestrictions(GWObjects::DeviceRestrictions &R) {
 | 
				
			||||||
			std::lock_guard G(ConnectionMutex_);
 | 
								std::lock_guard G(ConnectionMutex_);
 | 
				
			||||||
			R = Restrictions_;
 | 
								R = Restrictions_;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		void Process_connect(Poco::JSON::Object::Ptr ParamsObj, const std::string &Serial);
 | 
					 | 
				
			||||||
		void Process_state(Poco::JSON::Object::Ptr ParamsObj);
 | 
					 | 
				
			||||||
		void Process_healthcheck(Poco::JSON::Object::Ptr ParamsObj);
 | 
					 | 
				
			||||||
		void Process_log(Poco::JSON::Object::Ptr ParamsObj);
 | 
					 | 
				
			||||||
		void Process_crashlog(Poco::JSON::Object::Ptr ParamsObj);
 | 
					 | 
				
			||||||
		void Process_ping(Poco::JSON::Object::Ptr ParamsObj);
 | 
					 | 
				
			||||||
		void Process_cfgpending(Poco::JSON::Object::Ptr ParamsObj);
 | 
					 | 
				
			||||||
		void Process_recovery(Poco::JSON::Object::Ptr ParamsObj);
 | 
					 | 
				
			||||||
		void Process_deviceupdate(Poco::JSON::Object::Ptr ParamsObj, std::string &Serial);
 | 
					 | 
				
			||||||
		void Process_telemetry(Poco::JSON::Object::Ptr ParamsObj);
 | 
					 | 
				
			||||||
		void Process_venuebroadcast(Poco::JSON::Object::Ptr ParamsObj);
 | 
					 | 
				
			||||||
		void Process_event(Poco::JSON::Object::Ptr ParamsObj);
 | 
					 | 
				
			||||||
		void Process_wifiscan(Poco::JSON::Object::Ptr ParamsObj);
 | 
					 | 
				
			||||||
		void Process_alarm(Poco::JSON::Object::Ptr ParamsObj);
 | 
					 | 
				
			||||||
		void Process_rebootLog(Poco::JSON::Object::Ptr ParamsObj);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		bool ValidatedDevice();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		inline bool GetTelemetryParameters(bool &Reporting, uint64_t &Interval,
 | 
							inline bool GetTelemetryParameters(bool &Reporting, uint64_t &Interval,
 | 
				
			||||||
										   uint64_t &WebSocketTimer, uint64_t &KafkaTimer,
 | 
															   uint64_t &WebSocketTimer, uint64_t &KafkaTimer,
 | 
				
			||||||
										   uint64_t &WebSocketCount, uint64_t &KafkaCount,
 | 
															   uint64_t &WebSocketCount, uint64_t &KafkaCount,
 | 
				
			||||||
@@ -153,18 +105,18 @@ namespace OpenWifi {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
		friend class AP_WS_Server;
 | 
							friend class AP_WS_Server;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		inline GWObjects::DeviceRestrictions Restrictions() const {
 | 
							inline GWObjects::DeviceRestrictions Restrictions() {
 | 
				
			||||||
			std::lock_guard G(ConnectionMutex_);
 | 
								std::lock_guard G(ConnectionMutex_);
 | 
				
			||||||
			return Restrictions_;
 | 
								return Restrictions_;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
							void Start();
 | 
				
			||||||
		inline bool MustBeSecureRtty() const { return RttyMustBeSecure_; }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	  private:
 | 
						  private:
 | 
				
			||||||
		mutable std::mutex ConnectionMutex_;
 | 
							std::recursive_mutex ConnectionMutex_;
 | 
				
			||||||
		std::mutex TelemetryMutex_;
 | 
							std::mutex TelemetryMutex_;
 | 
				
			||||||
		Poco::Logger &Logger_;
 | 
							Poco::Logger &Logger_;
 | 
				
			||||||
		Poco::Net::SocketReactor &Reactor_;
 | 
							std::shared_ptr<Poco::Net::SocketReactor> 	Reactor_;
 | 
				
			||||||
 | 
							std::shared_ptr<LockedDbSession> 	DbSession_;
 | 
				
			||||||
		std::unique_ptr<Poco::Net::WebSocket> WS_;
 | 
							std::unique_ptr<Poco::Net::WebSocket> WS_;
 | 
				
			||||||
		std::string SerialNumber_;
 | 
							std::string SerialNumber_;
 | 
				
			||||||
		uint64_t SerialNumberInt_ = 0;
 | 
							uint64_t SerialNumberInt_ = 0;
 | 
				
			||||||
@@ -175,34 +127,56 @@ namespace OpenWifi {
 | 
				
			|||||||
		uint64_t Errors_ = 0;
 | 
							uint64_t Errors_ = 0;
 | 
				
			||||||
		Poco::Net::IPAddress PeerAddress_;
 | 
							Poco::Net::IPAddress PeerAddress_;
 | 
				
			||||||
		volatile bool TelemetryReporting_ = false;
 | 
							volatile bool TelemetryReporting_ = false;
 | 
				
			||||||
		volatile uint64_t TelemetryWebSocketRefCount_ = 0;
 | 
							std::atomic_uint64_t TelemetryWebSocketRefCount_ = 0;
 | 
				
			||||||
		volatile uint64_t TelemetryKafkaRefCount_ = 0;
 | 
							std::atomic_uint64_t TelemetryKafkaRefCount_ = 0;
 | 
				
			||||||
		volatile uint64_t TelemetryWebSocketTimer_ = 0;
 | 
							std::atomic_uint64_t TelemetryWebSocketTimer_ = 0;
 | 
				
			||||||
		volatile uint64_t TelemetryKafkaTimer_ = 0;
 | 
							std::atomic_uint64_t TelemetryKafkaTimer_ = 0;
 | 
				
			||||||
		volatile uint64_t TelemetryInterval_ = 0;
 | 
							std::atomic_uint64_t TelemetryInterval_ = 0;
 | 
				
			||||||
		volatile uint64_t TelemetryWebSocketPackets_ = 0;
 | 
							std::atomic_uint64_t TelemetryWebSocketPackets_ = 0;
 | 
				
			||||||
		volatile uint64_t TelemetryKafkaPackets_ = 0;
 | 
							std::atomic_uint64_t TelemetryKafkaPackets_ = 0;
 | 
				
			||||||
		GWObjects::ConnectionState State_;
 | 
							GWObjects::ConnectionState State_;
 | 
				
			||||||
		std::string RawLastStats_;
 | 
							Utils::CompressedString RawLastStats_;
 | 
				
			||||||
		GWObjects::HealthCheck RawLastHealthcheck_;
 | 
							GWObjects::HealthCheck RawLastHealthcheck_;
 | 
				
			||||||
		std::chrono::time_point<std::chrono::high_resolution_clock> ConnectionStart_ =
 | 
							std::chrono::time_point<std::chrono::high_resolution_clock> ConnectionStart_ =
 | 
				
			||||||
			std::chrono::high_resolution_clock::now();
 | 
								std::chrono::high_resolution_clock::now();
 | 
				
			||||||
		std::chrono::duration<double, std::milli> ConnectionCompletionTime_{0.0};
 | 
							std::chrono::duration<double, std::milli> ConnectionCompletionTime_{0.0};
 | 
				
			||||||
		std::atomic_flag Dead_ = false;
 | 
							std::atomic<bool> 	Dead_ = false;
 | 
				
			||||||
		std::atomic_bool DeviceValidated_ = false;
 | 
							std::atomic_bool DeviceValidated_ = false;
 | 
				
			||||||
		std::atomic_bool Valid_ = false;
 | 
					 | 
				
			||||||
		OpenWifi::GWObjects::DeviceRestrictions Restrictions_;
 | 
							OpenWifi::GWObjects::DeviceRestrictions Restrictions_;
 | 
				
			||||||
		bool 			RttyMustBeSecure_ = false;
 | 
							bool 			RTTYMustBeSecure_ = false;
 | 
				
			||||||
 | 
							bool hasGPS_=false;
 | 
				
			||||||
 | 
							std::double_t 	memory_used_=0.0, cpu_load_ = 0.0, temperature_ = 0.0;
 | 
				
			||||||
 | 
							std::uint64_t 	uuid_=0;
 | 
				
			||||||
 | 
							bool	Simulated_=false;
 | 
				
			||||||
 | 
							std::uint64_t 	LastContact_=0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		static inline std::atomic_uint64_t ConcurrentStartingDevices_ = 0;
 | 
							static inline std::atomic_uint64_t ConcurrentStartingDevices_ = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		bool StartTelemetry(uint64_t RPCID, const std::vector<std::string> &TelemetryTypes);
 | 
							bool StartTelemetry(uint64_t RPCID, const std::vector<std::string> &TelemetryTypes);
 | 
				
			||||||
		bool StopTelemetry(uint64_t RPCID);
 | 
							bool StopTelemetry(uint64_t RPCID);
 | 
				
			||||||
		void UpdateCounts();
 | 
							void UpdateCounts();
 | 
				
			||||||
		bool hasGPS=false;
 | 
							static void DeviceDisconnectionCleanup(const std::string &SerialNumber, std::uint64_t uuid);
 | 
				
			||||||
		std::double_t 	memory_used_=0.0, cpu_load_ = 0.0, temperature_ = 0.0;
 | 
							void SetLastStats(const std::string &LastStats);
 | 
				
			||||||
		std::uint64_t 	uuid_=0;
 | 
							void Process_connect(Poco::JSON::Object::Ptr ParamsObj, const std::string &Serial);
 | 
				
			||||||
		bool	Simulated_=false;
 | 
							void Process_state(Poco::JSON::Object::Ptr ParamsObj);
 | 
				
			||||||
 | 
							void Process_healthcheck(Poco::JSON::Object::Ptr ParamsObj);
 | 
				
			||||||
 | 
							void Process_log(Poco::JSON::Object::Ptr ParamsObj);
 | 
				
			||||||
 | 
							void Process_crashlog(Poco::JSON::Object::Ptr ParamsObj);
 | 
				
			||||||
 | 
							void Process_ping(Poco::JSON::Object::Ptr ParamsObj);
 | 
				
			||||||
 | 
							void Process_cfgpending(Poco::JSON::Object::Ptr ParamsObj);
 | 
				
			||||||
 | 
							void Process_recovery(Poco::JSON::Object::Ptr ParamsObj);
 | 
				
			||||||
 | 
							void Process_deviceupdate(Poco::JSON::Object::Ptr ParamsObj, std::string &Serial);
 | 
				
			||||||
 | 
							void Process_telemetry(Poco::JSON::Object::Ptr ParamsObj);
 | 
				
			||||||
 | 
							void Process_venuebroadcast(Poco::JSON::Object::Ptr ParamsObj);
 | 
				
			||||||
 | 
							void Process_event(Poco::JSON::Object::Ptr ParamsObj);
 | 
				
			||||||
 | 
							void Process_wifiscan(Poco::JSON::Object::Ptr ParamsObj);
 | 
				
			||||||
 | 
							void Process_alarm(Poco::JSON::Object::Ptr ParamsObj);
 | 
				
			||||||
 | 
							void Process_rebootLog(Poco::JSON::Object::Ptr ParamsObj);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							inline void SetLastHealthCheck(const GWObjects::HealthCheck &H) {
 | 
				
			||||||
 | 
								RawLastHealthcheck_ = H;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
} // namespace OpenWifi
 | 
					} // namespace OpenWifi
 | 
				
			||||||
							
								
								
									
										88
									
								
								src/AP_WS_LookForUpgrade.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										88
									
								
								src/AP_WS_LookForUpgrade.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,88 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					#include <AP_WS_Connection.h>
 | 
				
			||||||
 | 
					#include "ConfigurationCache.h"
 | 
				
			||||||
 | 
					#include "UI_GW_WebSocketNotifications.h"
 | 
				
			||||||
 | 
					#include "CommandManager.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace OpenWifi {
 | 
				
			||||||
 | 
						bool AP_WS_Connection::LookForUpgrade(Poco::Data::Session &Session, const uint64_t UUID, uint64_t &UpgradedUUID) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							//	A UUID of zero means ignore updates for that connection.
 | 
				
			||||||
 | 
							if (UUID == 0)
 | 
				
			||||||
 | 
								return false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							uint64_t GoodConfig = ConfigurationCache().CurrentConfig(SerialNumberInt_);
 | 
				
			||||||
 | 
							if (GoodConfig && (GoodConfig == UUID || GoodConfig == State_.PendingUUID)) {
 | 
				
			||||||
 | 
								UpgradedUUID = UUID;
 | 
				
			||||||
 | 
								return false;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							GWObjects::Device D;
 | 
				
			||||||
 | 
							if (StorageService()->GetDevice(Session,SerialNumber_, D)) {
 | 
				
			||||||
 | 
								if(D.pendingUUID!=0 && UUID==D.pendingUUID) {
 | 
				
			||||||
 | 
									//	so we sent an upgrade to a device, and now it is completing now...
 | 
				
			||||||
 | 
									UpgradedUUID = D.pendingUUID;
 | 
				
			||||||
 | 
									StorageService()->CompleteDeviceConfigurationChange(Session, SerialNumber_);
 | 
				
			||||||
 | 
									return true;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								//	This is the case where the cache is empty after a restart. So GoodConfig will 0. If
 | 
				
			||||||
 | 
								// the device already 	has the right UUID, we just return.
 | 
				
			||||||
 | 
								if (D.UUID == UUID) {
 | 
				
			||||||
 | 
									UpgradedUUID = UUID;
 | 
				
			||||||
 | 
									ConfigurationCache().Add(SerialNumberInt_, UUID);
 | 
				
			||||||
 | 
									return false;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								Config::Config Cfg(D.Configuration);
 | 
				
			||||||
 | 
								if (UUID > D.UUID) {
 | 
				
			||||||
 | 
									//	so we have a problem, the device has a newer config than we have. So we need to
 | 
				
			||||||
 | 
									// make sure our config 	is newer.
 | 
				
			||||||
 | 
									D.UUID = UUID + 2;
 | 
				
			||||||
 | 
									UpgradedUUID = D.UUID;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								Cfg.SetUUID(D.UUID);
 | 
				
			||||||
 | 
								D.Configuration = Cfg.get();
 | 
				
			||||||
 | 
								State_.PendingUUID = UpgradedUUID = D.UUID;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								GWObjects::CommandDetails Cmd;
 | 
				
			||||||
 | 
								Cmd.SerialNumber = SerialNumber_;
 | 
				
			||||||
 | 
								Cmd.UUID = MicroServiceCreateUUID();
 | 
				
			||||||
 | 
								Cmd.SubmittedBy = uCentralProtocol::SUBMITTED_BY_SYSTEM;
 | 
				
			||||||
 | 
								Cmd.Status = uCentralProtocol::PENDING;
 | 
				
			||||||
 | 
								Cmd.Command = uCentralProtocol::CONFIGURE;
 | 
				
			||||||
 | 
								Poco::JSON::Parser P;
 | 
				
			||||||
 | 
								auto ParsedConfig = P.parse(D.Configuration).extract<Poco::JSON::Object::Ptr>();
 | 
				
			||||||
 | 
								Poco::JSON::Object Params;
 | 
				
			||||||
 | 
								Params.set(uCentralProtocol::SERIAL, SerialNumber_);
 | 
				
			||||||
 | 
								Params.set(uCentralProtocol::UUID, D.UUID);
 | 
				
			||||||
 | 
								Params.set(uCentralProtocol::WHEN, 0);
 | 
				
			||||||
 | 
								Params.set(uCentralProtocol::CONFIG, ParsedConfig);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								std::ostringstream O;
 | 
				
			||||||
 | 
								Poco::JSON::Stringifier::stringify(Params, O);
 | 
				
			||||||
 | 
								Cmd.Details = O.str();
 | 
				
			||||||
 | 
								poco_information(Logger_,
 | 
				
			||||||
 | 
												 fmt::format("CFG-UPGRADE({}): Current ID: {}, newer configuration {}.",
 | 
				
			||||||
 | 
															 CId_, UUID, D.UUID));
 | 
				
			||||||
 | 
								bool Sent;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								StorageService()->AddCommand(SerialNumber_, Cmd,
 | 
				
			||||||
 | 
															 Storage::CommandExecutionType::COMMAND_EXECUTED);
 | 
				
			||||||
 | 
								CommandManager()->PostCommand(
 | 
				
			||||||
 | 
									CommandManager()->Next_RPC_ID(), APCommands::to_apcommand(Cmd.Command.c_str()),
 | 
				
			||||||
 | 
									SerialNumber_, Cmd.Command, Params, Cmd.UUID, Sent, false, false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								GWWebSocketNotifications::SingleDeviceConfigurationChange_t Notification;
 | 
				
			||||||
 | 
								Notification.content.serialNumber = D.SerialNumber;
 | 
				
			||||||
 | 
								Notification.content.oldUUID = UUID;
 | 
				
			||||||
 | 
								Notification.content.newUUID = UpgradedUUID;
 | 
				
			||||||
 | 
								GWWebSocketNotifications::DeviceConfigurationChange(Notification);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								return true;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return false;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -71,9 +71,8 @@ namespace OpenWifi {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
			CommandManager()->ClearQueue(SerialNumberInt_);
 | 
								CommandManager()->ClearQueue(SerialNumberInt_);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			AP_WS_Server()->SetSessionDetails(State_.sessionId, SerialNumberInt_);
 | 
								AP_WS_Server()->StartSession(State_.sessionId, SerialNumberInt_);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			std::lock_guard Lock(ConnectionMutex_);
 | 
					 | 
				
			||||||
			Config::Capabilities Caps(Capabilities);
 | 
								Config::Capabilities Caps(Capabilities);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			Compatible_ = Caps.Compatible();
 | 
								Compatible_ = Caps.Compatible();
 | 
				
			||||||
@@ -100,36 +99,24 @@ namespace OpenWifi {
 | 
				
			|||||||
				Restrictions_.from_json(RestrictionObject);
 | 
									Restrictions_.from_json(RestrictionObject);
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if (Capabilities->has("developer")) {
 | 
								if (Capabilities->has("developer") && !Capabilities->isNull("developer")) {
 | 
				
			||||||
				Restrictions_.developer = Capabilities->getValue<bool>("developer");
 | 
									Restrictions_.developer = Capabilities->getValue<bool>("developer");
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if(Capabilities->has("secure-rtty")) {
 | 
								if(Capabilities->has("secure-rtty")) {
 | 
				
			||||||
				RttyMustBeSecure_ = Capabilities->getValue<bool>("secure-rtty");
 | 
									RTTYMustBeSecure_ = Capabilities->getValue<bool>("secure-rtty");
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			State_.locale = FindCountryFromIP()->Get(IP);
 | 
								State_.locale = FindCountryFromIP()->Get(IP);
 | 
				
			||||||
			GWObjects::Device DeviceInfo;
 | 
								GWObjects::Device DeviceInfo;
 | 
				
			||||||
			auto DeviceExists = StorageService()->GetDevice(SerialNumber_, DeviceInfo);
 | 
								std::lock_guard DbSessionLock(DbSession_->Mutex());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								auto DeviceExists = StorageService()->GetDevice(DbSession_->Session(), SerialNumber_, DeviceInfo);
 | 
				
			||||||
			if (Daemon()->AutoProvisioning() && !DeviceExists) {
 | 
								if (Daemon()->AutoProvisioning() && !DeviceExists) {
 | 
				
			||||||
				//	check the firmware version. if this is too old, we cannot let that device connect yet, we must
 | 
									//	check the firmware version. if this is too old, we cannot let that device connect yet, we must
 | 
				
			||||||
				//	force a firmware upgrade
 | 
									//	force a firmware upgrade
 | 
				
			||||||
				GWObjects::DefaultFirmware	MinimumFirmware;
 | 
									GWObjects::DefaultFirmware	MinimumFirmware;
 | 
				
			||||||
				if(FirmwareRevisionCache()->DeviceMustUpgrade(Compatible_, Firmware, MinimumFirmware)) {
 | 
									if(FirmwareRevisionCache()->DeviceMustUpgrade(Compatible_, Firmware, MinimumFirmware)) {
 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
					{    "jsonrpc" : "2.0" ,
 | 
					 | 
				
			||||||
						 "method" : "upgrade" ,
 | 
					 | 
				
			||||||
						 "params" : {
 | 
					 | 
				
			||||||
								"serial" : <serial number> ,
 | 
					 | 
				
			||||||
								"when"  : Optional - <UTC time when to upgrade the firmware, 0 mean immediate, this is a suggestion>,
 | 
					 | 
				
			||||||
								"uri"   : <URI to download the firmware>,
 | 
					 | 
				
			||||||
								"FWsignature" : <string representation of the signature for the FW> (optional)
 | 
					 | 
				
			||||||
						 },
 | 
					 | 
				
			||||||
						 "id" : <some number>
 | 
					 | 
				
			||||||
					}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
					Poco::JSON::Object	UpgradeCommand, Params;
 | 
										Poco::JSON::Object	UpgradeCommand, Params;
 | 
				
			||||||
					UpgradeCommand.set(uCentralProtocol::JSONRPC,uCentralProtocol::JSONRPC_VERSION);
 | 
										UpgradeCommand.set(uCentralProtocol::JSONRPC,uCentralProtocol::JSONRPC_VERSION);
 | 
				
			||||||
					UpgradeCommand.set(uCentralProtocol::METHOD,uCentralProtocol::UPGRADE);
 | 
										UpgradeCommand.set(uCentralProtocol::METHOD,uCentralProtocol::UPGRADE);
 | 
				
			||||||
@@ -157,7 +144,7 @@ namespace OpenWifi {
 | 
				
			|||||||
					}
 | 
										}
 | 
				
			||||||
					return;
 | 
										return;
 | 
				
			||||||
				} else {
 | 
									} else {
 | 
				
			||||||
					StorageService()->CreateDefaultDevice(
 | 
										StorageService()->CreateDefaultDevice( DbSession_->Session(),
 | 
				
			||||||
						SerialNumber_, Caps, Firmware, PeerAddress_,
 | 
											SerialNumber_, Caps, Firmware, PeerAddress_,
 | 
				
			||||||
						State_.VerifiedCertificate == GWObjects::SIMULATED);
 | 
											State_.VerifiedCertificate == GWObjects::SIMULATED);
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
@@ -166,7 +153,7 @@ namespace OpenWifi {
 | 
				
			|||||||
				poco_warning(Logger(),fmt::format("Device {} is a {} from {} and cannot be provisioned.",SerialNumber_,Compatible_, CId_));
 | 
									poco_warning(Logger(),fmt::format("Device {} is a {} from {} and cannot be provisioned.",SerialNumber_,Compatible_, CId_));
 | 
				
			||||||
				return EndConnection();
 | 
									return EndConnection();
 | 
				
			||||||
			} else if (DeviceExists) {
 | 
								} else if (DeviceExists) {
 | 
				
			||||||
				StorageService()->UpdateDeviceCapabilities(SerialNumber_, Caps);
 | 
									StorageService()->UpdateDeviceCapabilities(DbSession_->Session(), SerialNumber_, Caps);
 | 
				
			||||||
				int Updated{0};
 | 
									int Updated{0};
 | 
				
			||||||
				if (!Firmware.empty()) {
 | 
									if (!Firmware.empty()) {
 | 
				
			||||||
					if (Firmware != DeviceInfo.Firmware) {
 | 
										if (Firmware != DeviceInfo.Firmware) {
 | 
				
			||||||
@@ -238,12 +225,12 @@ namespace OpenWifi {
 | 
				
			|||||||
				}
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				if (Updated) {
 | 
									if (Updated) {
 | 
				
			||||||
					StorageService()->UpdateDevice(DeviceInfo);
 | 
										StorageService()->UpdateDevice(DbSession_->Session(), DeviceInfo);
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				if(!Simulated_) {
 | 
									if(!Simulated_) {
 | 
				
			||||||
					uint64_t UpgradedUUID = 0;
 | 
										uint64_t UpgradedUUID = 0;
 | 
				
			||||||
					LookForUpgrade(UUID, UpgradedUUID);
 | 
										LookForUpgrade(DbSession_->Session(), UUID, UpgradedUUID);
 | 
				
			||||||
					State_.UUID = UpgradedUUID;
 | 
										State_.UUID = UpgradedUUID;
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -29,7 +29,7 @@ namespace OpenWifi {
 | 
				
			|||||||
										   .Recorded = Utils::Now(),
 | 
															   .Recorded = Utils::Now(),
 | 
				
			||||||
										   .LogType = 1,
 | 
															   .LogType = 1,
 | 
				
			||||||
										   .UUID = ParamsObj->get(uCentralProtocol::UUID)};
 | 
															   .UUID = ParamsObj->get(uCentralProtocol::UUID)};
 | 
				
			||||||
			StorageService()->AddLog(DeviceLog);
 | 
								StorageService()->AddLog(*DbSession_, DeviceLog);
 | 
				
			||||||
			DeviceLogKafkaEvent	E(DeviceLog);
 | 
								DeviceLogKafkaEvent	E(DeviceLog);
 | 
				
			||||||
		} else {
 | 
							} else {
 | 
				
			||||||
			poco_warning(Logger_, fmt::format("LOG({}): Missing parameters.", CId_));
 | 
								poco_warning(Logger_, fmt::format("LOG({}): Missing parameters.", CId_));
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -21,7 +21,7 @@ namespace OpenWifi {
 | 
				
			|||||||
		if (ParamsObj->has("currentPassword")) {
 | 
							if (ParamsObj->has("currentPassword")) {
 | 
				
			||||||
			auto Password = ParamsObj->get("currentPassword").toString();
 | 
								auto Password = ParamsObj->get("currentPassword").toString();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			StorageService()->SetDevicePassword(Serial, Password);
 | 
								StorageService()->SetDevicePassword(*DbSession_,Serial, Password);
 | 
				
			||||||
			poco_trace(
 | 
								poco_trace(
 | 
				
			||||||
				Logger_,
 | 
									Logger_,
 | 
				
			||||||
				fmt::format("DEVICE-UPDATE({}): Device is updating its login password.", Serial));
 | 
									fmt::format("DEVICE-UPDATE({}): Device is updating its login password.", Serial));
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -3,6 +3,7 @@
 | 
				
			|||||||
//
 | 
					//
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "AP_WS_Connection.h"
 | 
					#include "AP_WS_Connection.h"
 | 
				
			||||||
 | 
					#include "AP_WS_Server.h"
 | 
				
			||||||
#include "StorageService.h"
 | 
					#include "StorageService.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "fmt/format.h"
 | 
					#include "fmt/format.h"
 | 
				
			||||||
@@ -48,14 +49,14 @@ namespace OpenWifi {
 | 
				
			|||||||
			Check.Data = CheckData;
 | 
								Check.Data = CheckData;
 | 
				
			||||||
			Check.Sanity = Sanity;
 | 
								Check.Sanity = Sanity;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			StorageService()->AddHealthCheckData(Check);
 | 
								StorageService()->AddHealthCheckData(*DbSession_, Check);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if (!request_uuid.empty()) {
 | 
								if (!request_uuid.empty()) {
 | 
				
			||||||
				StorageService()->SetCommandResult(request_uuid, CheckData);
 | 
									StorageService()->SetCommandResult(request_uuid, CheckData);
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			SetLastHealthCheck(Check);
 | 
								SetLastHealthCheck(Check);
 | 
				
			||||||
			if (KafkaManager()->Enabled()) {
 | 
								if (KafkaManager()->Enabled() && !AP_WS_Server()->KafkaDisableHealthChecks()) {
 | 
				
			||||||
				KafkaManager()->PostMessage(KafkaTopics::HEALTHCHECK, SerialNumber_, *ParamsObj);
 | 
									KafkaManager()->PostMessage(KafkaTopics::HEALTHCHECK, SerialNumber_, *ParamsObj);
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		} else {
 | 
							} else {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -36,7 +36,7 @@ namespace OpenWifi {
 | 
				
			|||||||
										   .Recorded = (uint64_t)time(nullptr),
 | 
															   .Recorded = (uint64_t)time(nullptr),
 | 
				
			||||||
										   .LogType = 0,
 | 
															   .LogType = 0,
 | 
				
			||||||
										   .UUID = State_.UUID};
 | 
															   .UUID = State_.UUID};
 | 
				
			||||||
			StorageService()->AddLog(DeviceLog);
 | 
								StorageService()->AddLog(*DbSession_, DeviceLog);
 | 
				
			||||||
			DeviceLogKafkaEvent	E(DeviceLog);
 | 
								DeviceLogKafkaEvent	E(DeviceLog);
 | 
				
			||||||
		} else {
 | 
							} else {
 | 
				
			||||||
			poco_warning(Logger_, fmt::format("LOG({}): Missing parameters.", CId_));
 | 
								poco_warning(Logger_, fmt::format("LOG({}): Missing parameters.", CId_));
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -35,7 +35,7 @@ namespace OpenWifi {
 | 
				
			|||||||
										   .Recorded = ParamsObj->get(uCentralProtocol::DATE),
 | 
															   .Recorded = ParamsObj->get(uCentralProtocol::DATE),
 | 
				
			||||||
										   .LogType = 2,
 | 
															   .LogType = 2,
 | 
				
			||||||
										   .UUID = ParamsObj->get(uCentralProtocol::UUID)};
 | 
															   .UUID = ParamsObj->get(uCentralProtocol::UUID)};
 | 
				
			||||||
			StorageService()->AddLog(DeviceLog);
 | 
								StorageService()->AddLog(*DbSession_, DeviceLog);
 | 
				
			||||||
			DeviceLogKafkaEvent	E(DeviceLog);
 | 
								DeviceLogKafkaEvent	E(DeviceLog);
 | 
				
			||||||
		} else {
 | 
							} else {
 | 
				
			||||||
			poco_warning(Logger_, fmt::format("REBOOT-LOG({}): Missing parameters.", CId_));
 | 
								poco_warning(Logger_, fmt::format("REBOOT-LOG({}): Missing parameters.", CId_));
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -35,7 +35,7 @@ namespace OpenWifi {
 | 
				
			|||||||
										   .LogType = 1,
 | 
															   .LogType = 1,
 | 
				
			||||||
										   .UUID = 0};
 | 
															   .UUID = 0};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			StorageService()->AddLog(DeviceLog);
 | 
								StorageService()->AddLog(*DbSession_, DeviceLog);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if (ParamsObj->get(uCentralProtocol::REBOOT).toString() == "true") {
 | 
								if (ParamsObj->get(uCentralProtocol::REBOOT).toString() == "true") {
 | 
				
			||||||
				GWObjects::CommandDetails Cmd;
 | 
									GWObjects::CommandDetails Cmd;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -3,6 +3,7 @@
 | 
				
			|||||||
//
 | 
					//
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "AP_WS_Connection.h"
 | 
					#include "AP_WS_Connection.h"
 | 
				
			||||||
 | 
					#include "AP_WS_Server.h"
 | 
				
			||||||
#include "StateUtils.h"
 | 
					#include "StateUtils.h"
 | 
				
			||||||
#include "StorageService.h"
 | 
					#include "StorageService.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -39,17 +40,19 @@ namespace OpenWifi {
 | 
				
			|||||||
												UUID, request_uuid));
 | 
																	UUID, request_uuid));
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								std::lock_guard	Guard(DbSession_->Mutex());
 | 
				
			||||||
			if(!Simulated_) {
 | 
								if(!Simulated_) {
 | 
				
			||||||
				uint64_t UpgradedUUID;
 | 
									uint64_t UpgradedUUID;
 | 
				
			||||||
				LookForUpgrade(UUID, UpgradedUUID);
 | 
									LookForUpgrade(DbSession_->Session(), UUID, UpgradedUUID);
 | 
				
			||||||
				State_.UUID = UpgradedUUID;
 | 
									State_.UUID = UpgradedUUID;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			SetLastStats(StateStr);
 | 
								SetLastStats(StateStr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			GWObjects::Statistics Stats{
 | 
								GWObjects::Statistics Stats{
 | 
				
			||||||
				.SerialNumber = SerialNumber_, .UUID = UUID, .Data = StateStr};
 | 
									.SerialNumber = SerialNumber_, .UUID = UUID, .Data = StateStr};
 | 
				
			||||||
			Stats.Recorded = Utils::Now();
 | 
								Stats.Recorded = Utils::Now();
 | 
				
			||||||
			StorageService()->AddStatisticsData(Stats);
 | 
								StorageService()->AddStatisticsData(DbSession_->Session(),Stats);
 | 
				
			||||||
			if (!request_uuid.empty()) {
 | 
								if (!request_uuid.empty()) {
 | 
				
			||||||
				StorageService()->SetCommandResult(request_uuid, StateStr);
 | 
									StorageService()->SetCommandResult(request_uuid, StateStr);
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
@@ -57,7 +60,7 @@ namespace OpenWifi {
 | 
				
			|||||||
			StateUtils::ComputeAssociations(StateObj, State_.Associations_2G,
 | 
								StateUtils::ComputeAssociations(StateObj, State_.Associations_2G,
 | 
				
			||||||
											State_.Associations_5G, State_.Associations_6G);
 | 
																State_.Associations_5G, State_.Associations_6G);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if (KafkaManager()->Enabled()) {
 | 
								if (KafkaManager()->Enabled() && !AP_WS_Server()->KafkaDisableState()) {
 | 
				
			||||||
				KafkaManager()->PostMessage(KafkaTopics::STATE, SerialNumber_, *ParamsObj);
 | 
									KafkaManager()->PostMessage(KafkaTopics::STATE, SerialNumber_, *ParamsObj);
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -35,8 +35,7 @@ namespace OpenWifi {
 | 
				
			|||||||
				}
 | 
									}
 | 
				
			||||||
				if (TelemetryWebSocketRefCount_) {
 | 
									if (TelemetryWebSocketRefCount_) {
 | 
				
			||||||
					if (now < TelemetryWebSocketTimer_) {
 | 
										if (now < TelemetryWebSocketTimer_) {
 | 
				
			||||||
						// std::cout << SerialNumber_ << ": Updating WebSocket telemetry" <<
 | 
					
 | 
				
			||||||
						// std::endl;
 | 
					 | 
				
			||||||
						TelemetryWebSocketPackets_++;
 | 
											TelemetryWebSocketPackets_++;
 | 
				
			||||||
						State_.websocketPackets = TelemetryWebSocketPackets_;
 | 
											State_.websocketPackets = TelemetryWebSocketPackets_;
 | 
				
			||||||
						TelemetryStream()->NotifyEndPoint(SerialNumberInt_, KafkaPayload);
 | 
											TelemetryStream()->NotifyEndPoint(SerialNumberInt_, KafkaPayload);
 | 
				
			||||||
@@ -46,7 +45,6 @@ namespace OpenWifi {
 | 
				
			|||||||
				}
 | 
									}
 | 
				
			||||||
				if (TelemetryKafkaRefCount_) {
 | 
									if (TelemetryKafkaRefCount_) {
 | 
				
			||||||
					if (KafkaManager()->Enabled() && now < TelemetryKafkaTimer_) {
 | 
										if (KafkaManager()->Enabled() && now < TelemetryKafkaTimer_) {
 | 
				
			||||||
						// std::cout << SerialNumber_ << ": Updating Kafka telemetry" << std::endl;
 | 
					 | 
				
			||||||
						TelemetryKafkaPackets_++;
 | 
											TelemetryKafkaPackets_++;
 | 
				
			||||||
						State_.kafkaPackets = TelemetryKafkaPackets_;
 | 
											State_.kafkaPackets = TelemetryKafkaPackets_;
 | 
				
			||||||
						KafkaManager()->PostMessage(KafkaTopics::DEVICE_TELEMETRY, SerialNumber_,
 | 
											KafkaManager()->PostMessage(KafkaTopics::DEVICE_TELEMETRY, SerialNumber_,
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -9,30 +9,39 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#include "Poco/Environment.h"
 | 
					#include "Poco/Environment.h"
 | 
				
			||||||
#include "Poco/Net/SocketAcceptor.h"
 | 
					#include "Poco/Net/SocketAcceptor.h"
 | 
				
			||||||
 | 
					#include <Poco/Data/SessionPool.h>
 | 
				
			||||||
#include "framework/utils.h"
 | 
					#include "framework/utils.h"
 | 
				
			||||||
 | 
					#include <StorageService.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace OpenWifi {
 | 
					namespace OpenWifi {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	class AP_WS_ReactorThreadPool {
 | 
						class AP_WS_ReactorThreadPool {
 | 
				
			||||||
	  public:
 | 
						  public:
 | 
				
			||||||
		explicit AP_WS_ReactorThreadPool() {
 | 
							explicit AP_WS_ReactorThreadPool(Poco::Logger &Logger) : Logger_(Logger) {
 | 
				
			||||||
			NumberOfThreads_ = Poco::Environment::processorCount() * 4;
 | 
								NumberOfThreads_ = Poco::Environment::processorCount() * 4;
 | 
				
			||||||
			if (NumberOfThreads_ == 0)
 | 
								if (NumberOfThreads_ == 0)
 | 
				
			||||||
				NumberOfThreads_ = 4;
 | 
									NumberOfThreads_ = 8;
 | 
				
			||||||
 | 
								NumberOfThreads_ = std::min(NumberOfThreads_, (std::uint64_t) 128);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		~AP_WS_ReactorThreadPool() { Stop(); }
 | 
							~AP_WS_ReactorThreadPool() { Stop(); }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		void Start() {
 | 
							void Start() {
 | 
				
			||||||
 | 
								Reactors_.reserve(NumberOfThreads_);
 | 
				
			||||||
 | 
								DbSessions_.reserve(NumberOfThreads_);
 | 
				
			||||||
 | 
								Threads_.reserve(NumberOfThreads_);
 | 
				
			||||||
 | 
								Logger_.information(fmt::format("WebSocket Processor: starting {} threads.", NumberOfThreads_));
 | 
				
			||||||
			for (uint64_t i = 0; i < NumberOfThreads_; ++i) {
 | 
								for (uint64_t i = 0; i < NumberOfThreads_; ++i) {
 | 
				
			||||||
				auto NewReactor = std::make_unique<Poco::Net::SocketReactor>();
 | 
									auto NewReactor = std::make_shared<Poco::Net::SocketReactor>();
 | 
				
			||||||
				auto NewThread = std::make_unique<Poco::Thread>();
 | 
									auto NewThread = std::make_unique<Poco::Thread>();
 | 
				
			||||||
				NewThread->start(*NewReactor);
 | 
									NewThread->start(*NewReactor);
 | 
				
			||||||
				std::string ThreadName{"ap:react:" + std::to_string(i)};
 | 
									std::string ThreadName{"ap:react:" + std::to_string(i)};
 | 
				
			||||||
				Utils::SetThreadName(*NewThread, ThreadName.c_str());
 | 
									Utils::SetThreadName(*NewThread, ThreadName.c_str());
 | 
				
			||||||
				Reactors_.emplace_back(std::move(NewReactor));
 | 
									Reactors_.emplace_back(std::move(NewReactor));
 | 
				
			||||||
				Threads_.emplace_back(std::move(NewThread));
 | 
									Threads_.emplace_back(std::move(NewThread));
 | 
				
			||||||
 | 
									DbSessions_.emplace_back(std::make_shared<LockedDbSession>());
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
								Logger_.information(fmt::format("WebSocket Processor: {} threads started.", NumberOfThreads_));
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		void Stop() {
 | 
							void Stop() {
 | 
				
			||||||
@@ -43,20 +52,24 @@ namespace OpenWifi {
 | 
				
			|||||||
			}
 | 
								}
 | 
				
			||||||
			Reactors_.clear();
 | 
								Reactors_.clear();
 | 
				
			||||||
			Threads_.clear();
 | 
								Threads_.clear();
 | 
				
			||||||
 | 
								DbSessions_.clear();
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		Poco::Net::SocketReactor &NextReactor() {
 | 
							std::pair<std::shared_ptr<Poco::Net::SocketReactor>, std::shared_ptr<LockedDbSession> > NextReactor() {
 | 
				
			||||||
			std::lock_guard Lock(Mutex_);
 | 
								std::lock_guard Lock(Mutex_);
 | 
				
			||||||
			NextReactor_++;
 | 
								NextReactor_++;
 | 
				
			||||||
			NextReactor_ %= NumberOfThreads_;
 | 
								NextReactor_ %= NumberOfThreads_;
 | 
				
			||||||
			return *Reactors_[NextReactor_];
 | 
								return std::make_pair(Reactors_[NextReactor_], DbSessions_[NextReactor_]);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	  private:
 | 
						  private:
 | 
				
			||||||
		std::mutex Mutex_;
 | 
							std::mutex Mutex_;
 | 
				
			||||||
		uint64_t NumberOfThreads_;
 | 
							uint64_t NumberOfThreads_;
 | 
				
			||||||
		uint64_t NextReactor_ = 0;
 | 
							uint64_t NextReactor_ = 0;
 | 
				
			||||||
		std::vector<std::unique_ptr<Poco::Net::SocketReactor>> Reactors_;
 | 
							std::vector<std::shared_ptr<Poco::Net::SocketReactor>> 	Reactors_;
 | 
				
			||||||
		std::vector<std::unique_ptr<Poco::Thread>> Threads_;
 | 
							std::vector<std::unique_ptr<Poco::Thread>> 				Threads_;
 | 
				
			||||||
 | 
							std::vector<std::shared_ptr<LockedDbSession>>			DbSessions_;
 | 
				
			||||||
 | 
							Poco::Logger &Logger_;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
} // namespace OpenWifi
 | 
					} // namespace OpenWifi
 | 
				
			||||||
@@ -23,15 +23,47 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
namespace OpenWifi {
 | 
					namespace OpenWifi {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	void AP_WS_RequestHandler::handleRequest(Poco::Net::HTTPServerRequest &request,
 | 
						class AP_WS_RequestHandler : public Poco::Net::HTTPRequestHandler {
 | 
				
			||||||
											 Poco::Net::HTTPServerResponse &response) {
 | 
						  public:
 | 
				
			||||||
		try {
 | 
							explicit AP_WS_RequestHandler(Poco::Logger &L, std::uint64_t session_id) : Logger_(L),
 | 
				
			||||||
			AP_WS_Server()->AddConnection(
 | 
													   		session_id_(session_id) {
 | 
				
			||||||
				id_, std::make_shared<AP_WS_Connection>(request, response, id_, Logger_,
 | 
							 };
 | 
				
			||||||
														AP_WS_Server()->NextReactor()));
 | 
					
 | 
				
			||||||
		} catch (...) {
 | 
							void handleRequest(	Poco::Net::HTTPServerRequest &request,
 | 
				
			||||||
			poco_warning(Logger_, "Exception during WS creation");
 | 
											 	Poco::Net::HTTPServerResponse &response) override {
 | 
				
			||||||
 | 
								try {
 | 
				
			||||||
 | 
									auto NewConnection = std::make_shared<AP_WS_Connection>(request, response, session_id_, Logger_,
 | 
				
			||||||
 | 
																							AP_WS_Server()->NextReactor());
 | 
				
			||||||
 | 
									AP_WS_Server()->AddConnection(NewConnection);
 | 
				
			||||||
 | 
									NewConnection->Start();
 | 
				
			||||||
 | 
								} catch (...) {
 | 
				
			||||||
 | 
									poco_warning(Logger_, "Exception during WS creation");
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						  private:
 | 
				
			||||||
 | 
							Poco::Logger &Logger_;
 | 
				
			||||||
 | 
							std::uint64_t session_id_;
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						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) {
 | 
				
			||||||
 | 
									Utils::SetThreadName("ws:conn-init");
 | 
				
			||||||
 | 
									session_id_++;
 | 
				
			||||||
 | 
									return new AP_WS_RequestHandler(Logger_, session_id_);
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
									return nullptr;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
						  private:
 | 
				
			||||||
 | 
							Poco::Logger &Logger_;
 | 
				
			||||||
 | 
							inline static std::atomic_uint64_t session_id_ = 0;
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	bool AP_WS_Server::ValidateCertificate(const std::string &ConnectionId,
 | 
						bool AP_WS_Server::ValidateCertificate(const std::string &ConnectionId,
 | 
				
			||||||
@@ -57,7 +89,7 @@ namespace OpenWifi {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
		SessionTimeOut_ = MicroServiceConfigGetInt("openwifi.session.timeout", 10*60);
 | 
							SessionTimeOut_ = MicroServiceConfigGetInt("openwifi.session.timeout", 10*60);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		Reactor_pool_ = std::make_unique<AP_WS_ReactorThreadPool>();
 | 
							Reactor_pool_ = std::make_unique<AP_WS_ReactorThreadPool>(Logger());
 | 
				
			||||||
		Reactor_pool_->Start();
 | 
							Reactor_pool_->Start();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		for (const auto &Svr : ConfigServersList_) {
 | 
							for (const auto &Svr : ConfigServersList_) {
 | 
				
			||||||
@@ -135,6 +167,9 @@ namespace OpenWifi {
 | 
				
			|||||||
					WebServerHttpParams);
 | 
										WebServerHttpParams);
 | 
				
			||||||
				WebServers_.push_back(std::move(NewWebServer));
 | 
									WebServers_.push_back(std::move(NewWebServer));
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								KafkaDisableState_ = MicroServiceConfigGetBool("openwifi.kafka.disablestate", false);
 | 
				
			||||||
 | 
								KafkaDisableHealthChecks_ = MicroServiceConfigGetBool("openwifi.kafka.disablehealthchecks", false);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		for (auto &server : WebServers_) {
 | 
							for (auto &server : WebServers_) {
 | 
				
			||||||
@@ -156,243 +191,345 @@ namespace OpenWifi {
 | 
				
			|||||||
			UseDefaultConfig_ = true;
 | 
								UseDefaultConfig_ = true;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		SimulatorId_ = MicroServiceConfigGetString("simulatorid", "");
 | 
							SimulatorId_ = Poco::toLower(MicroServiceConfigGetString("simulatorid", ""));
 | 
				
			||||||
		SimulatorEnabled_ = !SimulatorId_.empty();
 | 
							SimulatorEnabled_ = !SimulatorId_.empty();
 | 
				
			||||||
		Utils::SetThreadName(ReactorThread_, "dev:react:head");
 | 
							Utils::SetThreadName(ReactorThread_, "dev:react:head");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		GarbageCollectorCallback_ = std::make_unique<Poco::TimerCallback<AP_WS_Server>>(
 | 
					 | 
				
			||||||
			*this, &AP_WS_Server::onGarbageCollecting);
 | 
					 | 
				
			||||||
		Timer_.setStartInterval(10 * 1000);
 | 
					 | 
				
			||||||
		Timer_.setPeriodicInterval(10 * 1000); // every minute
 | 
					 | 
				
			||||||
		Timer_.start(*GarbageCollectorCallback_, MicroServiceTimerPool());
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		Running_ = true;
 | 
							Running_ = true;
 | 
				
			||||||
 | 
							GarbageCollector_.setName("ws:garbage");
 | 
				
			||||||
 | 
							GarbageCollector_.start(*this);
 | 
				
			||||||
		return 0;
 | 
							return 0;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	void AP_WS_Server::onGarbageCollecting([[maybe_unused]] Poco::Timer &timer) {
 | 
						void AP_WS_Server::run() {
 | 
				
			||||||
		static uint64_t last_log = Utils::Now(), last_zombie_run = 0;
 | 
							uint64_t last_log = Utils::Now(),
 | 
				
			||||||
		auto now = Utils::Now();
 | 
									 last_zombie_run = 0,
 | 
				
			||||||
 | 
									 last_garbage_run = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		{
 | 
							Poco::Logger &LocalLogger = Poco::Logger::create(
 | 
				
			||||||
			{
 | 
								"WS-Session-Janitor", Poco::Logger::root().getChannel(), Poco::Logger::root().getLevel());
 | 
				
			||||||
				std::lock_guard SessionLock(SessionMutex_);
 | 
					
 | 
				
			||||||
				if (!Garbage_.empty()) {
 | 
							while(Running_) {
 | 
				
			||||||
					Garbage_.clear();
 | 
					
 | 
				
			||||||
				}
 | 
								if(!Poco::Thread::trySleep(30000)) {
 | 
				
			||||||
 | 
									break;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			uint64_t total_connected_time = 0;
 | 
								LocalLogger.information(fmt::format("Garbage collecting starting run."	));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if(now-last_zombie_run > 20) {
 | 
								uint64_t total_connected_time = 0, now = Utils::Now();
 | 
				
			||||||
				poco_information(Logger(), fmt::format("Garbage collecting..."));
 | 
					
 | 
				
			||||||
				std::vector<std::uint64_t> SessionsToRemove;
 | 
								if(now-last_zombie_run > 60) {
 | 
				
			||||||
				NumberOfConnectedDevices_ = 0;
 | 
									try {
 | 
				
			||||||
				NumberOfConnectingDevices_ = 0;
 | 
										poco_information(LocalLogger,
 | 
				
			||||||
				AverageDeviceConnectionTime_ = 0;
 | 
														 fmt::format("Garbage collecting zombies... (step 1)"));
 | 
				
			||||||
				last_zombie_run = now;
 | 
										NumberOfConnectedDevices_ = 0;
 | 
				
			||||||
				for(int hashIndex=0;hashIndex<256;hashIndex++) {
 | 
										NumberOfConnectingDevices_ = 0;
 | 
				
			||||||
					std::lock_guard Lock(SerialNumbersMutex_[hashIndex]);
 | 
										AverageDeviceConnectionTime_ = 0;
 | 
				
			||||||
					auto hint = SerialNumbers_[hashIndex].begin();
 | 
										int waits = 0;
 | 
				
			||||||
					while (hint != end(SerialNumbers_[hashIndex])) {
 | 
										for (int hashIndex = 0; hashIndex < MACHash::HashMax(); hashIndex++) {
 | 
				
			||||||
						if (hint->second.second == nullptr) {
 | 
											last_zombie_run = now;
 | 
				
			||||||
							hint = SerialNumbers_[hashIndex].erase(hint);
 | 
											waits = 0;
 | 
				
			||||||
						} else if ((now - hint->second.second->State_.LastContact) >
 | 
											while (true) {
 | 
				
			||||||
								   SessionTimeOut_) {
 | 
												if (SerialNumbersMutex_[hashIndex].try_lock()) {
 | 
				
			||||||
							hint->second.second->EndConnection(false);
 | 
													waits = 0;
 | 
				
			||||||
							poco_information(
 | 
													auto hint = SerialNumbers_[hashIndex].begin();
 | 
				
			||||||
								Logger(),
 | 
													while (hint != end(SerialNumbers_[hashIndex])) {
 | 
				
			||||||
								fmt::format(
 | 
					
 | 
				
			||||||
									"{}: Session seems idle. Controller disconnecting device.",
 | 
														if (hint->second == nullptr) {
 | 
				
			||||||
									hint->second.second->SerialNumber_));
 | 
															poco_information(
 | 
				
			||||||
							SessionsToRemove.emplace_back(hint->second.first);
 | 
																LocalLogger,
 | 
				
			||||||
							Garbage_.push_back(hint->second.second);
 | 
																fmt::format("Dead device found in hash index {}", hashIndex));
 | 
				
			||||||
							hint = SerialNumbers_[hashIndex].erase(hint);
 | 
															// hint = SerialNumbers_[hashIndex].erase(hint);
 | 
				
			||||||
						} else if (hint->second.second->State_.Connected) {
 | 
															hint++;
 | 
				
			||||||
							NumberOfConnectedDevices_++;
 | 
															continue;
 | 
				
			||||||
							total_connected_time += (now - hint->second.second->State_.started);
 | 
														}
 | 
				
			||||||
							hint++;
 | 
														auto Device = hint->second;
 | 
				
			||||||
						} else {
 | 
														if(Device->ConnectionMutex_.try_lock()) {
 | 
				
			||||||
							NumberOfConnectingDevices_++;
 | 
															auto RightNow = Utils::Now();
 | 
				
			||||||
							hint++;
 | 
															if (RightNow > Device->LastContact_ &&
 | 
				
			||||||
 | 
																(RightNow - Device->LastContact_) > SessionTimeOut_) {
 | 
				
			||||||
 | 
																poco_information(
 | 
				
			||||||
 | 
																	LocalLogger,
 | 
				
			||||||
 | 
																	fmt::format("{}: Session seems idle. Controller disconnecting device.",
 | 
				
			||||||
 | 
																				Device->SerialNumber_));
 | 
				
			||||||
 | 
																hint = SerialNumbers_[hashIndex].erase(hint);
 | 
				
			||||||
 | 
															} else if (Device->State_.Connected) {
 | 
				
			||||||
 | 
																NumberOfConnectedDevices_++;
 | 
				
			||||||
 | 
																total_connected_time +=
 | 
				
			||||||
 | 
																	(RightNow - Device->State_.started);
 | 
				
			||||||
 | 
																++hint;
 | 
				
			||||||
 | 
															} else {
 | 
				
			||||||
 | 
																++hint;
 | 
				
			||||||
 | 
															}
 | 
				
			||||||
 | 
															Device->ConnectionMutex_.unlock();
 | 
				
			||||||
 | 
															continue;
 | 
				
			||||||
 | 
														} else {
 | 
				
			||||||
 | 
															poco_warning(LocalLogger, fmt::format("Could not lock device mutex for {}",
 | 
				
			||||||
 | 
																								   Device->SerialNumber_));
 | 
				
			||||||
 | 
														}
 | 
				
			||||||
 | 
														++NumberOfConnectingDevices_;
 | 
				
			||||||
 | 
														++hint;
 | 
				
			||||||
 | 
													}
 | 
				
			||||||
 | 
													SerialNumbersMutex_[hashIndex].unlock();
 | 
				
			||||||
 | 
													break;
 | 
				
			||||||
 | 
												} else if (waits < 5) {
 | 
				
			||||||
 | 
													waits++;
 | 
				
			||||||
 | 
													std::this_thread::sleep_for(std::chrono::milliseconds(10));
 | 
				
			||||||
 | 
												} else {
 | 
				
			||||||
 | 
													break;
 | 
				
			||||||
 | 
												}
 | 
				
			||||||
						}
 | 
											}
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
				if(SessionsToRemove.empty()) {
 | 
										poco_information(LocalLogger,
 | 
				
			||||||
					poco_information(Logger(), fmt::format("Removing {} sessions.", SessionsToRemove.size()));
 | 
														 fmt::format("Garbage collecting zombies... (step 2)"));
 | 
				
			||||||
					std::lock_guard Lock(SessionMutex_);
 | 
										LeftOverSessions_ = 0;
 | 
				
			||||||
					for (const auto &Session : SessionsToRemove) {
 | 
										for (int i = 0; i < SessionHash::HashMax(); i++) {
 | 
				
			||||||
						Sessions_.erase(Session);
 | 
											waits = 0;
 | 
				
			||||||
 | 
											while (true) {
 | 
				
			||||||
 | 
												if (SessionMutex_[i].try_lock()) {
 | 
				
			||||||
 | 
													waits = 0;
 | 
				
			||||||
 | 
													auto hint = Sessions_[i].begin();
 | 
				
			||||||
 | 
													auto RightNow = Utils::Now();
 | 
				
			||||||
 | 
													while (hint != end(Sessions_[i])) {
 | 
				
			||||||
 | 
														if (hint->second == nullptr) {
 | 
				
			||||||
 | 
															hint = Sessions_[i].erase(hint);
 | 
				
			||||||
 | 
														} else if (RightNow > hint->second->LastContact_ &&
 | 
				
			||||||
 | 
																   (RightNow - hint->second->LastContact_) >
 | 
				
			||||||
 | 
																	   SessionTimeOut_) {
 | 
				
			||||||
 | 
															poco_information(
 | 
				
			||||||
 | 
																LocalLogger,
 | 
				
			||||||
 | 
																fmt::format("{}: Session seems idle. Controller disconnecting device.",
 | 
				
			||||||
 | 
																			hint->second->SerialNumber_));
 | 
				
			||||||
 | 
															hint = Sessions_[i].erase(hint);
 | 
				
			||||||
 | 
														} else {
 | 
				
			||||||
 | 
															++LeftOverSessions_;
 | 
				
			||||||
 | 
															++hint;
 | 
				
			||||||
 | 
														}
 | 
				
			||||||
 | 
													}
 | 
				
			||||||
 | 
													SessionMutex_[i].unlock();
 | 
				
			||||||
 | 
													break;
 | 
				
			||||||
 | 
												} else if (waits < 5) {
 | 
				
			||||||
 | 
													std::this_thread::sleep_for(std::chrono::milliseconds(10));
 | 
				
			||||||
 | 
													waits++;
 | 
				
			||||||
 | 
												} else {
 | 
				
			||||||
 | 
													break;
 | 
				
			||||||
 | 
												}
 | 
				
			||||||
 | 
											}
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
										AverageDeviceConnectionTime_ =
 | 
				
			||||||
 | 
											NumberOfConnectedDevices_ > 0
 | 
				
			||||||
 | 
												? total_connected_time / NumberOfConnectedDevices_
 | 
				
			||||||
 | 
												: 0;
 | 
				
			||||||
 | 
										poco_information(LocalLogger, fmt::format("Garbage collecting zombies done..."));
 | 
				
			||||||
 | 
									} catch (const Poco::Exception &E) {
 | 
				
			||||||
 | 
										poco_error(LocalLogger, fmt::format("Poco::Exception: Garbage collecting zombies failed: {}", E.displayText()));
 | 
				
			||||||
 | 
									} catch (const std::exception &E) {
 | 
				
			||||||
 | 
										poco_error(LocalLogger, fmt::format("std::exception: Garbage collecting zombies failed: {}", E.what()));
 | 
				
			||||||
 | 
									} catch (...) {
 | 
				
			||||||
 | 
										poco_error(LocalLogger, fmt::format("exception:Garbage collecting zombies failed: {}", "unknown"));
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				AverageDeviceConnectionTime_ =
 | 
					 | 
				
			||||||
				NumberOfConnectedDevices_ > 0 ? total_connected_time / NumberOfConnectedDevices_
 | 
					 | 
				
			||||||
											  : 0;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				poco_information(Logger(), fmt::format("Garbage collecting done..."));
 | 
					 | 
				
			||||||
			} else {
 | 
								} else {
 | 
				
			||||||
				std::lock_guard SessionLock(SessionMutex_);
 | 
									NumberOfConnectedDevices_=0;
 | 
				
			||||||
				NumberOfConnectedDevices_ = Sessions_.size();
 | 
									for(int i=0;i<MACHash::HashMax();i++) {
 | 
				
			||||||
				AverageDeviceConnectionTime_ += 10;
 | 
										std::lock_guard Lock(SerialNumbersMutex_[i]);
 | 
				
			||||||
 | 
										NumberOfConnectedDevices_ += SerialNumbers_[i].size();
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									if(NumberOfConnectedDevices_) {
 | 
				
			||||||
 | 
										if (last_garbage_run > 0) {
 | 
				
			||||||
 | 
											AverageDeviceConnectionTime_ += (now - last_garbage_run);
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
									} else {
 | 
				
			||||||
 | 
										AverageDeviceConnectionTime_ = 0;
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if ((now - last_log) > 120) {
 | 
								if ((now - last_log) > 60) {
 | 
				
			||||||
				last_log = now;
 | 
									last_log = now;
 | 
				
			||||||
				poco_information(Logger(),
 | 
									poco_information(LocalLogger,
 | 
				
			||||||
								 fmt::format("Active AP connections: {} Connecting: {} Average connection time: {} seconds",
 | 
													 fmt::format("Active AP connections: {} Connecting: {} Average connection time: {} seconds. Left Over Sessions: {}",
 | 
				
			||||||
											 NumberOfConnectedDevices_, NumberOfConnectingDevices_,
 | 
																 NumberOfConnectedDevices_, NumberOfConnectingDevices_,
 | 
				
			||||||
											 AverageDeviceConnectionTime_));
 | 
																 AverageDeviceConnectionTime_, LeftOverSessions_));
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								GWWebSocketNotifications::NumberOfConnection_t Notification;
 | 
				
			||||||
 | 
								Notification.content.numberOfConnectingDevices = NumberOfConnectingDevices_;
 | 
				
			||||||
 | 
								Notification.content.numberOfDevices = NumberOfConnectedDevices_;
 | 
				
			||||||
 | 
								Notification.content.averageConnectedTime = AverageDeviceConnectionTime_;
 | 
				
			||||||
 | 
								GetTotalDataStatistics(Notification.content.tx,Notification.content.rx);
 | 
				
			||||||
 | 
								GWWebSocketNotifications::NumberOfConnections(Notification);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								Poco::JSON::Object	KafkaNotification;
 | 
				
			||||||
 | 
								Notification.to_json(KafkaNotification);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								Poco::JSON::Object FullEvent;
 | 
				
			||||||
 | 
								FullEvent.set("type", "load-update");
 | 
				
			||||||
 | 
								FullEvent.set("timestamp", now);
 | 
				
			||||||
 | 
								FullEvent.set("payload", KafkaNotification);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								KafkaManager()->PostMessage(KafkaTopics::DEVICE_EVENT_QUEUE, "system", FullEvent);
 | 
				
			||||||
 | 
								LocalLogger.information(fmt::format("Garbage collection finished run."	));
 | 
				
			||||||
 | 
								last_garbage_run = now;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
							LocalLogger.information(fmt::format("Garbage collector done for the day."	));
 | 
				
			||||||
		GWWebSocketNotifications::NumberOfConnection_t Notification;
 | 
					 | 
				
			||||||
		Notification.content.numberOfConnectingDevices = NumberOfConnectingDevices_;
 | 
					 | 
				
			||||||
		Notification.content.numberOfDevices = NumberOfConnectedDevices_;
 | 
					 | 
				
			||||||
		Notification.content.averageConnectedTime = AverageDeviceConnectionTime_;
 | 
					 | 
				
			||||||
		GetTotalDataStatistics(Notification.content.tx,Notification.content.rx);
 | 
					 | 
				
			||||||
		GWWebSocketNotifications::NumberOfConnections(Notification);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		Poco::JSON::Object	KafkaNotification;
 | 
					 | 
				
			||||||
		Notification.to_json(KafkaNotification);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		Poco::JSON::Object FullEvent;
 | 
					 | 
				
			||||||
		FullEvent.set("type", "load-update");
 | 
					 | 
				
			||||||
		FullEvent.set("timestamp", now);
 | 
					 | 
				
			||||||
		FullEvent.set("payload", KafkaNotification);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		KafkaManager()->PostMessage(KafkaTopics::DEVICE_EVENT_QUEUE, "system", FullEvent);
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	void AP_WS_Server::Stop() {
 | 
						void AP_WS_Server::Stop() {
 | 
				
			||||||
		poco_information(Logger(), "Stopping...");
 | 
							poco_information(Logger(), "Stopping...");
 | 
				
			||||||
		Running_ = false;
 | 
							Running_ = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		Timer_.stop();
 | 
							GarbageCollector_.wakeUp();
 | 
				
			||||||
 | 
							GarbageCollector_.join();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		for (auto &server : WebServers_) {
 | 
							for (auto &server : WebServers_) {
 | 
				
			||||||
			server->stopAll();
 | 
								server->stopAll();
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		Reactor_pool_->Stop();
 | 
							Reactor_pool_->Stop();
 | 
				
			||||||
		Reactor_.stop();
 | 
							Reactor_.stop();
 | 
				
			||||||
		ReactorThread_.join();
 | 
							ReactorThread_.join();
 | 
				
			||||||
		poco_information(Logger(), "Stopped...");
 | 
							poco_information(Logger(), "Stopped...");
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						bool AP_WS_Server::GetHealthDevices(std::uint64_t lowLimit, std::uint64_t  highLimit, std::vector<std::string> & SerialNumbers) {
 | 
				
			||||||
 | 
							SerialNumbers.clear();
 | 
				
			||||||
 | 
							for(int i=0;i<SessionHash::HashMax();i++) {
 | 
				
			||||||
 | 
								std::lock_guard Lock(SessionMutex_[i]);
 | 
				
			||||||
 | 
								for (const auto &connection : Sessions_[i]) {
 | 
				
			||||||
 | 
									if (connection.second->RawLastHealthcheck_.Sanity >= lowLimit &&
 | 
				
			||||||
 | 
										connection.second->RawLastHealthcheck_.Sanity <= highLimit) {
 | 
				
			||||||
 | 
										SerialNumbers.push_back(connection.second->SerialNumber_);
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return true;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	bool AP_WS_Server::GetStatistics(uint64_t SerialNumber, std::string &Statistics) const {
 | 
						bool AP_WS_Server::GetStatistics(uint64_t SerialNumber, std::string &Statistics) const {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		auto hashIndex = Utils::CalculateMacAddressHash(SerialNumber);
 | 
							auto hashIndex = MACHash::Hash(SerialNumber);
 | 
				
			||||||
		std::lock_guard Lock(SerialNumbersMutex_[hashIndex]);
 | 
							std::lock_guard Lock(SerialNumbersMutex_[hashIndex]);
 | 
				
			||||||
		auto Device = SerialNumbers_[hashIndex].find(SerialNumber);
 | 
							auto Device = SerialNumbers_[hashIndex].find(SerialNumber);
 | 
				
			||||||
		if (Device == SerialNumbers_[hashIndex].end() || Device->second.second == nullptr) {
 | 
							if (Device == SerialNumbers_[hashIndex].end() || Device->second == nullptr) {
 | 
				
			||||||
			return false;
 | 
								return false;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		Device->second.second->GetLastStats(Statistics);
 | 
							Device->second->GetLastStats(Statistics);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		return true;
 | 
							return true;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	bool AP_WS_Server::GetState(uint64_t SerialNumber, GWObjects::ConnectionState &State) const {
 | 
						bool AP_WS_Server::GetState(uint64_t SerialNumber, GWObjects::ConnectionState &State) const {
 | 
				
			||||||
		auto hashIndex = Utils::CalculateMacAddressHash(SerialNumber);
 | 
							std::shared_ptr<AP_WS_Connection> Connection;
 | 
				
			||||||
		std::lock_guard Lock(SerialNumbersMutex_[hashIndex]);
 | 
							{
 | 
				
			||||||
		auto Device = SerialNumbers_[hashIndex].find(SerialNumber);
 | 
								auto hashIndex = MACHash::Hash(SerialNumber);
 | 
				
			||||||
		if (Device == SerialNumbers_[hashIndex].end() || Device->second.second == nullptr) {
 | 
								std::lock_guard DeviceLock(SerialNumbersMutex_[hashIndex]);
 | 
				
			||||||
			return false;
 | 
								auto DeviceHint = SerialNumbers_[hashIndex].find(SerialNumber);
 | 
				
			||||||
 | 
								if (DeviceHint == SerialNumbers_[hashIndex].end() ||
 | 
				
			||||||
 | 
									DeviceHint->second == nullptr) {
 | 
				
			||||||
 | 
									return false;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								Connection = DeviceHint->second;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		Device->second.second->GetState(State);
 | 
							Connection->GetState(State);
 | 
				
			||||||
		return true;
 | 
							return true;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	bool AP_WS_Server::GetHealthcheck(uint64_t SerialNumber,
 | 
						bool AP_WS_Server::GetHealthcheck(uint64_t SerialNumber,
 | 
				
			||||||
									  GWObjects::HealthCheck &CheckData) const {
 | 
														  GWObjects::HealthCheck &CheckData) const {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		auto hashIndex = Utils::CalculateMacAddressHash(SerialNumber);
 | 
							auto hashIndex = MACHash::Hash(SerialNumber);
 | 
				
			||||||
		std::lock_guard Lock(SerialNumbersMutex_[hashIndex]);
 | 
							std::lock_guard Lock(SerialNumbersMutex_[hashIndex]);
 | 
				
			||||||
		auto Device = SerialNumbers_[hashIndex].find(SerialNumber);
 | 
							auto Device = SerialNumbers_[hashIndex].find(SerialNumber);
 | 
				
			||||||
		if (Device == SerialNumbers_[hashIndex].end() || Device->second.second == nullptr) {
 | 
							if (Device == SerialNumbers_[hashIndex].end() || Device->second == nullptr) {
 | 
				
			||||||
			return false;
 | 
								return false;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		Device->second.second->GetLastHealthCheck(CheckData);
 | 
							Device->second->GetLastHealthCheck(CheckData);
 | 
				
			||||||
		return true;
 | 
							return true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	void AP_WS_Server::SetSessionDetails(uint64_t connection_id, uint64_t SerialNumber) {
 | 
						void AP_WS_Server::StartSession(uint64_t session_id, uint64_t SerialNumber) {
 | 
				
			||||||
		std::lock_guard SessionLock(SessionMutex_);
 | 
							auto deviceHash = MACHash::Hash(SerialNumber);
 | 
				
			||||||
		auto Conn = Sessions_.find(connection_id);
 | 
							auto sessionHash = SessionHash::Hash(session_id);
 | 
				
			||||||
		if (Conn == end(Sessions_))
 | 
							std::lock_guard SessionLock(SessionMutex_[sessionHash]);
 | 
				
			||||||
			return;
 | 
							auto SessionHint = Sessions_[sessionHash].find(session_id);
 | 
				
			||||||
 | 
							if (SessionHint != end(Sessions_[sessionHash])) {
 | 
				
			||||||
		auto hashIndex = Utils::CalculateMacAddressHash(SerialNumber);
 | 
								std::lock_guard Lock(SerialNumbersMutex_[deviceHash]);
 | 
				
			||||||
		std::lock_guard Lock(SerialNumbersMutex_[hashIndex]);
 | 
								SerialNumbers_[deviceHash][SerialNumber] = SessionHint->second;
 | 
				
			||||||
		auto CurrentSerialNumber = SerialNumbers_[hashIndex].find(SerialNumber);
 | 
								Sessions_[sessionHash].erase(SessionHint);
 | 
				
			||||||
		if ((CurrentSerialNumber == SerialNumbers_[hashIndex].end()) ||
 | 
							} else {
 | 
				
			||||||
			(CurrentSerialNumber->second.first < connection_id)) {
 | 
								poco_error(Logger(), fmt::format("StartSession: Could not find session '{}'", session_id));
 | 
				
			||||||
			SerialNumbers_[hashIndex][SerialNumber] = std::make_pair(connection_id, Conn->second);
 | 
					 | 
				
			||||||
			return;
 | 
					 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	bool AP_WS_Server::EndSession(uint64_t session_id, uint64_t SerialNumber) {
 | 
						bool AP_WS_Server::EndSession(uint64_t session_id, uint64_t SerialNumber) {
 | 
				
			||||||
		std::lock_guard SessionLock(SessionMutex_);
 | 
							{
 | 
				
			||||||
		auto Session = Sessions_.find(session_id);
 | 
								auto sessionHash = SessionHash::Hash(session_id);
 | 
				
			||||||
		if (Session == end(Sessions_))
 | 
								std::lock_guard SessionLock(SessionMutex_[sessionHash]);
 | 
				
			||||||
			return false;
 | 
								Sessions_[sessionHash].erase(session_id);
 | 
				
			||||||
 | 
					 | 
				
			||||||
		Garbage_.push_back(Session->second);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		auto hashIndex = Utils::CalculateMacAddressHash(SerialNumber);
 | 
					 | 
				
			||||||
		std::lock_guard Lock(SerialNumbersMutex_[hashIndex]);
 | 
					 | 
				
			||||||
		auto Device = SerialNumbers_[hashIndex].find(SerialNumber);
 | 
					 | 
				
			||||||
		if (Device == end(SerialNumbers_[hashIndex])) {
 | 
					 | 
				
			||||||
			Sessions_.erase(Session);
 | 
					 | 
				
			||||||
			return false;
 | 
					 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (Device->second.first == session_id) {
 | 
							{
 | 
				
			||||||
			Sessions_.erase(Session);
 | 
								auto hashIndex = MACHash::Hash(SerialNumber);
 | 
				
			||||||
			SerialNumbers_[hashIndex].erase(Device);
 | 
								std::lock_guard DeviceLock(SerialNumbersMutex_[hashIndex]);
 | 
				
			||||||
			return true;
 | 
								auto DeviceHint = SerialNumbers_[hashIndex].find(SerialNumber);
 | 
				
			||||||
 | 
								if (DeviceHint == SerialNumbers_[hashIndex].end()
 | 
				
			||||||
 | 
									|| DeviceHint->second == nullptr
 | 
				
			||||||
 | 
									|| DeviceHint->second->State_.sessionId != session_id) {
 | 
				
			||||||
 | 
									return false;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								SerialNumbers_[hashIndex].erase(DeviceHint);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
							return true;
 | 
				
			||||||
		Sessions_.erase(Session);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		return false;
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	bool AP_WS_Server::Connected(uint64_t SerialNumber,
 | 
						bool AP_WS_Server::Connected(uint64_t SerialNumber,
 | 
				
			||||||
								 GWObjects::DeviceRestrictions &Restrictions) const {
 | 
													 GWObjects::DeviceRestrictions &Restrictions) const {
 | 
				
			||||||
		auto hashIndex = Utils::CalculateMacAddressHash(SerialNumber);
 | 
							auto hashIndex = MACHash::Hash(SerialNumber);
 | 
				
			||||||
		std::lock_guard Lock(SerialNumbersMutex_[hashIndex]);
 | 
							std::lock_guard DeviceLock(SerialNumbersMutex_[hashIndex]);
 | 
				
			||||||
		auto Device = SerialNumbers_[hashIndex].find(SerialNumber);
 | 
							auto DeviceHint = SerialNumbers_[hashIndex].find(SerialNumber);
 | 
				
			||||||
		if (Device == end(SerialNumbers_[hashIndex]) || Device->second.second == nullptr) {
 | 
							if (DeviceHint == end(SerialNumbers_[hashIndex]) || DeviceHint->second == nullptr) {
 | 
				
			||||||
			return false;
 | 
								return false;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		Device->second.second->GetRestrictions(Restrictions);
 | 
							if(!DeviceHint->second->Dead_) {
 | 
				
			||||||
		return Device->second.second->State_.Connected;
 | 
								DeviceHint->second->GetRestrictions(Restrictions);
 | 
				
			||||||
 | 
								return DeviceHint->second->State_.Connected;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return false;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	bool AP_WS_Server::Connected(uint64_t SerialNumber) const {
 | 
						bool AP_WS_Server::Connected(uint64_t SerialNumber) const {
 | 
				
			||||||
		auto hashIndex = Utils::CalculateMacAddressHash(SerialNumber);
 | 
							auto hashIndex = MACHash::Hash(SerialNumber);
 | 
				
			||||||
		std::lock_guard Lock(SerialNumbersMutex_[hashIndex]);
 | 
							std::lock_guard Lock(SerialNumbersMutex_[hashIndex]);
 | 
				
			||||||
		auto Device = SerialNumbers_[hashIndex].find(SerialNumber);
 | 
							auto DeviceHint = SerialNumbers_[hashIndex].find(SerialNumber);
 | 
				
			||||||
		if (Device == end(SerialNumbers_[hashIndex]) || Device->second.second == nullptr) {
 | 
							if (DeviceHint == end(SerialNumbers_[hashIndex]) || DeviceHint->second == nullptr) {
 | 
				
			||||||
			return false;
 | 
								return false;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		return Device->second.second->State_.Connected;
 | 
							if(!DeviceHint->second->Dead_) {
 | 
				
			||||||
 | 
								return DeviceHint->second->State_.Connected;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return false;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	bool AP_WS_Server::SendFrame(uint64_t SerialNumber, const std::string &Payload) const {
 | 
						bool AP_WS_Server::SendFrame(uint64_t SerialNumber, const std::string &Payload) const {
 | 
				
			||||||
		auto hashIndex = Utils::CalculateMacAddressHash(SerialNumber);
 | 
							auto hashIndex = MACHash::Hash(SerialNumber);
 | 
				
			||||||
		std::lock_guard Lock(SerialNumbersMutex_[hashIndex]);
 | 
							std::lock_guard Lock(SerialNumbersMutex_[hashIndex]);
 | 
				
			||||||
		auto Device = SerialNumbers_[hashIndex].find(SerialNumber);
 | 
							auto DeviceHint = SerialNumbers_[hashIndex].find(SerialNumber);
 | 
				
			||||||
		if (Device == end(SerialNumbers_[hashIndex]) || Device->second.second == nullptr) {
 | 
							if (DeviceHint == end(SerialNumbers_[hashIndex]) || DeviceHint->second == nullptr) {
 | 
				
			||||||
 | 
								return false;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if(DeviceHint->second->Dead_) {
 | 
				
			||||||
			return false;
 | 
								return false;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		try {
 | 
							try {
 | 
				
			||||||
			return Device->second.second->Send(Payload);
 | 
								return DeviceHint->second->Send(Payload);
 | 
				
			||||||
		} catch (...) {
 | 
							} catch (...) {
 | 
				
			||||||
			poco_debug(Logger(), fmt::format(": SendFrame: Could not send data to device '{}'",
 | 
								poco_debug(Logger(), fmt::format(": SendFrame: Could not send data to device '{}'",
 | 
				
			||||||
											 Utils::IntToSerialNumber(SerialNumber)));
 | 
																 Utils::IntToSerialNumber(SerialNumber)));
 | 
				
			||||||
@@ -401,48 +538,48 @@ namespace OpenWifi {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	void AP_WS_Server::StopWebSocketTelemetry(uint64_t RPCID, uint64_t SerialNumber) {
 | 
						void AP_WS_Server::StopWebSocketTelemetry(uint64_t RPCID, uint64_t SerialNumber) {
 | 
				
			||||||
		auto hashIndex = Utils::CalculateMacAddressHash(SerialNumber);
 | 
							auto hashIndex = MACHash::Hash(SerialNumber);
 | 
				
			||||||
		std::lock_guard Lock(SerialNumbersMutex_[hashIndex]);
 | 
							std::lock_guard Lock(SerialNumbersMutex_[hashIndex]);
 | 
				
			||||||
		auto Device = SerialNumbers_[hashIndex].find(SerialNumber);
 | 
							auto Device = SerialNumbers_[hashIndex].find(SerialNumber);
 | 
				
			||||||
		if (Device == end(SerialNumbers_[hashIndex]) || Device->second.second == nullptr) {
 | 
							if (Device == end(SerialNumbers_[hashIndex]) || Device->second == nullptr) {
 | 
				
			||||||
			return;
 | 
								return;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		Device->second.second->StopWebSocketTelemetry(RPCID);
 | 
							Device->second->StopWebSocketTelemetry(RPCID);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	void
 | 
						void
 | 
				
			||||||
	AP_WS_Server::SetWebSocketTelemetryReporting(uint64_t RPCID, uint64_t SerialNumber,
 | 
						AP_WS_Server::SetWebSocketTelemetryReporting(uint64_t RPCID, uint64_t SerialNumber,
 | 
				
			||||||
												 uint64_t Interval, uint64_t Lifetime,
 | 
																	 uint64_t Interval, uint64_t Lifetime,
 | 
				
			||||||
												 const std::vector<std::string> &TelemetryTypes) {
 | 
																	 const std::vector<std::string> &TelemetryTypes) {
 | 
				
			||||||
		auto hashIndex = Utils::CalculateMacAddressHash(SerialNumber);
 | 
							auto hashIndex = MACHash::Hash(SerialNumber);
 | 
				
			||||||
		std::lock_guard Lock(SerialNumbersMutex_[hashIndex]);
 | 
							std::lock_guard DeviceLock(SerialNumbersMutex_[hashIndex]);
 | 
				
			||||||
		auto Device = SerialNumbers_[hashIndex].find(SerialNumber);
 | 
							auto DeviceHint = SerialNumbers_[hashIndex].find(SerialNumber);
 | 
				
			||||||
		if (Device == end(SerialNumbers_[hashIndex]) || Device->second.second == nullptr) {
 | 
							if (DeviceHint == end(SerialNumbers_[hashIndex]) || DeviceHint->second == nullptr) {
 | 
				
			||||||
			return;
 | 
								return;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		Device->second.second->SetWebSocketTelemetryReporting(RPCID, Interval, Lifetime, TelemetryTypes);
 | 
							DeviceHint->second->SetWebSocketTelemetryReporting(RPCID, Interval, Lifetime, TelemetryTypes);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	void AP_WS_Server::SetKafkaTelemetryReporting(uint64_t RPCID, uint64_t SerialNumber,
 | 
						void AP_WS_Server::SetKafkaTelemetryReporting(uint64_t RPCID, uint64_t SerialNumber,
 | 
				
			||||||
												  uint64_t Interval, uint64_t Lifetime,
 | 
																	  uint64_t Interval, uint64_t Lifetime,
 | 
				
			||||||
												  const std::vector<std::string> &TelemetryTypes) {
 | 
																	  const std::vector<std::string> &TelemetryTypes) {
 | 
				
			||||||
		auto hashIndex = Utils::CalculateMacAddressHash(SerialNumber);
 | 
							auto hashIndex = MACHash::Hash(SerialNumber);
 | 
				
			||||||
		std::lock_guard Lock(SerialNumbersMutex_[hashIndex]);
 | 
							std::lock_guard Lock(SerialNumbersMutex_[hashIndex]);
 | 
				
			||||||
		auto Device = SerialNumbers_[hashIndex].find(SerialNumber);
 | 
							auto DeviceHint = SerialNumbers_[hashIndex].find(SerialNumber);
 | 
				
			||||||
		if (Device == end(SerialNumbers_[hashIndex]) || Device->second.second == nullptr) {
 | 
							if (DeviceHint == end(SerialNumbers_[hashIndex]) || DeviceHint->second == nullptr) {
 | 
				
			||||||
			return;
 | 
								return;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		Device->second.second->SetKafkaTelemetryReporting(RPCID, Interval, Lifetime, TelemetryTypes);
 | 
							DeviceHint->second->SetKafkaTelemetryReporting(RPCID, Interval, Lifetime, TelemetryTypes);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	void AP_WS_Server::StopKafkaTelemetry(uint64_t RPCID, uint64_t SerialNumber) {
 | 
						void AP_WS_Server::StopKafkaTelemetry(uint64_t RPCID, uint64_t SerialNumber) {
 | 
				
			||||||
		auto hashIndex = Utils::CalculateMacAddressHash(SerialNumber);
 | 
							auto hashIndex = MACHash::Hash(SerialNumber);
 | 
				
			||||||
		std::lock_guard Lock(SerialNumbersMutex_[hashIndex]);
 | 
							std::lock_guard DevicesLock(SerialNumbersMutex_[hashIndex]);
 | 
				
			||||||
		auto Device = SerialNumbers_[hashIndex].find(SerialNumber);
 | 
							auto DeviceHint = SerialNumbers_[hashIndex].find(SerialNumber);
 | 
				
			||||||
		if (Device == end(SerialNumbers_[hashIndex]) || Device->second.second == nullptr) {
 | 
							if (DeviceHint == end(SerialNumbers_[hashIndex]) || DeviceHint->second == nullptr) {
 | 
				
			||||||
			return;
 | 
								return;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		Device->second.second->StopKafkaTelemetry(RPCID);
 | 
							DeviceHint->second->StopKafkaTelemetry(RPCID);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	void AP_WS_Server::GetTelemetryParameters(
 | 
						void AP_WS_Server::GetTelemetryParameters(
 | 
				
			||||||
@@ -451,14 +588,14 @@ namespace OpenWifi {
 | 
				
			|||||||
		uint64_t &TelemetryWebSocketCount, uint64_t &TelemetryKafkaCount,
 | 
							uint64_t &TelemetryWebSocketCount, uint64_t &TelemetryKafkaCount,
 | 
				
			||||||
		uint64_t &TelemetryWebSocketPackets, uint64_t &TelemetryKafkaPackets) {
 | 
							uint64_t &TelemetryWebSocketPackets, uint64_t &TelemetryKafkaPackets) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		auto hashIndex = Utils::CalculateMacAddressHash(SerialNumber);
 | 
							auto hashIndex = MACHash::Hash(SerialNumber);
 | 
				
			||||||
		std::lock_guard Lock(SerialNumbersMutex_[hashIndex]);
 | 
							std::lock_guard DevicesLock(SerialNumbersMutex_[hashIndex]);
 | 
				
			||||||
		auto Device = SerialNumbers_[hashIndex].find(SerialNumber);
 | 
							auto DeviceHint = SerialNumbers_[hashIndex].find(SerialNumber);
 | 
				
			||||||
		if (Device == end(SerialNumbers_[hashIndex]) || Device->second.second == nullptr) {
 | 
							if (DeviceHint == end(SerialNumbers_[hashIndex]) || DeviceHint->second == nullptr) {
 | 
				
			||||||
			return;
 | 
								return;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		Device->second.second->GetTelemetryParameters(TelemetryRunning, TelemetryInterval,
 | 
							DeviceHint->second->GetTelemetryParameters(TelemetryRunning, TelemetryInterval,
 | 
				
			||||||
										  TelemetryWebSocketTimer, TelemetryKafkaTimer,
 | 
															  TelemetryWebSocketTimer, TelemetryKafkaTimer,
 | 
				
			||||||
										  TelemetryWebSocketCount, TelemetryKafkaCount,
 | 
															  TelemetryWebSocketCount, TelemetryKafkaCount,
 | 
				
			||||||
										  TelemetryWebSocketPackets, TelemetryKafkaPackets);
 | 
															  TelemetryWebSocketPackets, TelemetryKafkaPackets);
 | 
				
			||||||
@@ -468,15 +605,19 @@ namespace OpenWifi {
 | 
				
			|||||||
												const unsigned char *buffer, std::size_t size) {
 | 
																	const unsigned char *buffer, std::size_t size) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		auto IntSerialNumber = Utils::SerialNumberToInt(SerialNumber);
 | 
							auto IntSerialNumber = Utils::SerialNumberToInt(SerialNumber);
 | 
				
			||||||
		auto hashIndex = Utils::CalculateMacAddressHash(IntSerialNumber);
 | 
							auto hashIndex = MACHash::Hash(IntSerialNumber);
 | 
				
			||||||
		std::lock_guard Lock(SerialNumbersMutex_[hashIndex]);
 | 
							std::lock_guard DevicesLock(SerialNumbersMutex_[hashIndex]);
 | 
				
			||||||
		auto Device = SerialNumbers_[hashIndex].find(IntSerialNumber);
 | 
							auto DeviceHint = SerialNumbers_[hashIndex].find(IntSerialNumber);
 | 
				
			||||||
		if (Device == end(SerialNumbers_[hashIndex]) || Device->second.second == nullptr) {
 | 
							if (DeviceHint == end(SerialNumbers_[hashIndex]) || DeviceHint->second == nullptr) {
 | 
				
			||||||
 | 
								return false;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if(DeviceHint->second->Dead_) {
 | 
				
			||||||
			return false;
 | 
								return false;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		try {
 | 
							try {
 | 
				
			||||||
			return Device->second.second->SendRadiusAccountingData(buffer, size);
 | 
								return DeviceHint->second->SendRadiusAccountingData(buffer, size);
 | 
				
			||||||
		} catch (...) {
 | 
							} catch (...) {
 | 
				
			||||||
			poco_debug(
 | 
								poco_debug(
 | 
				
			||||||
				Logger(),
 | 
									Logger(),
 | 
				
			||||||
@@ -489,15 +630,19 @@ namespace OpenWifi {
 | 
				
			|||||||
	bool AP_WS_Server::SendRadiusAuthenticationData(const std::string &SerialNumber,
 | 
						bool AP_WS_Server::SendRadiusAuthenticationData(const std::string &SerialNumber,
 | 
				
			||||||
													const unsigned char *buffer, std::size_t size) {
 | 
																		const unsigned char *buffer, std::size_t size) {
 | 
				
			||||||
		auto IntSerialNumber = Utils::SerialNumberToInt(SerialNumber);
 | 
							auto IntSerialNumber = Utils::SerialNumberToInt(SerialNumber);
 | 
				
			||||||
		auto hashIndex = Utils::CalculateMacAddressHash(IntSerialNumber);
 | 
							auto hashIndex = MACHash::Hash(IntSerialNumber);
 | 
				
			||||||
		std::lock_guard Lock(SerialNumbersMutex_[hashIndex]);
 | 
							std::lock_guard DevicesLock(SerialNumbersMutex_[hashIndex]);
 | 
				
			||||||
		auto Device = SerialNumbers_[hashIndex].find(IntSerialNumber);
 | 
							auto DeviceHint = SerialNumbers_[hashIndex].find(IntSerialNumber);
 | 
				
			||||||
		if (Device == end(SerialNumbers_[hashIndex]) || Device->second.second == nullptr) {
 | 
							if (DeviceHint == end(SerialNumbers_[hashIndex]) || DeviceHint->second == nullptr) {
 | 
				
			||||||
 | 
								return false;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if(DeviceHint->second->Dead_) {
 | 
				
			||||||
			return false;
 | 
								return false;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		try {
 | 
							try {
 | 
				
			||||||
			return Device->second.second->SendRadiusAuthenticationData(buffer, size);
 | 
								return DeviceHint->second->SendRadiusAuthenticationData(buffer, size);
 | 
				
			||||||
		} catch (...) {
 | 
							} catch (...) {
 | 
				
			||||||
			poco_debug(
 | 
								poco_debug(
 | 
				
			||||||
				Logger(),
 | 
									Logger(),
 | 
				
			||||||
@@ -510,15 +655,18 @@ namespace OpenWifi {
 | 
				
			|||||||
	bool AP_WS_Server::SendRadiusCoAData(const std::string &SerialNumber,
 | 
						bool AP_WS_Server::SendRadiusCoAData(const std::string &SerialNumber,
 | 
				
			||||||
										 const unsigned char *buffer, std::size_t size) {
 | 
															 const unsigned char *buffer, std::size_t size) {
 | 
				
			||||||
		auto IntSerialNumber = Utils::SerialNumberToInt(SerialNumber);
 | 
							auto IntSerialNumber = Utils::SerialNumberToInt(SerialNumber);
 | 
				
			||||||
		auto hashIndex = Utils::CalculateMacAddressHash(IntSerialNumber);
 | 
							auto hashIndex = MACHash::Hash(IntSerialNumber);
 | 
				
			||||||
		std::lock_guard Lock(SerialNumbersMutex_[hashIndex]);
 | 
							std::lock_guard DevicesGuard(SerialNumbersMutex_[hashIndex]);
 | 
				
			||||||
		auto Device = SerialNumbers_[hashIndex].find(IntSerialNumber);
 | 
							auto DeviceHint = SerialNumbers_[hashIndex].find(IntSerialNumber);
 | 
				
			||||||
		if (Device == end(SerialNumbers_[hashIndex]) || Device->second.second == nullptr) {
 | 
							if (DeviceHint == end(SerialNumbers_[hashIndex]) || DeviceHint->second == nullptr) {
 | 
				
			||||||
			return false;
 | 
								return false;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if(DeviceHint->second->Dead_) {
 | 
				
			||||||
 | 
								return false;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
		try {
 | 
							try {
 | 
				
			||||||
			return Device->second.second->SendRadiusCoAData(buffer, size);
 | 
								return DeviceHint->second->SendRadiusCoAData(buffer, size);
 | 
				
			||||||
		} catch (...) {
 | 
							} catch (...) {
 | 
				
			||||||
			poco_debug(Logger(),
 | 
								poco_debug(Logger(),
 | 
				
			||||||
					   fmt::format(": SendRadiusCoAData: Could not send data to device '{}'",
 | 
										   fmt::format(": SendRadiusCoAData: Could not send data to device '{}'",
 | 
				
			||||||
@@ -527,4 +675,32 @@ namespace OpenWifi {
 | 
				
			|||||||
		return false;
 | 
							return false;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						bool AP_WS_Server::ExtendedAttributes(const std::string &serialNumber,
 | 
				
			||||||
 | 
													   bool & hasGPS,
 | 
				
			||||||
 | 
													   std::uint64_t &Sanity,
 | 
				
			||||||
 | 
													   std::double_t &MemoryUsed,
 | 
				
			||||||
 | 
													   std::double_t &Load,
 | 
				
			||||||
 | 
													   std::double_t &Temperature
 | 
				
			||||||
 | 
						) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							auto serialNumberInt = Utils::SerialNumberToInt(serialNumber);
 | 
				
			||||||
 | 
							auto hashIndex = MACHash::Hash(serialNumberInt);
 | 
				
			||||||
 | 
							std::lock_guard	DevicesGuard(SerialNumbersMutex_[hashIndex]);
 | 
				
			||||||
 | 
							auto DeviceHint = SerialNumbers_[hashIndex].find(Utils::SerialNumberToInt(serialNumber));
 | 
				
			||||||
 | 
							if(DeviceHint==end(SerialNumbers_[hashIndex])) {
 | 
				
			||||||
 | 
								return false;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if(DeviceHint->second->Dead_) {
 | 
				
			||||||
 | 
								return false;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							std::lock_guard DeviceGuard(DeviceHint->second->ConnectionMutex_);
 | 
				
			||||||
 | 
							hasGPS = DeviceHint->second->hasGPS_;
 | 
				
			||||||
 | 
							Sanity = DeviceHint->second->RawLastHealthcheck_.Sanity;
 | 
				
			||||||
 | 
							MemoryUsed = DeviceHint->second->memory_used_;
 | 
				
			||||||
 | 
							Load = DeviceHint->second->cpu_load_;
 | 
				
			||||||
 | 
							Temperature = DeviceHint->second->temperature_;
 | 
				
			||||||
 | 
							return true;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
} // namespace OpenWifi
 | 
					} // namespace OpenWifi
 | 
				
			||||||
@@ -24,46 +24,51 @@
 | 
				
			|||||||
#include "Poco/Timer.h"
 | 
					#include "Poco/Timer.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "AP_WS_Connection.h"
 | 
					#include "AP_WS_Connection.h"
 | 
				
			||||||
#include "AP_WS_ReactorPool.h"
 | 
					#include "AP_WS_Reactor_Pool.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "framework/SubSystemServer.h"
 | 
					#include "framework/SubSystemServer.h"
 | 
				
			||||||
#include "framework/utils.h"
 | 
					#include "framework/utils.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace OpenWifi {
 | 
					namespace OpenWifi {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	class AP_WS_RequestHandler : public Poco::Net::HTTPRequestHandler {
 | 
						constexpr uint MACHashMax = 256;
 | 
				
			||||||
 | 
						constexpr uint MACHashMask = MACHashMax-1;
 | 
				
			||||||
 | 
						class MACHash {
 | 
				
			||||||
	  public:
 | 
						  public:
 | 
				
			||||||
		explicit AP_WS_RequestHandler(Poco::Logger &L, uint64_t id) : Logger_(L), id_(id){};
 | 
							[[nodiscard]] static inline uint16_t Hash(std::uint64_t value) {
 | 
				
			||||||
 | 
								uint8_t hash = 0, i=6;
 | 
				
			||||||
		void handleRequest(Poco::Net::HTTPServerRequest &request,
 | 
								while(i) {
 | 
				
			||||||
						   Poco::Net::HTTPServerResponse &response) override;
 | 
									hash ^= (value & MACHashMask) + 1;
 | 
				
			||||||
 | 
									value >>= 8;
 | 
				
			||||||
	  private:
 | 
									--i;
 | 
				
			||||||
		Poco::Logger &Logger_;
 | 
					 | 
				
			||||||
		uint64_t id_ = 0;
 | 
					 | 
				
			||||||
	};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	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) {
 | 
					 | 
				
			||||||
				Utils::SetThreadName("ws:conn-init");
 | 
					 | 
				
			||||||
				return new AP_WS_RequestHandler(Logger_, id_++);
 | 
					 | 
				
			||||||
			} else {
 | 
					 | 
				
			||||||
				return nullptr;
 | 
					 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
								return hash;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	  private:
 | 
							[[nodiscard]] static inline uint16_t Hash(const std::string & value) {
 | 
				
			||||||
		Poco::Logger &Logger_;
 | 
								return Hash(Utils::MACToInt(value));
 | 
				
			||||||
		inline static uint64_t id_ = 1;
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							[[nodiscard]] static inline uint16_t HashMax() {
 | 
				
			||||||
 | 
								return MACHashMax;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	class AP_WS_Server : public SubSystemServer {
 | 
						constexpr uint SessionHashMax = 256;
 | 
				
			||||||
 | 
						constexpr uint SessionHashMask = SessionHashMax-1;
 | 
				
			||||||
 | 
						class SessionHash {
 | 
				
			||||||
 | 
						  public:
 | 
				
			||||||
 | 
							[[nodiscard]] static inline uint16_t Hash(std::uint64_t value) {
 | 
				
			||||||
 | 
								return (value & SessionHashMask);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							[[nodiscard]] static inline uint16_t HashMax() {
 | 
				
			||||||
 | 
								return SessionHashMax;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						class AP_WS_Server : public SubSystemServer, public Poco::Runnable {
 | 
				
			||||||
	  public:
 | 
						  public:
 | 
				
			||||||
		static auto instance() {
 | 
							static auto instance() {
 | 
				
			||||||
			static auto instance_ = new AP_WS_Server;
 | 
								static auto instance_ = new AP_WS_Server;
 | 
				
			||||||
@@ -77,48 +82,47 @@ namespace OpenWifi {
 | 
				
			|||||||
								 const Poco::Crypto::X509Certificate &Certificate);
 | 
													 const Poco::Crypto::X509Certificate &Certificate);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		inline bool IsSimSerialNumber(const std::string &SerialNumber) const {
 | 
							inline bool IsSimSerialNumber(const std::string &SerialNumber) const {
 | 
				
			||||||
			return IsSim(Poco::toLower(SerialNumber)) &&
 | 
								return IsSim(SerialNumber) &&
 | 
				
			||||||
				   Poco::toLower(SerialNumber) == Poco::toLower(SimulatorId_);
 | 
									   SerialNumber == SimulatorId_;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		inline static bool IsSim(const std::string &SerialNumber) {
 | 
							inline static bool IsSim(const std::string &SerialNumber) {
 | 
				
			||||||
			return SerialNumber.substr(0, 6) == "53494d";
 | 
								return SerialNumber.substr(0, 6) == "53494d";
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		inline bool IsSimEnabled() const { return SimulatorEnabled_; }
 | 
							void run() override;		//	Garbage collector thread.
 | 
				
			||||||
 | 
							[[nodiscard]] inline bool IsSimEnabled() const { return SimulatorEnabled_; }
 | 
				
			||||||
		inline bool AllowSerialNumberMismatch() const { return AllowSerialNumberMismatch_; }
 | 
							[[nodiscard]] inline bool AllowSerialNumberMismatch() const { return AllowSerialNumberMismatch_; }
 | 
				
			||||||
 | 
							[[nodiscard]] inline uint64_t MismatchDepth() const { return MismatchDepth_; }
 | 
				
			||||||
		inline uint64_t MismatchDepth() const { return MismatchDepth_; }
 | 
							[[nodiscard]] inline bool UseProvisioning() const { return LookAtProvisioning_; }
 | 
				
			||||||
 | 
							[[nodiscard]] inline bool UseDefaults() const { return UseDefaultConfig_; }
 | 
				
			||||||
		inline bool UseProvisioning() const { return LookAtProvisioning_; }
 | 
							[[nodiscard]] inline bool Running() const { return Running_; }
 | 
				
			||||||
		inline bool UseDefaults() const { return UseDefaultConfig_; }
 | 
							[[nodiscard]] inline std::pair<std::shared_ptr<Poco::Net::SocketReactor>, std::shared_ptr<LockedDbSession>> NextReactor() {
 | 
				
			||||||
 | 
					 | 
				
			||||||
		[[nodiscard]] inline Poco::Net::SocketReactor &NextReactor() {
 | 
					 | 
				
			||||||
			return Reactor_pool_->NextReactor();
 | 
								return Reactor_pool_->NextReactor();
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		[[nodiscard]] inline bool Running() const { return Running_; }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		inline void AddConnection(uint64_t session_id,
 | 
							inline void AddConnection(std::shared_ptr<AP_WS_Connection> Connection) {
 | 
				
			||||||
								  std::shared_ptr<AP_WS_Connection> Connection) {
 | 
								std::uint64_t sessionHash = SessionHash::Hash(Connection->State_.sessionId);
 | 
				
			||||||
			std::lock_guard Lock(SessionMutex_);
 | 
								std::lock_guard Lock(SessionMutex_[sessionHash]);
 | 
				
			||||||
			Sessions_[session_id] = std::move(Connection);
 | 
								if(Sessions_[sessionHash].find(Connection->State_.sessionId)==end(Sessions_[sessionHash])) {
 | 
				
			||||||
 | 
									Sessions_[sessionHash][Connection->State_.sessionId] = std::move(Connection);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		inline bool DeviceRequiresSecureRtty(uint64_t serialNumber) const {
 | 
							[[nodiscard]] inline bool DeviceRequiresSecureRTTY(uint64_t serialNumber) const {
 | 
				
			||||||
			auto hashIndex = Utils::CalculateMacAddressHash(serialNumber);
 | 
								auto hashIndex = MACHash::Hash(serialNumber);
 | 
				
			||||||
			std::lock_guard	G(SerialNumbersMutex_[hashIndex]);
 | 
								std::lock_guard	G(SerialNumbersMutex_[hashIndex]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			auto Connection = SerialNumbers_[hashIndex].find(serialNumber);
 | 
								auto Connection = SerialNumbers_[hashIndex].find(serialNumber);
 | 
				
			||||||
			if (Connection==end(SerialNumbers_[hashIndex]) || Connection->second.second==nullptr)
 | 
								if (Connection==end(SerialNumbers_[hashIndex]) || Connection->second==nullptr)
 | 
				
			||||||
				return false;
 | 
									return false;
 | 
				
			||||||
			return Connection->second.second->RttyMustBeSecure_;
 | 
								return Connection->second->RTTYMustBeSecure_;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		inline bool GetStatistics(const std::string &SerialNumber, std::string &Statistics) const {
 | 
							inline bool GetStatistics(const std::string &SerialNumber, std::string &Statistics) const {
 | 
				
			||||||
			return GetStatistics(Utils::SerialNumberToInt(SerialNumber), Statistics);
 | 
								return GetStatistics(Utils::SerialNumberToInt(SerialNumber), Statistics);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		bool GetStatistics(uint64_t SerialNumber, std::string &Statistics) const;
 | 
							[[nodiscard]] bool GetStatistics(uint64_t SerialNumber, std::string &Statistics) const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		inline bool GetState(const std::string &SerialNumber,
 | 
							inline bool GetState(const std::string &SerialNumber,
 | 
				
			||||||
							 GWObjects::ConnectionState &State) const {
 | 
												 GWObjects::ConnectionState &State) const {
 | 
				
			||||||
@@ -134,13 +138,7 @@ namespace OpenWifi {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
		bool Connected(uint64_t SerialNumber, GWObjects::DeviceRestrictions &Restrictions) const;
 | 
							bool Connected(uint64_t SerialNumber, GWObjects::DeviceRestrictions &Restrictions) const;
 | 
				
			||||||
		bool Connected(uint64_t SerialNumber) const;
 | 
							bool Connected(uint64_t SerialNumber) const;
 | 
				
			||||||
 | 
					 | 
				
			||||||
		inline bool SendFrame(const std::string &SerialNumber, const std::string &Payload) const {
 | 
					 | 
				
			||||||
			return SendFrame(Utils::SerialNumberToInt(SerialNumber), Payload);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		bool SendFrame(uint64_t SerialNumber, const std::string &Payload) const;
 | 
							bool SendFrame(uint64_t SerialNumber, const std::string &Payload) const;
 | 
				
			||||||
 | 
					 | 
				
			||||||
		bool SendRadiusAuthenticationData(const std::string &SerialNumber,
 | 
							bool SendRadiusAuthenticationData(const std::string &SerialNumber,
 | 
				
			||||||
										  const unsigned char *buffer, std::size_t size);
 | 
															  const unsigned char *buffer, std::size_t size);
 | 
				
			||||||
		bool SendRadiusAccountingData(const std::string &SerialNumber, const unsigned char *buffer,
 | 
							bool SendRadiusAccountingData(const std::string &SerialNumber, const unsigned char *buffer,
 | 
				
			||||||
@@ -148,9 +146,8 @@ namespace OpenWifi {
 | 
				
			|||||||
		bool SendRadiusCoAData(const std::string &SerialNumber, const unsigned char *buffer,
 | 
							bool SendRadiusCoAData(const std::string &SerialNumber, const unsigned char *buffer,
 | 
				
			||||||
							   std::size_t size);
 | 
												   std::size_t size);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		void SetSessionDetails(uint64_t connection_id, uint64_t SerialNumber);
 | 
							void StartSession(uint64_t session_id, uint64_t SerialNumber);
 | 
				
			||||||
		bool EndSession(uint64_t connection_id, uint64_t serial_number);
 | 
							bool EndSession(uint64_t session_id, uint64_t SerialNumber);
 | 
				
			||||||
		bool EndSessionUnSafe(uint64_t session_id, uint64_t serial_number);
 | 
					 | 
				
			||||||
		void SetWebSocketTelemetryReporting(uint64_t RPCID, uint64_t SerialNumber,
 | 
							void SetWebSocketTelemetryReporting(uint64_t RPCID, uint64_t SerialNumber,
 | 
				
			||||||
											uint64_t Interval, uint64_t Lifetime,
 | 
																uint64_t Interval, uint64_t Lifetime,
 | 
				
			||||||
											const std::vector<std::string> &TelemetryTypes);
 | 
																const std::vector<std::string> &TelemetryTypes);
 | 
				
			||||||
@@ -167,7 +164,9 @@ namespace OpenWifi {
 | 
				
			|||||||
									uint64_t &TelemetryWebSocketPackets,
 | 
														uint64_t &TelemetryWebSocketPackets,
 | 
				
			||||||
									uint64_t &TelemetryKafkaPackets);
 | 
														uint64_t &TelemetryKafkaPackets);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		void onGarbageCollecting(Poco::Timer &timer);
 | 
							bool GetHealthDevices(std::uint64_t lowLimit, std::uint64_t  highLimit, std::vector<std::string> & SerialNumbers);
 | 
				
			||||||
 | 
							bool ExtendedAttributes(const std::string &serialNumber, bool & hasGPS, std::uint64_t &Sanity,
 | 
				
			||||||
 | 
													std::double_t &MemoryUsed, std::double_t &Load, std::double_t &Temperature);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		inline void AverageDeviceStatistics(uint64_t &Connections, uint64_t &AverageConnectionTime,
 | 
							inline void AverageDeviceStatistics(uint64_t &Connections, uint64_t &AverageConnectionTime,
 | 
				
			||||||
											uint64_t &NumberOfConnectingDevices) const {
 | 
																uint64_t &NumberOfConnectingDevices) const {
 | 
				
			||||||
@@ -176,94 +175,60 @@ namespace OpenWifi {
 | 
				
			|||||||
			NumberOfConnectingDevices = NumberOfConnectingDevices_;
 | 
								NumberOfConnectingDevices = NumberOfConnectingDevices_;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							inline bool SendFrame(const std::string &SerialNumber, const std::string &Payload) const {
 | 
				
			||||||
 | 
								return SendFrame(Utils::SerialNumberToInt(SerialNumber), Payload);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		inline void AddRX(std::uint64_t bytes) {
 | 
							inline void AddRX(std::uint64_t bytes) {
 | 
				
			||||||
			std::lock_guard		G(StatsMutex_);
 | 
					 | 
				
			||||||
			RX_ += bytes;
 | 
								RX_ += bytes;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		inline void AddTX(std::uint64_t bytes) {
 | 
							inline void AddTX(std::uint64_t bytes) {
 | 
				
			||||||
			std::lock_guard		G(StatsMutex_);
 | 
					 | 
				
			||||||
			TX_ += bytes;
 | 
								TX_ += bytes;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		inline void GetTotalDataStatistics(std::uint64_t &TX, std::uint64_t &RX) const {
 | 
							inline void GetTotalDataStatistics(std::uint64_t &TX, std::uint64_t &RX) const {
 | 
				
			||||||
			std::lock_guard		G(StatsMutex_);
 | 
					 | 
				
			||||||
			TX = TX_;
 | 
								TX = TX_;
 | 
				
			||||||
			RX = RX_;
 | 
								RX = RX_;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		//	TOD: move to hash based map.
 | 
							bool KafkaDisableState() const { return KafkaDisableState_; }
 | 
				
			||||||
		inline bool GetHealthDevices(std::uint64_t lowLimit, std::uint64_t  highLimit, std::vector<std::string> & SerialNumbers) {
 | 
							bool KafkaDisableHealthChecks() const { return KafkaDisableHealthChecks_; }
 | 
				
			||||||
			std::lock_guard Lock(SessionMutex_);
 | 
					 | 
				
			||||||
			for(const auto &connection:Sessions_) {
 | 
					 | 
				
			||||||
				if(	connection.second->RawLastHealthcheck_.Sanity>=lowLimit 	&&
 | 
					 | 
				
			||||||
					connection.second->RawLastHealthcheck_.Sanity<=highLimit) {
 | 
					 | 
				
			||||||
					SerialNumbers.push_back(connection.second->SerialNumber_);
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			return true;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		inline bool ExtendedAttributes(const std::string &serialNumber,
 | 
					 | 
				
			||||||
			bool & hasGPS,
 | 
					 | 
				
			||||||
			std::uint64_t &Sanity,
 | 
					 | 
				
			||||||
			std::double_t &MemoryUsed,
 | 
					 | 
				
			||||||
			std::double_t &Load,
 | 
					 | 
				
			||||||
			std::double_t &Temperature
 | 
					 | 
				
			||||||
			) {
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			auto serialNumberInt = Utils::SerialNumberToInt(serialNumber);
 | 
					 | 
				
			||||||
			auto hashIndex = Utils::CalculateMacAddressHash(serialNumberInt);
 | 
					 | 
				
			||||||
			std::lock_guard	G(SerialNumbersMutex_[hashIndex]);
 | 
					 | 
				
			||||||
			auto session_hint = SerialNumbers_[hashIndex].find(Utils::SerialNumberToInt(serialNumber));
 | 
					 | 
				
			||||||
			if(session_hint==end(SerialNumbers_[hashIndex])) {
 | 
					 | 
				
			||||||
				return false;
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			hasGPS = session_hint->second.second->hasGPS;
 | 
					 | 
				
			||||||
			Sanity = session_hint->second.second->RawLastHealthcheck_.Sanity;
 | 
					 | 
				
			||||||
			MemoryUsed = session_hint->second.second->memory_used_;
 | 
					 | 
				
			||||||
			Load = session_hint->second.second->cpu_load_;
 | 
					 | 
				
			||||||
			Temperature = session_hint->second.second->temperature_;
 | 
					 | 
				
			||||||
			return true;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	  private:
 | 
						  private:
 | 
				
			||||||
		mutable std::mutex 			SessionMutex_;
 | 
							std::array<std::mutex,SessionHashMax> 			SessionMutex_;
 | 
				
			||||||
		mutable std::mutex			StatsMutex_;
 | 
							std::array<std::map<std::uint64_t, std::shared_ptr<AP_WS_Connection>>,SessionHashMax> Sessions_;
 | 
				
			||||||
 | 
							using SerialNumberMap = std::map<uint64_t /* serial number */,
 | 
				
			||||||
 | 
															 std::shared_ptr<AP_WS_Connection>>;
 | 
				
			||||||
 | 
							std::array<SerialNumberMap,MACHashMax>			SerialNumbers_;
 | 
				
			||||||
 | 
							mutable std::array<std::recursive_mutex,MACHashMax>		SerialNumbersMutex_;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		std::unique_ptr<Poco::Crypto::X509Certificate> IssuerCert_;
 | 
							std::unique_ptr<Poco::Crypto::X509Certificate> IssuerCert_;
 | 
				
			||||||
		std::list<std::unique_ptr<Poco::Net::HTTPServer>> WebServers_;
 | 
							std::list<std::unique_ptr<Poco::Net::HTTPServer>> WebServers_;
 | 
				
			||||||
 | 
							Poco::ThreadPool DeviceConnectionPool_{"ws:dev-pool", 4, 256};
 | 
				
			||||||
		Poco::Net::SocketReactor Reactor_;
 | 
							Poco::Net::SocketReactor Reactor_;
 | 
				
			||||||
		Poco::Thread ReactorThread_;
 | 
							Poco::Thread ReactorThread_;
 | 
				
			||||||
		std::string SimulatorId_;
 | 
							std::string SimulatorId_;
 | 
				
			||||||
		Poco::ThreadPool DeviceConnectionPool_{"ws:dev-pool", 2, 64};
 | 
					 | 
				
			||||||
		bool LookAtProvisioning_ = false;
 | 
							bool LookAtProvisioning_ = false;
 | 
				
			||||||
		bool UseDefaultConfig_ = true;
 | 
							bool UseDefaultConfig_ = true;
 | 
				
			||||||
		bool SimulatorEnabled_ = false;
 | 
							bool SimulatorEnabled_ = false;
 | 
				
			||||||
 | 
							bool AllowSerialNumberMismatch_ = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		std::unique_ptr<AP_WS_ReactorThreadPool> Reactor_pool_;
 | 
							std::unique_ptr<AP_WS_ReactorThreadPool> Reactor_pool_;
 | 
				
			||||||
		std::atomic_bool Running_ = false;
 | 
							std::atomic_bool Running_ = false;
 | 
				
			||||||
		std::map<std::uint64_t, std::shared_ptr<AP_WS_Connection>> Sessions_;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		using SerialNumberMap = std::map<uint64_t /* serial number */, std::pair<uint64_t /* session id*/,
 | 
					 | 
				
			||||||
									 std::shared_ptr<AP_WS_Connection>>>;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		std::array<SerialNumberMap,256>			SerialNumbers_;
 | 
					 | 
				
			||||||
		mutable std::array<std::mutex,256>		SerialNumbersMutex_;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		std::atomic_bool AllowSerialNumberMismatch_ = true;
 | 
					 | 
				
			||||||
		std::atomic_uint64_t MismatchDepth_ = 2;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							std::uint64_t 			MismatchDepth_ = 2;
 | 
				
			||||||
		std::uint64_t 			NumberOfConnectedDevices_ = 0;
 | 
							std::uint64_t 			NumberOfConnectedDevices_ = 0;
 | 
				
			||||||
		std::uint64_t 			AverageDeviceConnectionTime_ = 0;
 | 
							std::uint64_t 			AverageDeviceConnectionTime_ = 0;
 | 
				
			||||||
		std::uint64_t 			NumberOfConnectingDevices_ = 0;
 | 
							std::uint64_t 			NumberOfConnectingDevices_ = 0;
 | 
				
			||||||
		std::uint64_t 			SessionTimeOut_ = 10*60;
 | 
							std::uint64_t 			SessionTimeOut_ = 10*60;
 | 
				
			||||||
 | 
							std::uint64_t 			LeftOverSessions_ = 0;
 | 
				
			||||||
		std::atomic_uint64_t 	TX_=0,RX_=0;
 | 
							std::atomic_uint64_t 	TX_=0,RX_=0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		std::vector<std::shared_ptr<AP_WS_Connection>> Garbage_;
 | 
							std::atomic_bool 		KafkaDisableState_=false,
 | 
				
			||||||
 | 
											 		KafkaDisableHealthChecks_=false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		std::unique_ptr<Poco::TimerCallback<AP_WS_Server>> GarbageCollectorCallback_;
 | 
							Poco::Thread 			GarbageCollector_;
 | 
				
			||||||
		Poco::Timer Timer_;
 | 
					 | 
				
			||||||
		Poco::Thread GarbageCollector_;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		AP_WS_Server() noexcept
 | 
							AP_WS_Server() noexcept
 | 
				
			||||||
			: SubSystemServer("WebSocketServer", "WS-SVR", "ucentral.websocket") {}
 | 
								: SubSystemServer("WebSocketServer", "WS-SVR", "ucentral.websocket") {}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -45,11 +45,9 @@ namespace OpenWifi {
 | 
				
			|||||||
							std::lock_guard Lock(LocalMutex_);
 | 
												std::lock_guard Lock(LocalMutex_);
 | 
				
			||||||
							auto RPC = OutStandingRequests_.find(ID);
 | 
												auto RPC = OutStandingRequests_.find(ID);
 | 
				
			||||||
							if (RPC == OutStandingRequests_.end()) {
 | 
												if (RPC == OutStandingRequests_.end()) {
 | 
				
			||||||
								//								std::cout << __LINE__ << std::endl;
 | 
					 | 
				
			||||||
								poco_debug(Logger(), fmt::format("({}): RPC {} cannot be found.",
 | 
													poco_debug(Logger(), fmt::format("({}): RPC {} cannot be found.",
 | 
				
			||||||
																 SerialNumberStr, ID));
 | 
																					 SerialNumberStr, ID));
 | 
				
			||||||
							} else if (RPC->second.SerialNumber != Resp->SerialNumber_) {
 | 
												} else if (RPC->second.SerialNumber != Resp->SerialNumber_) {
 | 
				
			||||||
								//								std::cout << __LINE__ << std::endl;
 | 
					 | 
				
			||||||
								poco_debug(
 | 
													poco_debug(
 | 
				
			||||||
									Logger(),
 | 
														Logger(),
 | 
				
			||||||
									fmt::format("({}): RPC {} serial number mismatch {}!={}.",
 | 
														fmt::format("({}): RPC {} serial number mismatch {}!={}.",
 | 
				
			||||||
@@ -60,7 +58,6 @@ namespace OpenWifi {
 | 
				
			|||||||
								std::chrono::duration<double, std::milli> rpc_execution_time =
 | 
													std::chrono::duration<double, std::milli> rpc_execution_time =
 | 
				
			||||||
									std::chrono::high_resolution_clock::now() -
 | 
														std::chrono::high_resolution_clock::now() -
 | 
				
			||||||
									RPC->second.submitted;
 | 
														RPC->second.submitted;
 | 
				
			||||||
								//								std::cout << __LINE__ << std::endl;
 | 
					 | 
				
			||||||
								poco_debug(Logger(),
 | 
													poco_debug(Logger(),
 | 
				
			||||||
										   fmt::format("({}): Received RPC answer {}. Command={}",
 | 
															   fmt::format("({}): Received RPC answer {}. Command={}",
 | 
				
			||||||
													   SerialNumberStr, ID,
 | 
																		   SerialNumberStr, ID,
 | 
				
			||||||
@@ -140,7 +137,6 @@ namespace OpenWifi {
 | 
				
			|||||||
				}
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		} else {
 | 
							} else {
 | 
				
			||||||
			//				std::cout << __LINE__ << std::endl;
 | 
					 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		Command.State = 0;
 | 
							Command.State = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -163,7 +159,6 @@ namespace OpenWifi {
 | 
				
			|||||||
		if (Command.rpc_entry) {
 | 
							if (Command.rpc_entry) {
 | 
				
			||||||
			TmpRpcEntry = Command.rpc_entry;
 | 
								TmpRpcEntry = Command.rpc_entry;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		//		std::cout << __LINE__ << "  State=" << Command.State << std::endl;
 | 
					 | 
				
			||||||
		if (Command.State == 2) {
 | 
							if (Command.State == 2) {
 | 
				
			||||||
			//	 look at the payload to see if we should continue or not...
 | 
								//	 look at the payload to see if we should continue or not...
 | 
				
			||||||
			if (Payload->has("result")) {
 | 
								if (Payload->has("result")) {
 | 
				
			||||||
@@ -173,12 +168,10 @@ namespace OpenWifi {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
					std::uint64_t Error = Status->get("error");
 | 
										std::uint64_t Error = Status->get("error");
 | 
				
			||||||
					if (Error == 0) {
 | 
										if (Error == 0) {
 | 
				
			||||||
						//						std::cout << __LINE__ << std::endl;
 | 
					 | 
				
			||||||
						StorageService()->CommandCompleted(Command.UUID, Payload,
 | 
											StorageService()->CommandCompleted(Command.UUID, Payload,
 | 
				
			||||||
														   rpc_execution_time, true);
 | 
																			   rpc_execution_time, true);
 | 
				
			||||||
						Command.State = 1;
 | 
											Command.State = 1;
 | 
				
			||||||
					} else {
 | 
										} else {
 | 
				
			||||||
						//						std::cout << __LINE__ << std::endl;
 | 
					 | 
				
			||||||
						StorageService()->CommandCompleted(Command.UUID, Payload,
 | 
											StorageService()->CommandCompleted(Command.UUID, Payload,
 | 
				
			||||||
														   rpc_execution_time, true);
 | 
																			   rpc_execution_time, true);
 | 
				
			||||||
						std::string ErrorTxt = Status->get("result");
 | 
											std::string ErrorTxt = Status->get("result");
 | 
				
			||||||
@@ -186,14 +179,11 @@ namespace OpenWifi {
 | 
				
			|||||||
						Command.State = 0;
 | 
											Command.State = 0;
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
				} else {
 | 
									} else {
 | 
				
			||||||
					//					std::cout << __LINE__ << std::endl;
 | 
					 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			} else {
 | 
								} else {
 | 
				
			||||||
				//				std::cout << __LINE__ << std::endl;
 | 
					 | 
				
			||||||
				Command.State = 0;
 | 
									Command.State = 0;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		} else if (Command.State == 1) {
 | 
							} else if (Command.State == 1) {
 | 
				
			||||||
			//			std::cout << "Completing script 2 phase commit." << std::endl;
 | 
					 | 
				
			||||||
			StorageService()->CommandCompleted(Command.UUID, Payload, rpc_execution_time, true);
 | 
								StorageService()->CommandCompleted(Command.UUID, Payload, rpc_execution_time, true);
 | 
				
			||||||
			if (Command.Deferred) {
 | 
								if (Command.Deferred) {
 | 
				
			||||||
				Reply = false;
 | 
									Reply = false;
 | 
				
			||||||
@@ -202,7 +192,6 @@ namespace OpenWifi {
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (Command.State == 0) {
 | 
							if (Command.State == 0) {
 | 
				
			||||||
			//			std::cout << __LINE__ << "  State=" << Command.State << std::endl;
 | 
					 | 
				
			||||||
			OutStandingRequests_.erase(Command.Id);
 | 
								OutStandingRequests_.erase(Command.Id);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		if (Reply && TmpRpcEntry != nullptr)
 | 
							if (Reply && TmpRpcEntry != nullptr)
 | 
				
			||||||
@@ -262,8 +251,6 @@ namespace OpenWifi {
 | 
				
			|||||||
		for (auto request = OutStandingRequests_.begin(); request != OutStandingRequests_.end();) {
 | 
							for (auto request = OutStandingRequests_.begin(); request != OutStandingRequests_.end();) {
 | 
				
			||||||
			std::chrono::duration<double, std::milli> delta = now - request->second.submitted;
 | 
								std::chrono::duration<double, std::milli> delta = now - request->second.submitted;
 | 
				
			||||||
			if (delta > 10min) {
 | 
								if (delta > 10min) {
 | 
				
			||||||
				//				std::cout << __LINE__ << "  -->> " << request->second.Id <<
 | 
					 | 
				
			||||||
				// std::endl;
 | 
					 | 
				
			||||||
				MyLogger.debug(fmt::format("{}: Command={} for {} Timed out.", request->second.UUID,
 | 
									MyLogger.debug(fmt::format("{}: Command={} for {} Timed out.", request->second.UUID,
 | 
				
			||||||
										   APCommands::to_string(request->second.Command),
 | 
															   APCommands::to_string(request->second.Command),
 | 
				
			||||||
										   Utils::IntToSerialNumber(request->second.SerialNumber)));
 | 
															   Utils::IntToSerialNumber(request->second.SerialNumber)));
 | 
				
			||||||
@@ -275,8 +262,6 @@ namespace OpenWifi {
 | 
				
			|||||||
				StorageService()->SetCommandTimedOut(request->second.UUID);
 | 
									StorageService()->SetCommandTimedOut(request->second.UUID);
 | 
				
			||||||
				request = OutStandingRequests_.erase(request);
 | 
									request = OutStandingRequests_.erase(request);
 | 
				
			||||||
			} else {
 | 
								} else {
 | 
				
			||||||
				//				std::cout << __LINE__ << "  -->> " << request->second.Id <<
 | 
					 | 
				
			||||||
				// std::endl;
 | 
					 | 
				
			||||||
				++request;
 | 
									++request;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -21,7 +21,6 @@ namespace OpenWifi {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	void DeviceDashboard::Generate(GWObjects::Dashboard &D, Poco::Logger &Logger) {
 | 
						void DeviceDashboard::Generate(GWObjects::Dashboard &D, Poco::Logger &Logger) {
 | 
				
			||||||
		if (GeneratingDashboard_.load()) {
 | 
							if (GeneratingDashboard_.load()) {
 | 
				
			||||||
			// std::cout << "Trying to generate dashboard but already being generated" << std::endl;
 | 
					 | 
				
			||||||
			while (GeneratingDashboard_.load()) {
 | 
								while (GeneratingDashboard_.load()) {
 | 
				
			||||||
				Poco::Thread::trySleep(100);
 | 
									Poco::Thread::trySleep(100);
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
@@ -31,7 +30,6 @@ namespace OpenWifi {
 | 
				
			|||||||
			GeneratingDashboard_ = true;
 | 
								GeneratingDashboard_ = true;
 | 
				
			||||||
			ValidDashboard_ = false;
 | 
								ValidDashboard_ = false;
 | 
				
			||||||
			try {
 | 
								try {
 | 
				
			||||||
				// std::cout << "Generating dashboard." << std::endl;
 | 
					 | 
				
			||||||
				poco_information(Logger, "DASHBOARD: Generating a new dashboard.");
 | 
									poco_information(Logger, "DASHBOARD: Generating a new dashboard.");
 | 
				
			||||||
				GWObjects::Dashboard NewData;
 | 
									GWObjects::Dashboard NewData;
 | 
				
			||||||
				StorageService()->AnalyzeCommands(NewData.commands);
 | 
									StorageService()->AnalyzeCommands(NewData.commands);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1753,7 +1753,6 @@ namespace OpenWifi {
 | 
				
			|||||||
		nlohmann::json new_ie;
 | 
							nlohmann::json new_ie;
 | 
				
			||||||
		nlohmann::json content;
 | 
							nlohmann::json content;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// std::cout << BufferToHex(&data[0],data.size()) << std::endl;
 | 
					 | 
				
			||||||
		uint offset = 0;
 | 
							uint offset = 0;
 | 
				
			||||||
		auto sub_ie = data[offset++];
 | 
							auto sub_ie = data[offset++];
 | 
				
			||||||
		switch (sub_ie) {
 | 
							switch (sub_ie) {
 | 
				
			||||||
@@ -1788,7 +1787,6 @@ namespace OpenWifi {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
		try {
 | 
							try {
 | 
				
			||||||
			nlohmann::json D = nlohmann::json::parse(ofs.str());
 | 
								nlohmann::json D = nlohmann::json::parse(ofs.str());
 | 
				
			||||||
			// std::cout << "Start of parsing wifi" << std::endl;
 | 
					 | 
				
			||||||
			if (D.contains("status")) {
 | 
								if (D.contains("status")) {
 | 
				
			||||||
				auto Status = D["status"];
 | 
									auto Status = D["status"];
 | 
				
			||||||
				if (Status.contains("scan") && Status["scan"].is_array()) {
 | 
									if (Status.contains("scan") && Status["scan"].is_array()) {
 | 
				
			||||||
@@ -1803,8 +1801,6 @@ namespace OpenWifi {
 | 
				
			|||||||
									if (ie.contains("type") && ie.contains("data")) {
 | 
														if (ie.contains("type") && ie.contains("data")) {
 | 
				
			||||||
										uint64_t ie_type = ie["type"];
 | 
															uint64_t ie_type = ie["type"];
 | 
				
			||||||
										std::string ie_data = ie["data"];
 | 
															std::string ie_data = ie["data"];
 | 
				
			||||||
										// std::cout << "TYPE:" << ie_type << "  DATA:" << ie_data
 | 
					 | 
				
			||||||
										// << std::endl;
 | 
					 | 
				
			||||||
										auto data = Base64Decode2Vec(ie_data);
 | 
															auto data = Base64Decode2Vec(ie_data);
 | 
				
			||||||
										if (ie_type == ieee80211_eid::WLAN_EID_COUNTRY) {
 | 
															if (ie_type == ieee80211_eid::WLAN_EID_COUNTRY) {
 | 
				
			||||||
											new_ies.push_back(WFS_WLAN_EID_COUNTRY(data));
 | 
																new_ies.push_back(WFS_WLAN_EID_COUNTRY(data));
 | 
				
			||||||
@@ -1858,18 +1854,12 @@ namespace OpenWifi {
 | 
				
			|||||||
										} else if (ie_type == ieee80211_eid::WLAN_EID_EXTENSION) {
 | 
															} else if (ie_type == ieee80211_eid::WLAN_EID_EXTENSION) {
 | 
				
			||||||
											new_ies.push_back(WFS_WLAN_EID_EXTENSION(data));
 | 
																new_ies.push_back(WFS_WLAN_EID_EXTENSION(data));
 | 
				
			||||||
										} else {
 | 
															} else {
 | 
				
			||||||
											// std::cout
 | 
					 | 
				
			||||||
											//	<< "Skipping IE: no parsing available: " << ie_type
 | 
					 | 
				
			||||||
											//	<< std::endl;
 | 
					 | 
				
			||||||
											new_ies.push_back(ie);
 | 
																new_ies.push_back(ie);
 | 
				
			||||||
										}
 | 
															}
 | 
				
			||||||
									} else {
 | 
														} else {
 | 
				
			||||||
										// std::cout << "Skipping IE: no data and type" <<
 | 
					 | 
				
			||||||
										// std::endl;
 | 
					 | 
				
			||||||
										new_ies.push_back(ie);
 | 
															new_ies.push_back(ie);
 | 
				
			||||||
									}
 | 
														}
 | 
				
			||||||
								} catch (...) {
 | 
													} catch (...) {
 | 
				
			||||||
									// std::cout << "Skipping IE: exception" << std::endl;
 | 
					 | 
				
			||||||
									Logger.information(fmt::format("Error parsing IEs"));
 | 
														Logger.information(fmt::format("Error parsing IEs"));
 | 
				
			||||||
									new_ies.push_back(ie);
 | 
														new_ies.push_back(ie);
 | 
				
			||||||
								}
 | 
													}
 | 
				
			||||||
@@ -1877,7 +1867,6 @@ namespace OpenWifi {
 | 
				
			|||||||
							scan_entry["ies"] = new_ies;
 | 
												scan_entry["ies"] = new_ies;
 | 
				
			||||||
							ParsedScan.push_back(scan_entry);
 | 
												ParsedScan.push_back(scan_entry);
 | 
				
			||||||
						} else {
 | 
											} else {
 | 
				
			||||||
							// std::cout << "Skipping scan" << std::endl;
 | 
					 | 
				
			||||||
							ParsedScan.push_back(scan_entry);
 | 
												ParsedScan.push_back(scan_entry);
 | 
				
			||||||
						}
 | 
											}
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
@@ -1886,7 +1875,6 @@ namespace OpenWifi {
 | 
				
			|||||||
				}
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			Result << to_string(D);
 | 
								Result << to_string(D);
 | 
				
			||||||
			// std::cout << "End of parsing wifi" << std::endl;
 | 
					 | 
				
			||||||
			return true;
 | 
								return true;
 | 
				
			||||||
		} catch (const Poco::Exception &E) {
 | 
							} catch (const Poco::Exception &E) {
 | 
				
			||||||
			Logger.log(E);
 | 
								Logger.log(E);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -177,15 +177,6 @@ namespace OpenWifi {
 | 
				
			|||||||
		} else {
 | 
							} else {
 | 
				
			||||||
			session_hint->second->lastTransaction = Utils::Now();
 | 
								session_hint->second->lastTransaction = Utils::Now();
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
		if(ap_hint!=AccountingSessions_.end()) {
 | 
					 | 
				
			||||||
			std::cout << "Auth table:" << std::endl;
 | 
					 | 
				
			||||||
			for(const auto &session:ap_hint->second) {
 | 
					 | 
				
			||||||
				std::cout << Notification.SerialNumber_ << ":  Index: " << session.first << ": ID: " << session.second->accountingSessionId << "  MID:" << session.second->accountingMultiSessionId << std::endl;
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
*/
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	std::uint32_t GetUiInt32(const std::uint8_t *buf) {
 | 
						std::uint32_t GetUiInt32(const std::uint8_t *buf) {
 | 
				
			||||||
@@ -423,15 +414,15 @@ namespace OpenWifi {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	void RADIUSSessionTracker::DisconnectSession(const std::string &SerialNumber) {
 | 
						void RADIUSSessionTracker::DisconnectSession(const std::string &SerialNumber) {
 | 
				
			||||||
		poco_information(Logger(),fmt::format("{}: Disconnecting.", SerialNumber));
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		std::lock_guard		Guard(Mutex_);
 | 
							std::lock_guard		Guard(Mutex_);
 | 
				
			||||||
 | 
					 | 
				
			||||||
		auto hint = AccountingSessions_.find(SerialNumber);
 | 
							auto hint = AccountingSessions_.find(SerialNumber);
 | 
				
			||||||
		if(hint==end(AccountingSessions_)) {
 | 
							if(hint==end(AccountingSessions_)) {
 | 
				
			||||||
			return;
 | 
								return;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							poco_information(Logger(),fmt::format("{}: Disconnecting.", SerialNumber));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		//	we need to go through all sessions and send an accounting stop
 | 
							//	we need to go through all sessions and send an accounting stop
 | 
				
			||||||
		for(const auto &session:hint->second) {
 | 
							for(const auto &session:hint->second) {
 | 
				
			||||||
			poco_debug(Logger(), fmt::format("Stopping accounting for {}:{}", SerialNumber, session.first ));
 | 
								poco_debug(Logger(), fmt::format("Stopping accounting for {}:{}", SerialNumber, session.first ));
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -63,7 +63,7 @@ namespace OpenWifi {
 | 
				
			|||||||
		poco_debug(Logger(), fmt::format("BLACKLIST-POST: {}", D.serialNumber));
 | 
							poco_debug(Logger(), fmt::format("BLACKLIST-POST: {}", D.serialNumber));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		Poco::toLowerInPlace(D.serialNumber);
 | 
							Poco::toLowerInPlace(D.serialNumber);
 | 
				
			||||||
		if (StorageService()->IsBlackListed(D.serialNumber)) {
 | 
							if (StorageService()->IsBlackListed(Utils::MACToInt(D.serialNumber))) {
 | 
				
			||||||
			return BadRequest(RESTAPI::Errors::SerialNumberExists);
 | 
								return BadRequest(RESTAPI::Errors::SerialNumberExists);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -87,7 +87,7 @@ namespace OpenWifi {
 | 
				
			|||||||
			poco_debug(
 | 
								poco_debug(
 | 
				
			||||||
				Logger_,
 | 
									Logger_,
 | 
				
			||||||
				fmt::format(
 | 
									fmt::format(
 | 
				
			||||||
					"Command rtty TID={} can proceed. Identified as {} and RPCID as {}. thr_id={}",
 | 
										"Command RTTY TID={} can proceed. Identified as {} and RPCID as {}. thr_id={}",
 | 
				
			||||||
					TransactionId_, UUID, RPC, Poco::Thread::current()->id()));
 | 
										TransactionId_, UUID, RPC, Poco::Thread::current()->id()));
 | 
				
			||||||
			return Rtty(UUID, RPC, 60000ms, Restrictions);
 | 
								return Rtty(UUID, RPC, 60000ms, Restrictions);
 | 
				
			||||||
		};
 | 
							};
 | 
				
			||||||
@@ -1169,7 +1169,7 @@ namespace OpenWifi {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
				if (RTTYS_server()->UseInternal()) {
 | 
									if (RTTYS_server()->UseInternal()) {
 | 
				
			||||||
					std::uint64_t SN = Utils::SerialNumberToInt(SerialNumber_);
 | 
										std::uint64_t SN = Utils::SerialNumberToInt(SerialNumber_);
 | 
				
			||||||
					bool mTLS = AP_WS_Server()->DeviceRequiresSecureRtty(SN);
 | 
										bool mTLS = AP_WS_Server()->DeviceRequiresSecureRTTY(SN);
 | 
				
			||||||
					auto Hash =  Utils::ComputeHash(UserInfo_.webtoken.refresh_token_, Utils::Now());
 | 
										auto Hash =  Utils::ComputeHash(UserInfo_.webtoken.refresh_token_, Utils::Now());
 | 
				
			||||||
					Rtty.Token = Hash.substr(0, RTTY_DEVICE_TOKEN_LENGTH);
 | 
										Rtty.Token = Hash.substr(0, RTTY_DEVICE_TOKEN_LENGTH);
 | 
				
			||||||
					if (!RTTYS_server()->CreateEndPoint(Rtty.ConnectionId, Rtty.Token, Requester(),
 | 
										if (!RTTYS_server()->CreateEndPoint(Rtty.ConnectionId, Rtty.Token, Requester(),
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -175,10 +175,12 @@ namespace OpenWifi {
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if(GetBoolParameter("simulatedDevices",false)) {
 | 
							if(GetBoolParameter("simulatedDevices",false)) {
 | 
				
			||||||
			if(StorageService()->DeleteSimulatedDevice("")) {
 | 
								auto F = []() ->void {
 | 
				
			||||||
				return OK();
 | 
									StorageService()->DeleteSimulatedDevice("");
 | 
				
			||||||
			}
 | 
								};
 | 
				
			||||||
			return NotFound();
 | 
								std::thread T(F);
 | 
				
			||||||
 | 
								T.detach();
 | 
				
			||||||
 | 
								return OK();
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if(!QB_.Select.empty() && !Utils::ValidSerialNumbers(QB_.Select)) {
 | 
							if(!QB_.Select.empty() && !Utils::ValidSerialNumbers(QB_.Select)) {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -16,6 +16,22 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
namespace OpenWifi {
 | 
					namespace OpenWifi {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						class LockedDbSession {
 | 
				
			||||||
 | 
						  public:
 | 
				
			||||||
 | 
							explicit LockedDbSession();
 | 
				
			||||||
 | 
							~LockedDbSession() = default;
 | 
				
			||||||
 | 
							inline std::mutex &Mutex() { return *Mutex_; };
 | 
				
			||||||
 | 
							inline Poco::Data::Session &Session() {
 | 
				
			||||||
 | 
								if(!Session_->isConnected()) {
 | 
				
			||||||
 | 
									Session_->reconnect();
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								return *Session_;
 | 
				
			||||||
 | 
							};
 | 
				
			||||||
 | 
						  private:
 | 
				
			||||||
 | 
							std::shared_ptr<Poco::Data::Session> 	Session_;
 | 
				
			||||||
 | 
							std::shared_ptr<std::mutex> 			Mutex_;
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	class Storage : public StorageClass {
 | 
						class Storage : public StorageClass {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	  public:
 | 
						  public:
 | 
				
			||||||
@@ -90,7 +106,8 @@ namespace OpenWifi {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
		// typedef std::map<std::string,std::string>	DeviceCapabilitiesCache;
 | 
							// typedef std::map<std::string,std::string>	DeviceCapabilitiesCache;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		bool AddLog(const GWObjects::DeviceLog &Log);
 | 
							bool AddLog(LockedDbSession &Session, const GWObjects::DeviceLog &Log);
 | 
				
			||||||
 | 
							bool AddStatisticsData(Poco::Data::Session &Session, const GWObjects::Statistics &Stats);
 | 
				
			||||||
		bool AddStatisticsData(const GWObjects::Statistics &Stats);
 | 
							bool AddStatisticsData(const GWObjects::Statistics &Stats);
 | 
				
			||||||
		bool GetStatisticsData(std::string &SerialNumber, uint64_t FromDate, uint64_t ToDate,
 | 
							bool GetStatisticsData(std::string &SerialNumber, uint64_t FromDate, uint64_t ToDate,
 | 
				
			||||||
							   uint64_t Offset, uint64_t HowMany,
 | 
												   uint64_t Offset, uint64_t HowMany,
 | 
				
			||||||
@@ -102,6 +119,7 @@ namespace OpenWifi {
 | 
				
			|||||||
									 std::vector<GWObjects::Statistics> &Stats);
 | 
														 std::vector<GWObjects::Statistics> &Stats);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		bool AddHealthCheckData(const GWObjects::HealthCheck &Check);
 | 
							bool AddHealthCheckData(const GWObjects::HealthCheck &Check);
 | 
				
			||||||
 | 
							bool AddHealthCheckData(LockedDbSession &Session, const GWObjects::HealthCheck &Check);
 | 
				
			||||||
		bool GetHealthCheckData(std::string &SerialNumber, uint64_t FromDate, uint64_t ToDate,
 | 
							bool GetHealthCheckData(std::string &SerialNumber, uint64_t FromDate, uint64_t ToDate,
 | 
				
			||||||
								uint64_t Offset, uint64_t HowMany,
 | 
													uint64_t Offset, uint64_t HowMany,
 | 
				
			||||||
								std::vector<GWObjects::HealthCheck> &Checks);
 | 
													std::vector<GWObjects::HealthCheck> &Checks);
 | 
				
			||||||
@@ -115,13 +133,18 @@ namespace OpenWifi {
 | 
				
			|||||||
									   uint64_t &NewUUID);
 | 
														   uint64_t &NewUUID);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		bool RollbackDeviceConfigurationChange(std::string & SerialNumber);
 | 
							bool RollbackDeviceConfigurationChange(std::string & SerialNumber);
 | 
				
			||||||
 | 
							bool CompleteDeviceConfigurationChange(Poco::Data::Session &Session, std::string & SerialNumber);
 | 
				
			||||||
		bool CompleteDeviceConfigurationChange(std::string & SerialNumber);
 | 
							bool CompleteDeviceConfigurationChange(std::string & SerialNumber);
 | 
				
			||||||
 | 
							bool CreateDevice(LockedDbSession &Session, GWObjects::Device &);
 | 
				
			||||||
		bool CreateDevice(GWObjects::Device &);
 | 
							bool CreateDevice(GWObjects::Device &);
 | 
				
			||||||
		bool CreateDefaultDevice(std::string &SerialNumber, const Config::Capabilities &Caps,
 | 
							bool CreateDefaultDevice(Poco::Data::Session &Session,std::string &SerialNumber,
 | 
				
			||||||
 | 
													 const Config::Capabilities &Caps,
 | 
				
			||||||
								 std::string &Firmware, const Poco::Net::IPAddress &IPAddress,
 | 
													 std::string &Firmware, const Poco::Net::IPAddress &IPAddress,
 | 
				
			||||||
								 bool simulated);
 | 
													 bool simulated);
 | 
				
			||||||
 | 
							bool CreateDevice(Poco::Data::Session &Sess, GWObjects::Device &DeviceDetails);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							bool GetDevice(LockedDbSession &Session, std::string &SerialNumber, GWObjects::Device &);
 | 
				
			||||||
 | 
							bool GetDevice(Poco::Data::Session &Session, std::string &SerialNumber, GWObjects::Device &DeviceDetails);
 | 
				
			||||||
		bool GetDevice(std::string &SerialNumber, GWObjects::Device &);
 | 
							bool GetDevice(std::string &SerialNumber, GWObjects::Device &);
 | 
				
			||||||
		bool GetDevices(uint64_t From, uint64_t HowMany, std::vector<GWObjects::Device> &Devices,
 | 
							bool GetDevices(uint64_t From, uint64_t HowMany, std::vector<GWObjects::Device> &Devices,
 | 
				
			||||||
						const std::string &orderBy = "");
 | 
											const std::string &orderBy = "");
 | 
				
			||||||
@@ -132,6 +155,8 @@ namespace OpenWifi {
 | 
				
			|||||||
		bool DeleteDevices(std::uint64_t OlderContact, bool SimulatedOnly);
 | 
							bool DeleteDevices(std::uint64_t OlderContact, bool SimulatedOnly);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		bool UpdateDevice(GWObjects::Device &);
 | 
							bool UpdateDevice(GWObjects::Device &);
 | 
				
			||||||
 | 
							bool UpdateDevice(LockedDbSession &Session, GWObjects::Device &);
 | 
				
			||||||
 | 
							bool UpdateDevice(Poco::Data::Session &Sess, GWObjects::Device &NewDeviceDetails);
 | 
				
			||||||
		bool DeviceExists(std::string &SerialNumber);
 | 
							bool DeviceExists(std::string &SerialNumber);
 | 
				
			||||||
		bool SetConnectInfo(std::string &SerialNumber, std::string &Firmware);
 | 
							bool SetConnectInfo(std::string &SerialNumber, std::string &Firmware);
 | 
				
			||||||
		bool GetDeviceCount(uint64_t &Count);
 | 
							bool GetDeviceCount(uint64_t &Count);
 | 
				
			||||||
@@ -139,7 +164,7 @@ namespace OpenWifi {
 | 
				
			|||||||
									std::vector<std::string> &SerialNumbers,
 | 
														std::vector<std::string> &SerialNumbers,
 | 
				
			||||||
									const std::string &orderBy = "");
 | 
														const std::string &orderBy = "");
 | 
				
			||||||
		bool GetDeviceFWUpdatePolicy(std::string &SerialNumber, std::string &Policy);
 | 
							bool GetDeviceFWUpdatePolicy(std::string &SerialNumber, std::string &Policy);
 | 
				
			||||||
		bool SetDevicePassword(std::string &SerialNumber, std::string &Password);
 | 
							bool SetDevicePassword(LockedDbSession &Session, std::string &SerialNumber, std::string &Password);
 | 
				
			||||||
		bool UpdateSerialNumberCache();
 | 
							bool UpdateSerialNumberCache();
 | 
				
			||||||
		static void GetDeviceDbFieldList(Types::StringVec &Fields);
 | 
							static void GetDeviceDbFieldList(Types::StringVec &Fields);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -148,9 +173,11 @@ namespace OpenWifi {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
		bool UpdateDeviceCapabilities(std::string &SerialNumber,
 | 
							bool UpdateDeviceCapabilities(std::string &SerialNumber,
 | 
				
			||||||
									  const Config::Capabilities &Capabilities);
 | 
														  const Config::Capabilities &Capabilities);
 | 
				
			||||||
 | 
							bool UpdateDeviceCapabilities(Poco::Data::Session &Session, std::string &SerialNumber,
 | 
				
			||||||
 | 
														  const Config::Capabilities &Capabilities);
 | 
				
			||||||
		bool GetDeviceCapabilities(std::string &SerialNumber, GWObjects::Capabilities &);
 | 
							bool GetDeviceCapabilities(std::string &SerialNumber, GWObjects::Capabilities &);
 | 
				
			||||||
		bool DeleteDeviceCapabilities(std::string &SerialNumber);
 | 
							bool DeleteDeviceCapabilities(std::string &SerialNumber);
 | 
				
			||||||
		bool CreateDeviceCapabilities(std::string &SerialNumber,
 | 
							bool CreateDeviceCapabilities(Poco::Data::Session &Session, std::string &SerialNumber,
 | 
				
			||||||
									  const Config::Capabilities &Capabilities);
 | 
														  const Config::Capabilities &Capabilities);
 | 
				
			||||||
		bool InitCapabilitiesCache();
 | 
							bool InitCapabilitiesCache();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -222,15 +249,15 @@ namespace OpenWifi {
 | 
				
			|||||||
		void RemovedExpiredCommands();
 | 
							void RemovedExpiredCommands();
 | 
				
			||||||
		void RemoveTimedOutCommands();
 | 
							void RemoveTimedOutCommands();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		bool RemoveOldCommands(std::string &SerilNumber, std::string &Command);
 | 
							bool RemoveOldCommands(std::string &SerialNumber, std::string &Command);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		bool AddBlackListDevices(std::vector<GWObjects::BlackListedDevice> &Devices);
 | 
							bool AddBlackListDevices(std::vector<GWObjects::BlackListedDevice> &Devices);
 | 
				
			||||||
		bool AddBlackListDevice(GWObjects::BlackListedDevice &Device);
 | 
							bool AddBlackListDevice(GWObjects::BlackListedDevice &Device);
 | 
				
			||||||
		bool GetBlackListDevice(std::string &SerialNumber, GWObjects::BlackListedDevice &Device);
 | 
							bool GetBlackListDevice(std::string &SerialNumber, GWObjects::BlackListedDevice &Device);
 | 
				
			||||||
		bool DeleteBlackListDevice(std::string &SerialNumber);
 | 
							bool DeleteBlackListDevice(std::string &SerialNumber);
 | 
				
			||||||
		bool IsBlackListed(const std::string &SerialNumber, std::string &reason,
 | 
							bool IsBlackListed(std::uint64_t SerialNumber, std::string &reason,
 | 
				
			||||||
						   std::string &author, std::uint64_t &created);
 | 
											   std::string &author, std::uint64_t &created);
 | 
				
			||||||
		bool IsBlackListed(const std::string &SerialNumber);
 | 
							bool IsBlackListed(std::uint64_t SerialNumber);
 | 
				
			||||||
		bool InitializeBlackListCache();
 | 
							bool InitializeBlackListCache();
 | 
				
			||||||
		bool GetBlackListDevices(uint64_t Offset, uint64_t HowMany,
 | 
							bool GetBlackListDevices(uint64_t Offset, uint64_t HowMany,
 | 
				
			||||||
								 std::vector<GWObjects::BlackListedDevice> &Devices);
 | 
													 std::vector<GWObjects::BlackListedDevice> &Devices);
 | 
				
			||||||
@@ -245,7 +272,9 @@ namespace OpenWifi {
 | 
				
			|||||||
		bool RemoveCommandListRecordsOlderThan(uint64_t Date);
 | 
							bool RemoveCommandListRecordsOlderThan(uint64_t Date);
 | 
				
			||||||
		bool RemoveUploadedFilesRecordsOlderThan(uint64_t Date);
 | 
							bool RemoveUploadedFilesRecordsOlderThan(uint64_t Date);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		bool SetDeviceLastRecordedContact(std::string & SeialNumber, std::uint64_t lastRecordedContact);
 | 
							bool SetDeviceLastRecordedContact(LockedDbSession &Session, std::string & SerialNumber, std::uint64_t lastRecordedContact);
 | 
				
			||||||
 | 
							bool SetDeviceLastRecordedContact(std::string & SerialNumber, std::uint64_t lastRecordedContact);
 | 
				
			||||||
 | 
							bool SetDeviceLastRecordedContact(Poco::Data::Session & Session, std::string & SerialNumber, std::uint64_t lastRecordedContact);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		int Create_Tables();
 | 
							int Create_Tables();
 | 
				
			||||||
		int Create_Statistics();
 | 
							int Create_Statistics();
 | 
				
			||||||
@@ -265,10 +294,19 @@ namespace OpenWifi {
 | 
				
			|||||||
		int Start() override;
 | 
							int Start() override;
 | 
				
			||||||
		void Stop() override;
 | 
							void Stop() override;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							inline Poco::Data::Session	StartSession() {
 | 
				
			||||||
 | 
								return Pool_->get();
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	  private:
 | 
						  private:
 | 
				
			||||||
		std::unique_ptr<OpenWifi::ScriptDB> ScriptDB_;
 | 
							std::unique_ptr<OpenWifi::ScriptDB> ScriptDB_;
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	inline auto StorageService() { return Storage::instance(); }
 | 
						inline auto StorageService() { return Storage::instance(); }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						inline LockedDbSession::LockedDbSession() {
 | 
				
			||||||
 | 
							Session_ = std::make_shared<Poco::Data::Session>(Poco::Data::Session(StorageService()->StartSession()));
 | 
				
			||||||
 | 
							Mutex_ = std::make_shared<std::mutex>();
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
} // namespace OpenWifi
 | 
					} // namespace OpenWifi
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -23,7 +23,7 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#include "framework/SubSystemServer.h"
 | 
					#include "framework/SubSystemServer.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "AP_WS_ReactorPool.h"
 | 
					#include "AP_WS_Reactor_Pool.h"
 | 
				
			||||||
#include "TelemetryClient.h"
 | 
					#include "TelemetryClient.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace OpenWifi {
 | 
					namespace OpenWifi {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -9,8 +9,6 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
namespace OpenWifi {
 | 
					namespace OpenWifi {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	EventBusManager::EventBusManager(Poco::Logger &L) : Logger_(L) {}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	void EventBusManager::run() {
 | 
						void EventBusManager::run() {
 | 
				
			||||||
		Running_ = true;
 | 
							Running_ = true;
 | 
				
			||||||
		Utils::SetThreadName("fmwk:EventMgr");
 | 
							Utils::SetThreadName("fmwk:EventMgr");
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -12,6 +12,16 @@ namespace OpenWifi {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	class EventBusManager : public Poco::Runnable {
 | 
						class EventBusManager : public Poco::Runnable {
 | 
				
			||||||
	  public:
 | 
						  public:
 | 
				
			||||||
 | 
							EventBusManager() :
 | 
				
			||||||
 | 
								Logger_(Poco::Logger::create(
 | 
				
			||||||
 | 
									"EventBusManager", Poco::Logger::root().getChannel(), Poco::Logger::root().getLevel())) {
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							static auto instance() {
 | 
				
			||||||
 | 
								static auto instance_ = new EventBusManager;
 | 
				
			||||||
 | 
								return instance_;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		explicit EventBusManager(Poco::Logger &L);
 | 
							explicit EventBusManager(Poco::Logger &L);
 | 
				
			||||||
		void run() final;
 | 
							void run() final;
 | 
				
			||||||
		void Start();
 | 
							void Start();
 | 
				
			||||||
@@ -24,4 +34,6 @@ namespace OpenWifi {
 | 
				
			|||||||
		Poco::Logger &Logger_;
 | 
							Poco::Logger &Logger_;
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						inline auto EventBusManager() { return EventBusManager::instance(); }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
} // namespace OpenWifi
 | 
					} // namespace OpenWifi
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -33,9 +33,23 @@ namespace OpenWifi {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	void MicroService::Exit(int Reason) { std::exit(Reason); }
 | 
						void MicroService::Exit(int Reason) { std::exit(Reason); }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    static std::string MakeServiceListString(const Types::MicroServiceMetaMap &Services) {
 | 
				
			||||||
 | 
					        std::string SvcList;
 | 
				
			||||||
 | 
					        for (const auto &Svc : Services) {
 | 
				
			||||||
 | 
					            if (SvcList.empty())
 | 
				
			||||||
 | 
					                SvcList = Svc.second.Type;
 | 
				
			||||||
 | 
					            else
 | 
				
			||||||
 | 
					                SvcList += ", " + Svc.second.Type;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return SvcList;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	void MicroService::BusMessageReceived([[maybe_unused]] const std::string &Key,
 | 
						void MicroService::BusMessageReceived([[maybe_unused]] const std::string &Key,
 | 
				
			||||||
										  const std::string &Payload) {
 | 
															  const std::string &Payload) {
 | 
				
			||||||
		std::lock_guard G(InfraMutex_);
 | 
							std::lock_guard G(InfraMutex_);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							Poco::Logger &BusLogger = EventBusManager()->Logger();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		try {
 | 
							try {
 | 
				
			||||||
			Poco::JSON::Parser P;
 | 
								Poco::JSON::Parser P;
 | 
				
			||||||
			auto Object = P.parse(Payload).extract<Poco::JSON::Object::Ptr>();
 | 
								auto Object = P.parse(Payload).extract<Poco::JSON::Object::Ptr>();
 | 
				
			||||||
@@ -55,13 +69,10 @@ namespace OpenWifi {
 | 
				
			|||||||
							Object->has(KafkaTopics::ServiceEvents::Fields::KEY)) {
 | 
												Object->has(KafkaTopics::ServiceEvents::Fields::KEY)) {
 | 
				
			||||||
							auto PrivateEndPoint =
 | 
												auto PrivateEndPoint =
 | 
				
			||||||
								Object->get(KafkaTopics::ServiceEvents::Fields::PRIVATE).toString();
 | 
													Object->get(KafkaTopics::ServiceEvents::Fields::PRIVATE).toString();
 | 
				
			||||||
							if (Event == KafkaTopics::ServiceEvents::EVENT_KEEP_ALIVE &&
 | 
												if (Event == KafkaTopics::ServiceEvents::EVENT_LEAVE) {
 | 
				
			||||||
								Services_.find(PrivateEndPoint) != Services_.end()) {
 | 
					 | 
				
			||||||
								Services_[PrivateEndPoint].LastUpdate = Utils::Now();
 | 
					 | 
				
			||||||
							} else if (Event == KafkaTopics::ServiceEvents::EVENT_LEAVE) {
 | 
					 | 
				
			||||||
								Services_.erase(PrivateEndPoint);
 | 
													Services_.erase(PrivateEndPoint);
 | 
				
			||||||
								poco_debug(
 | 
													poco_information(
 | 
				
			||||||
									logger(),
 | 
														BusLogger,
 | 
				
			||||||
									fmt::format(
 | 
														fmt::format(
 | 
				
			||||||
										"Service {} ID={} leaving system.",
 | 
															"Service {} ID={} leaving system.",
 | 
				
			||||||
										Object->get(KafkaTopics::ServiceEvents::Fields::PRIVATE)
 | 
															Object->get(KafkaTopics::ServiceEvents::Fields::PRIVATE)
 | 
				
			||||||
@@ -69,14 +80,7 @@ namespace OpenWifi {
 | 
				
			|||||||
										ID));
 | 
															ID));
 | 
				
			||||||
							} else if (Event == KafkaTopics::ServiceEvents::EVENT_JOIN ||
 | 
												} else if (Event == KafkaTopics::ServiceEvents::EVENT_JOIN ||
 | 
				
			||||||
									   Event == KafkaTopics::ServiceEvents::EVENT_KEEP_ALIVE) {
 | 
														   Event == KafkaTopics::ServiceEvents::EVENT_KEEP_ALIVE) {
 | 
				
			||||||
								poco_debug(
 | 
													auto ServiceInfo = Types::MicroServiceMeta{
 | 
				
			||||||
									logger(),
 | 
					 | 
				
			||||||
									fmt::format(
 | 
					 | 
				
			||||||
										"Service {} ID={} joining system.",
 | 
					 | 
				
			||||||
										Object->get(KafkaTopics::ServiceEvents::Fields::PRIVATE)
 | 
					 | 
				
			||||||
											.toString(),
 | 
					 | 
				
			||||||
										ID));
 | 
					 | 
				
			||||||
								Services_[PrivateEndPoint] = Types::MicroServiceMeta{
 | 
					 | 
				
			||||||
									.Id = ID,
 | 
														.Id = ID,
 | 
				
			||||||
									.Type = Poco::toLower(
 | 
														.Type = Poco::toLower(
 | 
				
			||||||
										Object->get(KafkaTopics::ServiceEvents::Fields::TYPE)
 | 
															Object->get(KafkaTopics::ServiceEvents::Fields::TYPE)
 | 
				
			||||||
@@ -94,20 +98,46 @@ namespace OpenWifi {
 | 
				
			|||||||
												   .toString(),
 | 
																	   .toString(),
 | 
				
			||||||
									.LastUpdate = Utils::Now()};
 | 
														.LastUpdate = Utils::Now()};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
								std::string SvcList;
 | 
					                                auto s1 = MakeServiceListString(Services_);
 | 
				
			||||||
								for (const auto &Svc : Services_) {
 | 
													auto PreviousSize = Services_.size();
 | 
				
			||||||
									if (SvcList.empty())
 | 
													Services_[PrivateEndPoint] = ServiceInfo;
 | 
				
			||||||
										SvcList = Svc.second.Type;
 | 
													auto CurrentSize = Services_.size();
 | 
				
			||||||
									else
 | 
													if(Event == KafkaTopics::ServiceEvents::EVENT_JOIN) {
 | 
				
			||||||
										SvcList += ", " + Svc.second.Type;
 | 
														if(!s1.empty()) {
 | 
				
			||||||
 | 
															poco_information(
 | 
				
			||||||
 | 
																BusLogger,
 | 
				
			||||||
 | 
																fmt::format(
 | 
				
			||||||
 | 
																	"Service {} ID={} is joining the system.",
 | 
				
			||||||
 | 
																	Object
 | 
				
			||||||
 | 
																		->get(
 | 
				
			||||||
 | 
																			KafkaTopics::ServiceEvents::Fields::PRIVATE)
 | 
				
			||||||
 | 
																		.toString(),
 | 
				
			||||||
 | 
																	ID));
 | 
				
			||||||
 | 
														}
 | 
				
			||||||
 | 
														std::string SvcList;
 | 
				
			||||||
 | 
														for (const auto &Svc : Services_) {
 | 
				
			||||||
 | 
															if (SvcList.empty())
 | 
				
			||||||
 | 
																SvcList = Svc.second.Type;
 | 
				
			||||||
 | 
															else
 | 
				
			||||||
 | 
																SvcList += ", " + Svc.second.Type;
 | 
				
			||||||
 | 
														}
 | 
				
			||||||
 | 
														poco_information(
 | 
				
			||||||
 | 
															BusLogger,
 | 
				
			||||||
 | 
															fmt::format("Current list of microservices: {}", SvcList));
 | 
				
			||||||
 | 
													} else if(CurrentSize!=PreviousSize) {
 | 
				
			||||||
 | 
														poco_information(
 | 
				
			||||||
 | 
															BusLogger,
 | 
				
			||||||
 | 
															fmt::format(
 | 
				
			||||||
 | 
																"Service {} ID={} is being added back in.",
 | 
				
			||||||
 | 
																Object
 | 
				
			||||||
 | 
																	->get(KafkaTopics::ServiceEvents::Fields::PRIVATE)
 | 
				
			||||||
 | 
																	.toString(),
 | 
				
			||||||
 | 
																ID));
 | 
				
			||||||
								}
 | 
													}
 | 
				
			||||||
								poco_information(
 | 
					 | 
				
			||||||
									logger(),
 | 
					 | 
				
			||||||
									fmt::format("Current list of microservices: {}", SvcList));
 | 
					 | 
				
			||||||
							}
 | 
												}
 | 
				
			||||||
						} else {
 | 
											} else {
 | 
				
			||||||
							poco_error(
 | 
												poco_information(
 | 
				
			||||||
								logger(),
 | 
													BusLogger,
 | 
				
			||||||
								fmt::format("KAFKA-MSG: invalid event '{}', missing a field.",
 | 
													fmt::format("KAFKA-MSG: invalid event '{}', missing a field.",
 | 
				
			||||||
											Event));
 | 
																Event));
 | 
				
			||||||
						}
 | 
											}
 | 
				
			||||||
@@ -118,32 +148,39 @@ namespace OpenWifi {
 | 
				
			|||||||
								Object->get(KafkaTopics::ServiceEvents::Fields::TOKEN).toString());
 | 
													Object->get(KafkaTopics::ServiceEvents::Fields::TOKEN).toString());
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
						} else {
 | 
											} else {
 | 
				
			||||||
							poco_error(
 | 
												poco_information(
 | 
				
			||||||
								logger(),
 | 
													BusLogger,
 | 
				
			||||||
								fmt::format("KAFKA-MSG: invalid event '{}', missing token", Event));
 | 
													fmt::format("KAFKA-MSG: invalid event '{}', missing token", Event));
 | 
				
			||||||
						}
 | 
											}
 | 
				
			||||||
					} else {
 | 
										} else {
 | 
				
			||||||
						poco_error(logger(),
 | 
											poco_information(BusLogger,
 | 
				
			||||||
								   fmt::format("Unknown Event: {} Source: {}", Event, ID));
 | 
													   fmt::format("Unknown Event: {} Source: {}", Event, ID));
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			} else {
 | 
								} else {
 | 
				
			||||||
				poco_error(logger(), "Bad bus message.");
 | 
									std::ostringstream os;
 | 
				
			||||||
                std::ostringstream os;
 | 
									Object->stringify(std::cout);
 | 
				
			||||||
                Object->stringify(std::cout);
 | 
									poco_error(BusLogger, fmt::format("Bad bus message: {}", os.str()));
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			auto i = Services_.begin();
 | 
								auto ServiceHint = Services_.begin();
 | 
				
			||||||
			auto now = Utils::Now();
 | 
								auto now = Utils::Now();
 | 
				
			||||||
			for (; i != Services_.end();) {
 | 
					            auto si1 = Services_.size();
 | 
				
			||||||
				if ((now - i->second.LastUpdate) > 60) {
 | 
					            auto ss1 = MakeServiceListString(Services_);
 | 
				
			||||||
					i = Services_.erase(i);
 | 
								while(ServiceHint!=Services_.end()) {
 | 
				
			||||||
 | 
									if ((now - ServiceHint->second.LastUpdate) > 120) {
 | 
				
			||||||
 | 
										poco_information(BusLogger, fmt::format("ZombieService: Removing service {}, ", ServiceHint->second.PublicEndPoint));
 | 
				
			||||||
 | 
										ServiceHint = Services_.erase(ServiceHint);
 | 
				
			||||||
				} else
 | 
									} else
 | 
				
			||||||
					++i;
 | 
										++ServiceHint;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					            if(Services_.size() != si1) {
 | 
				
			||||||
 | 
					                auto ss2 = MakeServiceListString(Services_);
 | 
				
			||||||
 | 
					                poco_information(BusLogger, fmt::format("Current list of microservices: {} -> {}", ss1, ss2));
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		} catch (const Poco::Exception &E) {
 | 
							} catch (const Poco::Exception &E) {
 | 
				
			||||||
			logger().log(E);
 | 
								BusLogger.log(E);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -412,7 +449,7 @@ namespace OpenWifi {
 | 
				
			|||||||
			try {
 | 
								try {
 | 
				
			||||||
				DataDir.createDirectory();
 | 
									DataDir.createDirectory();
 | 
				
			||||||
			} catch (const Poco::Exception &E) {
 | 
								} catch (const Poco::Exception &E) {
 | 
				
			||||||
				logger().log(E);
 | 
									Logger_.log(E);
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		WWWAssetsDir_ = ConfigPath("openwifi.restapi.wwwassets", "");
 | 
							WWWAssetsDir_ = ConfigPath("openwifi.restapi.wwwassets", "");
 | 
				
			||||||
@@ -530,14 +567,12 @@ namespace OpenWifi {
 | 
				
			|||||||
		for (auto i : SubSystems_) {
 | 
							for (auto i : SubSystems_) {
 | 
				
			||||||
			i->Start();
 | 
								i->Start();
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		EventBusManager_ = std::make_unique<EventBusManager>(Poco::Logger::create(
 | 
							EventBusManager()->Start();
 | 
				
			||||||
			"EventBusManager", Poco::Logger::root().getChannel(), Poco::Logger::root().getLevel()));
 | 
					 | 
				
			||||||
		EventBusManager_->Start();
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	void MicroService::StopSubSystemServers() {
 | 
						void MicroService::StopSubSystemServers() {
 | 
				
			||||||
		AddActivity("Stopping");
 | 
							AddActivity("Stopping");
 | 
				
			||||||
		EventBusManager_->Stop();
 | 
							EventBusManager()->Stop();
 | 
				
			||||||
		for (auto i = SubSystems_.rbegin(); i != SubSystems_.rend(); ++i) {
 | 
							for (auto i = SubSystems_.rbegin(); i != SubSystems_.rend(); ++i) {
 | 
				
			||||||
			(*i)->Stop();
 | 
								(*i)->Stop();
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
@@ -697,7 +732,7 @@ namespace OpenWifi {
 | 
				
			|||||||
			auto APIKEY = Request.get("X-API-KEY");
 | 
								auto APIKEY = Request.get("X-API-KEY");
 | 
				
			||||||
			return APIKEY == MyHash_;
 | 
								return APIKEY == MyHash_;
 | 
				
			||||||
		} catch (const Poco::Exception &E) {
 | 
							} catch (const Poco::Exception &E) {
 | 
				
			||||||
			logger().log(E);
 | 
								Logger_.log(E);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		return false;
 | 
							return false;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -201,7 +201,6 @@ namespace OpenWifi {
 | 
				
			|||||||
		Poco::JWT::Signer Signer_;
 | 
							Poco::JWT::Signer Signer_;
 | 
				
			||||||
		Poco::Logger &Logger_;
 | 
							Poco::Logger &Logger_;
 | 
				
			||||||
		Poco::ThreadPool TimerPool_{"timer:pool", 2, 32};
 | 
							Poco::ThreadPool TimerPool_{"timer:pool", 2, 32};
 | 
				
			||||||
		std::unique_ptr<EventBusManager> EventBusManager_;
 | 
					 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	inline MicroService *MicroService::instance_ = nullptr;
 | 
						inline MicroService *MicroService::instance_ = nullptr;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -47,6 +47,8 @@ namespace OpenWifi {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							Poco::Data::SessionPool &Pool() { return *Pool_; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	  private:
 | 
						  private:
 | 
				
			||||||
		inline int Setup_SQLite();
 | 
							inline int Setup_SQLite();
 | 
				
			||||||
		inline int Setup_MySQL();
 | 
							inline int Setup_MySQL();
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -576,8 +576,8 @@ namespace ORM {
 | 
				
			|||||||
		bool UpdateRecord(field_name_t FieldName, const T &Value, const RecordType &R) {
 | 
							bool UpdateRecord(field_name_t FieldName, const T &Value, const RecordType &R) {
 | 
				
			||||||
			try {
 | 
								try {
 | 
				
			||||||
				assert(ValidFieldName(FieldName));
 | 
									assert(ValidFieldName(FieldName));
 | 
				
			||||||
 | 
					 | 
				
			||||||
				Poco::Data::Session Session = Pool_.get();
 | 
									Poco::Data::Session Session = Pool_.get();
 | 
				
			||||||
 | 
					                Session.begin();
 | 
				
			||||||
				Poco::Data::Statement Update(Session);
 | 
									Poco::Data::Statement Update(Session);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				RecordTuple RT;
 | 
									RecordTuple RT;
 | 
				
			||||||
@@ -593,6 +593,7 @@ namespace ORM {
 | 
				
			|||||||
				Update.execute();
 | 
									Update.execute();
 | 
				
			||||||
				if (Cache_)
 | 
									if (Cache_)
 | 
				
			||||||
					Cache_->UpdateCache(R);
 | 
										Cache_->UpdateCache(R);
 | 
				
			||||||
 | 
					                Session.commit();
 | 
				
			||||||
				return true;
 | 
									return true;
 | 
				
			||||||
			} catch (const Poco::Exception &E) {
 | 
								} catch (const Poco::Exception &E) {
 | 
				
			||||||
				Logger_.log(E);
 | 
									Logger_.log(E);
 | 
				
			||||||
@@ -662,6 +663,7 @@ namespace ORM {
 | 
				
			|||||||
				assert(ValidFieldName(FieldName));
 | 
									assert(ValidFieldName(FieldName));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				Poco::Data::Session Session = Pool_.get();
 | 
									Poco::Data::Session Session = Pool_.get();
 | 
				
			||||||
 | 
					                Session.begin();
 | 
				
			||||||
				Poco::Data::Statement Delete(Session);
 | 
									Poco::Data::Statement Delete(Session);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				std::string St = "delete from " + TableName_ + " where " + FieldName + "=?";
 | 
									std::string St = "delete from " + TableName_ + " where " + FieldName + "=?";
 | 
				
			||||||
@@ -671,6 +673,7 @@ namespace ORM {
 | 
				
			|||||||
				Delete.execute();
 | 
									Delete.execute();
 | 
				
			||||||
				if (Cache_)
 | 
									if (Cache_)
 | 
				
			||||||
					Cache_->Delete(FieldName, Value);
 | 
										Cache_->Delete(FieldName, Value);
 | 
				
			||||||
 | 
					                Session.commit();
 | 
				
			||||||
				return true;
 | 
									return true;
 | 
				
			||||||
			} catch (const Poco::Exception &E) {
 | 
								} catch (const Poco::Exception &E) {
 | 
				
			||||||
				Logger_.log(E);
 | 
									Logger_.log(E);
 | 
				
			||||||
@@ -682,11 +685,13 @@ namespace ORM {
 | 
				
			|||||||
			try {
 | 
								try {
 | 
				
			||||||
				assert(!WhereClause.empty());
 | 
									assert(!WhereClause.empty());
 | 
				
			||||||
				Poco::Data::Session Session = Pool_.get();
 | 
									Poco::Data::Session Session = Pool_.get();
 | 
				
			||||||
 | 
					                Session.begin();
 | 
				
			||||||
				Poco::Data::Statement Delete(Session);
 | 
									Poco::Data::Statement Delete(Session);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				std::string St = "delete from " + TableName_ + " where " + WhereClause;
 | 
									std::string St = "delete from " + TableName_ + " where " + WhereClause;
 | 
				
			||||||
				Delete << St;
 | 
									Delete << St;
 | 
				
			||||||
				Delete.execute();
 | 
									Delete.execute();
 | 
				
			||||||
 | 
					                Session.commit();
 | 
				
			||||||
				return true;
 | 
									return true;
 | 
				
			||||||
			} catch (const Poco::Exception &E) {
 | 
								} catch (const Poco::Exception &E) {
 | 
				
			||||||
				Logger_.log(E);
 | 
									Logger_.log(E);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -126,20 +126,6 @@ namespace OpenWifi::Utils {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	[[nodiscard]] std::uint64_t ConvertDate(const std::string &d);
 | 
						[[nodiscard]] std::uint64_t ConvertDate(const std::string &d);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	[[nodiscard]] inline uint8_t CalculateMacAddressHash(std::uint64_t value) {
 | 
					 | 
				
			||||||
		uint8_t hash = 0, i=6;
 | 
					 | 
				
			||||||
		while(i) {
 | 
					 | 
				
			||||||
			hash ^= (value & 0xFF) + 1;
 | 
					 | 
				
			||||||
			value >>= 8;
 | 
					 | 
				
			||||||
			--i;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		return hash;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	[[nodiscard]] inline uint8_t CalculateMacAddressHash(const std::string & value) {
 | 
					 | 
				
			||||||
		return CalculateMacAddressHash(MACToInt(value));
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	template <typename T> std::string int_to_hex(T i) {
 | 
						template <typename T> std::string int_to_hex(T i) {
 | 
				
			||||||
		std::stringstream stream;
 | 
							std::stringstream stream;
 | 
				
			||||||
		stream << std::setfill('0') << std::setw(12) << std::hex << i;
 | 
							stream << std::setfill('0') << std::setw(12) << std::hex << i;
 | 
				
			||||||
@@ -330,5 +316,90 @@ namespace OpenWifi::Utils {
 | 
				
			|||||||
        uint32_t        Port;
 | 
					        uint32_t        Port;
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						class CompressedString {
 | 
				
			||||||
 | 
						  public:
 | 
				
			||||||
 | 
							CompressedString() {
 | 
				
			||||||
 | 
								DecompressedSize_ = 0;
 | 
				
			||||||
 | 
							};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							explicit CompressedString(const std::string &Data) : DecompressedSize_(Data.size()) {
 | 
				
			||||||
 | 
								CompressIt(Data);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							CompressedString(const CompressedString &Data) {
 | 
				
			||||||
 | 
								this->DecompressedSize_ = Data.DecompressedSize_;
 | 
				
			||||||
 | 
								this->CompressedData_ = Data.CompressedData_;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							CompressedString& operator=(const CompressedString& rhs) {
 | 
				
			||||||
 | 
								if (this != &rhs) {
 | 
				
			||||||
 | 
									this->DecompressedSize_ = rhs.DecompressedSize_;
 | 
				
			||||||
 | 
									this->CompressedData_ = rhs.CompressedData_;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								return *this;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							CompressedString& operator=(CompressedString&& rhs) {
 | 
				
			||||||
 | 
								if (this != &rhs) {
 | 
				
			||||||
 | 
									this->DecompressedSize_ = rhs.DecompressedSize_;
 | 
				
			||||||
 | 
									this->CompressedData_ = rhs.CompressedData_;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								return *this;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							~CompressedString() = default;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							operator std::string() const {
 | 
				
			||||||
 | 
								return DecompressIt();
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							CompressedString &operator=(const std::string &Data) {
 | 
				
			||||||
 | 
								DecompressedSize_ = Data.size();
 | 
				
			||||||
 | 
								CompressIt(Data);
 | 
				
			||||||
 | 
								return *this;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							auto CompressedSize() const { return CompressedData_.size(); }
 | 
				
			||||||
 | 
							auto DecompressedSize() const { return DecompressedSize_; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						  private:
 | 
				
			||||||
 | 
							std::string     CompressedData_;
 | 
				
			||||||
 | 
							std::size_t     DecompressedSize_;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							inline void CompressIt(const std::string &Data) {
 | 
				
			||||||
 | 
								z_stream strm; // = {0};
 | 
				
			||||||
 | 
								CompressedData_.resize(Data.size());
 | 
				
			||||||
 | 
								strm.next_in = (Bytef *)Data.data();
 | 
				
			||||||
 | 
								strm.avail_in = Data.size();
 | 
				
			||||||
 | 
								strm.next_out = (Bytef *)CompressedData_.data();
 | 
				
			||||||
 | 
								strm.avail_out = Data.size();
 | 
				
			||||||
 | 
								strm.zalloc = Z_NULL;
 | 
				
			||||||
 | 
								strm.zfree = Z_NULL;
 | 
				
			||||||
 | 
								strm.opaque = Z_NULL;
 | 
				
			||||||
 | 
								deflateInit2(&strm, Z_DEFAULT_COMPRESSION, Z_DEFLATED, 15 + 16, 8, Z_DEFAULT_STRATEGY);
 | 
				
			||||||
 | 
								deflate(&strm, Z_FINISH);
 | 
				
			||||||
 | 
								deflateEnd(&strm);
 | 
				
			||||||
 | 
								CompressedData_.resize(strm.total_out);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							[[nodiscard]] std::string DecompressIt() const {
 | 
				
			||||||
 | 
								std::string Result;
 | 
				
			||||||
 | 
								if(DecompressedSize_!=0) {
 | 
				
			||||||
 | 
									Result.resize(DecompressedSize_);
 | 
				
			||||||
 | 
									z_stream strm ; //= {0};
 | 
				
			||||||
 | 
									strm.next_in = (Bytef *)CompressedData_.data();
 | 
				
			||||||
 | 
									strm.avail_in = CompressedData_.size();
 | 
				
			||||||
 | 
									strm.next_out = (Bytef *)Result.data();
 | 
				
			||||||
 | 
									strm.avail_out = Result.size();
 | 
				
			||||||
 | 
									strm.zalloc = Z_NULL;
 | 
				
			||||||
 | 
									strm.zfree = Z_NULL;
 | 
				
			||||||
 | 
									strm.opaque = Z_NULL;
 | 
				
			||||||
 | 
									inflateInit2(&strm, 15 + 32);
 | 
				
			||||||
 | 
									inflate(&strm, Z_FINISH);
 | 
				
			||||||
 | 
									inflateEnd(&strm);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								return Result;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
} // namespace OpenWifi::Utils
 | 
					} // namespace OpenWifi::Utils
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -146,7 +146,7 @@ namespace OpenWifi {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
				auto WebClientSecureContext =
 | 
									auto WebClientSecureContext =
 | 
				
			||||||
					new Poco::Net::Context(Poco::Net::Context::SERVER_USE, KeyFileName,
 | 
										new Poco::Net::Context(Poco::Net::Context::SERVER_USE, KeyFileName,
 | 
				
			||||||
										   CertFileName, "", Poco::Net::Context::VERIFY_RELAXED);
 | 
															   CertFileName, "", Poco::Net::Context::VERIFY_NONE);
 | 
				
			||||||
				Poco::Crypto::X509Certificate WebRoot(RootCaFileName);
 | 
									Poco::Crypto::X509Certificate WebRoot(RootCaFileName);
 | 
				
			||||||
				WebClientSecureContext->addCertificateAuthority(WebRoot);
 | 
									WebClientSecureContext->addCertificateAuthority(WebRoot);
 | 
				
			||||||
				WebClientSecureContext->disableStatelessSessionResumption();
 | 
									WebClientSecureContext->disableStatelessSessionResumption();
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -56,10 +56,10 @@ namespace OpenWifi {
 | 
				
			|||||||
	struct DeviceDetails {
 | 
						struct DeviceDetails {
 | 
				
			||||||
		std::string reason;
 | 
							std::string reason;
 | 
				
			||||||
		std::string author;
 | 
							std::string author;
 | 
				
			||||||
		std::uint64_t created;
 | 
							std::uint64_t created=Utils::Now();
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	static std::map<std::string, DeviceDetails> BlackListDevices;
 | 
						static std::map<std::uint64_t , DeviceDetails> BlackListDevices;
 | 
				
			||||||
	static std::recursive_mutex BlackListMutex;
 | 
						static std::recursive_mutex BlackListMutex;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	bool Storage::InitializeBlackListCache() {
 | 
						bool Storage::InitializeBlackListCache() {
 | 
				
			||||||
@@ -78,7 +78,7 @@ namespace OpenWifi {
 | 
				
			|||||||
				auto Reason = RSet[1].convert<std::string>();
 | 
									auto Reason = RSet[1].convert<std::string>();
 | 
				
			||||||
				auto Author = RSet[2].convert<std::string>();
 | 
									auto Author = RSet[2].convert<std::string>();
 | 
				
			||||||
				auto Created = RSet[3].convert<std::uint64_t>();
 | 
									auto Created = RSet[3].convert<std::uint64_t>();
 | 
				
			||||||
				BlackListDevices[SerialNumber] =
 | 
									BlackListDevices[Utils::MACToInt(SerialNumber)] =
 | 
				
			||||||
					DeviceDetails{.reason = Reason, .author = Author, .created = Created};
 | 
										DeviceDetails{.reason = Reason, .author = Author, .created = Created};
 | 
				
			||||||
				More = RSet.moveNext();
 | 
									More = RSet.moveNext();
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
@@ -93,6 +93,7 @@ namespace OpenWifi {
 | 
				
			|||||||
	bool Storage::AddBlackListDevice(GWObjects::BlackListedDevice &Device) {
 | 
						bool Storage::AddBlackListDevice(GWObjects::BlackListedDevice &Device) {
 | 
				
			||||||
		try {
 | 
							try {
 | 
				
			||||||
			Poco::Data::Session Sess = Pool_->get();
 | 
								Poco::Data::Session Sess = Pool_->get();
 | 
				
			||||||
 | 
								Sess.begin();
 | 
				
			||||||
			Poco::Data::Statement Insert(Sess);
 | 
								Poco::Data::Statement Insert(Sess);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			std::string St{"INSERT INTO BlackList (" + DB_BlackListDeviceSelectFields + ") " +
 | 
								std::string St{"INSERT INTO BlackList (" + DB_BlackListDeviceSelectFields + ") " +
 | 
				
			||||||
@@ -102,9 +103,9 @@ namespace OpenWifi {
 | 
				
			|||||||
			ConvertBlackListDeviceRecord(Device, T);
 | 
								ConvertBlackListDeviceRecord(Device, T);
 | 
				
			||||||
			Insert << ConvertParams(St), Poco::Data::Keywords::use(T);
 | 
								Insert << ConvertParams(St), Poco::Data::Keywords::use(T);
 | 
				
			||||||
			Insert.execute();
 | 
								Insert.execute();
 | 
				
			||||||
 | 
								Sess.commit();
 | 
				
			||||||
			std::lock_guard G(BlackListMutex);
 | 
								std::lock_guard G(BlackListMutex);
 | 
				
			||||||
			BlackListDevices[Device.serialNumber] = DeviceDetails{
 | 
								BlackListDevices[Utils::MACToInt(Device.serialNumber)] = DeviceDetails{
 | 
				
			||||||
				.reason = Device.reason, .author = Device.author, .created = Device.created};
 | 
									.reason = Device.reason, .author = Device.author, .created = Device.created};
 | 
				
			||||||
			return true;
 | 
								return true;
 | 
				
			||||||
		} catch (const Poco::Exception &E) {
 | 
							} catch (const Poco::Exception &E) {
 | 
				
			||||||
@@ -130,6 +131,7 @@ namespace OpenWifi {
 | 
				
			|||||||
	bool Storage::DeleteBlackListDevice(std::string &SerialNumber) {
 | 
						bool Storage::DeleteBlackListDevice(std::string &SerialNumber) {
 | 
				
			||||||
		try {
 | 
							try {
 | 
				
			||||||
			Poco::Data::Session Sess = Pool_->get();
 | 
								Poco::Data::Session Sess = Pool_->get();
 | 
				
			||||||
 | 
								Sess.begin();
 | 
				
			||||||
			Poco::Data::Statement Delete(Sess);
 | 
								Poco::Data::Statement Delete(Sess);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			std::string St{"DELETE FROM BlackList WHERE SerialNumber=?"};
 | 
								std::string St{"DELETE FROM BlackList WHERE SerialNumber=?"};
 | 
				
			||||||
@@ -137,9 +139,9 @@ namespace OpenWifi {
 | 
				
			|||||||
			Poco::toLowerInPlace(SerialNumber);
 | 
								Poco::toLowerInPlace(SerialNumber);
 | 
				
			||||||
			Delete << ConvertParams(St), Poco::Data::Keywords::use(SerialNumber);
 | 
								Delete << ConvertParams(St), Poco::Data::Keywords::use(SerialNumber);
 | 
				
			||||||
			Delete.execute();
 | 
								Delete.execute();
 | 
				
			||||||
 | 
								Sess.commit();
 | 
				
			||||||
			std::lock_guard G(BlackListMutex);
 | 
								std::lock_guard G(BlackListMutex);
 | 
				
			||||||
			BlackListDevices.erase(SerialNumber);
 | 
								BlackListDevices.erase(Utils::MACToInt(SerialNumber));
 | 
				
			||||||
			return true;
 | 
								return true;
 | 
				
			||||||
		} catch (const Poco::Exception &E) {
 | 
							} catch (const Poco::Exception &E) {
 | 
				
			||||||
			poco_warning(Logger(), fmt::format("{}: Failed with: {}", std::string(__func__),
 | 
								poco_warning(Logger(), fmt::format("{}: Failed with: {}", std::string(__func__),
 | 
				
			||||||
@@ -177,6 +179,7 @@ namespace OpenWifi {
 | 
				
			|||||||
										GWObjects::BlackListedDevice &Device) {
 | 
															GWObjects::BlackListedDevice &Device) {
 | 
				
			||||||
		try {
 | 
							try {
 | 
				
			||||||
			Poco::Data::Session Sess = Pool_->get();
 | 
								Poco::Data::Session Sess = Pool_->get();
 | 
				
			||||||
 | 
								Sess.begin();
 | 
				
			||||||
			Poco::Data::Statement Update(Sess);
 | 
								Poco::Data::Statement Update(Sess);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			std::string St{"UPDATE BlackList SET " + DB_BlackListDeviceUpdateFields +
 | 
								std::string St{"UPDATE BlackList SET " + DB_BlackListDeviceUpdateFields +
 | 
				
			||||||
@@ -187,9 +190,9 @@ namespace OpenWifi {
 | 
				
			|||||||
			Update << ConvertParams(St), Poco::Data::Keywords::use(T),
 | 
								Update << ConvertParams(St), Poco::Data::Keywords::use(T),
 | 
				
			||||||
				Poco::Data::Keywords::use(SerialNumber);
 | 
									Poco::Data::Keywords::use(SerialNumber);
 | 
				
			||||||
			Update.execute();
 | 
								Update.execute();
 | 
				
			||||||
 | 
								Sess.commit();
 | 
				
			||||||
			std::lock_guard G(BlackListMutex);
 | 
								std::lock_guard G(BlackListMutex);
 | 
				
			||||||
			BlackListDevices[Device.serialNumber] = DeviceDetails{
 | 
								BlackListDevices[Utils::MACToInt(Device.serialNumber)] = DeviceDetails{
 | 
				
			||||||
				.reason = Device.reason, .author = Device.author, .created = Device.created};
 | 
									.reason = Device.reason, .author = Device.author, .created = Device.created};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			return true;
 | 
								return true;
 | 
				
			||||||
@@ -233,10 +236,10 @@ namespace OpenWifi {
 | 
				
			|||||||
		return BlackListDevices.size();
 | 
							return BlackListDevices.size();
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	bool Storage::IsBlackListed(const std::string &SerialNumber, std::string &reason,
 | 
						bool Storage::IsBlackListed(std::uint64_t SerialNumber, std::string &reason,
 | 
				
			||||||
								std::string &author, std::uint64_t &created) {
 | 
													std::string &author, std::uint64_t &created) {
 | 
				
			||||||
		std::lock_guard G(BlackListMutex);
 | 
							std::lock_guard G(BlackListMutex);
 | 
				
			||||||
		auto DeviceHint = BlackListDevices.find(Poco::toLower(SerialNumber));
 | 
							auto DeviceHint = BlackListDevices.find(SerialNumber);
 | 
				
			||||||
		if (DeviceHint == end(BlackListDevices))
 | 
							if (DeviceHint == end(BlackListDevices))
 | 
				
			||||||
			return false;
 | 
								return false;
 | 
				
			||||||
		reason = DeviceHint->second.reason;
 | 
							reason = DeviceHint->second.reason;
 | 
				
			||||||
@@ -245,9 +248,9 @@ namespace OpenWifi {
 | 
				
			|||||||
		return true;
 | 
							return true;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	bool Storage::IsBlackListed(const std::string &SerialNumber) {
 | 
						bool Storage::IsBlackListed(std::uint64_t SerialNumber) {
 | 
				
			||||||
		std::lock_guard G(BlackListMutex);
 | 
							std::lock_guard G(BlackListMutex);
 | 
				
			||||||
		auto DeviceHint = BlackListDevices.find(Poco::toLower(SerialNumber));
 | 
							auto DeviceHint = BlackListDevices.find(SerialNumber);
 | 
				
			||||||
		return DeviceHint != end(BlackListDevices);
 | 
							return DeviceHint != end(BlackListDevices);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
} // namespace OpenWifi
 | 
					} // namespace OpenWifi
 | 
				
			||||||
@@ -17,11 +17,11 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
namespace OpenWifi {
 | 
					namespace OpenWifi {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	bool Storage::CreateDeviceCapabilities(std::string &SerialNumber,
 | 
						bool Storage::CreateDeviceCapabilities(Poco::Data::Session &Session, std::string &SerialNumber,
 | 
				
			||||||
										   const Config::Capabilities &Capabilities) {
 | 
															   const Config::Capabilities &Capabilities) {
 | 
				
			||||||
		try {
 | 
							try {
 | 
				
			||||||
			Poco::Data::Session Sess = Pool_->get();
 | 
								Session.begin();
 | 
				
			||||||
			Poco::Data::Statement UpSert(Sess);
 | 
								Poco::Data::Statement UpSert(Session);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			std::string TCaps{Capabilities.AsString()};
 | 
								std::string TCaps{Capabilities.AsString()};
 | 
				
			||||||
			uint64_t Now = Utils::Now();
 | 
								uint64_t Now = Utils::Now();
 | 
				
			||||||
@@ -33,6 +33,7 @@ namespace OpenWifi {
 | 
				
			|||||||
				Poco::Data::Keywords::use(Now), Poco::Data::Keywords::use(TCaps),
 | 
									Poco::Data::Keywords::use(Now), Poco::Data::Keywords::use(TCaps),
 | 
				
			||||||
				Poco::Data::Keywords::use(Now);
 | 
									Poco::Data::Keywords::use(Now);
 | 
				
			||||||
			UpSert.execute();
 | 
								UpSert.execute();
 | 
				
			||||||
 | 
								Session.commit();
 | 
				
			||||||
			return true;
 | 
								return true;
 | 
				
			||||||
		} catch (const Poco::Exception &E) {
 | 
							} catch (const Poco::Exception &E) {
 | 
				
			||||||
			poco_warning(Logger(), fmt::format("{}: Failed with: {}", std::string(__func__),
 | 
								poco_warning(Logger(), fmt::format("{}: Failed with: {}", std::string(__func__),
 | 
				
			||||||
@@ -41,11 +42,11 @@ namespace OpenWifi {
 | 
				
			|||||||
		return false;
 | 
							return false;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	bool Storage::UpdateDeviceCapabilities(std::string &SerialNumber,
 | 
						bool Storage::UpdateDeviceCapabilities(Poco::Data::Session &Session, std::string &SerialNumber,
 | 
				
			||||||
										   const Config::Capabilities &Caps) {
 | 
															   const Config::Capabilities &Caps) {
 | 
				
			||||||
		try {
 | 
							try {
 | 
				
			||||||
			Poco::Data::Session Sess = Pool_->get();
 | 
								Session.begin();
 | 
				
			||||||
			Poco::Data::Statement UpSert(Sess);
 | 
								Poco::Data::Statement UpSert(Session);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			uint64_t Now = Utils::Now();
 | 
								uint64_t Now = Utils::Now();
 | 
				
			||||||
			if (!Caps.Compatible().empty() && !Caps.Platform().empty())
 | 
								if (!Caps.Compatible().empty() && !Caps.Platform().empty())
 | 
				
			||||||
@@ -61,6 +62,7 @@ namespace OpenWifi {
 | 
				
			|||||||
				Poco::Data::Keywords::use(Now), Poco::Data::Keywords::use(TCaps),
 | 
									Poco::Data::Keywords::use(Now), Poco::Data::Keywords::use(TCaps),
 | 
				
			||||||
				Poco::Data::Keywords::use(Now);
 | 
									Poco::Data::Keywords::use(Now);
 | 
				
			||||||
			UpSert.execute();
 | 
								UpSert.execute();
 | 
				
			||||||
 | 
								Session.commit();
 | 
				
			||||||
			return true;
 | 
								return true;
 | 
				
			||||||
		} catch (const Poco::Exception &E) {
 | 
							} catch (const Poco::Exception &E) {
 | 
				
			||||||
			poco_warning(Logger(), fmt::format("{}: Failed with: {}", std::string(__func__),
 | 
								poco_warning(Logger(), fmt::format("{}: Failed with: {}", std::string(__func__),
 | 
				
			||||||
@@ -99,13 +101,14 @@ namespace OpenWifi {
 | 
				
			|||||||
	bool Storage::DeleteDeviceCapabilities(std::string &SerialNumber) {
 | 
						bool Storage::DeleteDeviceCapabilities(std::string &SerialNumber) {
 | 
				
			||||||
		try {
 | 
							try {
 | 
				
			||||||
			Poco::Data::Session Sess = Pool_->get();
 | 
								Poco::Data::Session Sess = Pool_->get();
 | 
				
			||||||
 | 
								Sess.begin();
 | 
				
			||||||
			Poco::Data::Statement Delete(Sess);
 | 
								Poco::Data::Statement Delete(Sess);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			std::string St{"DELETE FROM Capabilities WHERE SerialNumber=?"};
 | 
								std::string St{"DELETE FROM Capabilities WHERE SerialNumber=?"};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			Delete << ConvertParams(St), Poco::Data::Keywords::use(SerialNumber);
 | 
								Delete << ConvertParams(St), Poco::Data::Keywords::use(SerialNumber);
 | 
				
			||||||
			Delete.execute();
 | 
								Delete.execute();
 | 
				
			||||||
 | 
								Sess.commit();
 | 
				
			||||||
			return true;
 | 
								return true;
 | 
				
			||||||
		} catch (const Poco::Exception &E) {
 | 
							} catch (const Poco::Exception &E) {
 | 
				
			||||||
			poco_warning(Logger(), fmt::format("{}: Failed with: {}", std::string(__func__),
 | 
								poco_warning(Logger(), fmt::format("{}: Failed with: {}", std::string(__func__),
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -105,6 +105,7 @@ namespace OpenWifi {
 | 
				
			|||||||
	bool Storage::RemoveOldCommands(std::string &SerialNumber, std::string &Command) {
 | 
						bool Storage::RemoveOldCommands(std::string &SerialNumber, std::string &Command) {
 | 
				
			||||||
		try {
 | 
							try {
 | 
				
			||||||
			Poco::Data::Session Sess = Pool_->get();
 | 
								Poco::Data::Session Sess = Pool_->get();
 | 
				
			||||||
 | 
								Sess.begin();
 | 
				
			||||||
			Poco::Data::Statement Delete(Sess);
 | 
								Poco::Data::Statement Delete(Sess);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			std::string St{
 | 
								std::string St{
 | 
				
			||||||
@@ -112,8 +113,7 @@ namespace OpenWifi {
 | 
				
			|||||||
			Delete << ConvertParams(St), Poco::Data::Keywords::use(SerialNumber),
 | 
								Delete << ConvertParams(St), Poco::Data::Keywords::use(SerialNumber),
 | 
				
			||||||
				Poco::Data::Keywords::use(Command);
 | 
									Poco::Data::Keywords::use(Command);
 | 
				
			||||||
			Delete.execute();
 | 
								Delete.execute();
 | 
				
			||||||
			Delete.reset(Sess);
 | 
								Sess.commit();
 | 
				
			||||||
 | 
					 | 
				
			||||||
			return true;
 | 
								return true;
 | 
				
			||||||
		} catch (const Poco::Exception &E) {
 | 
							} catch (const Poco::Exception &E) {
 | 
				
			||||||
			Logger().log(E);
 | 
								Logger().log(E);
 | 
				
			||||||
@@ -146,6 +146,7 @@ namespace OpenWifi {
 | 
				
			|||||||
			RemoveOldCommands(SerialNumber, Command.Command);
 | 
								RemoveOldCommands(SerialNumber, Command.Command);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			Poco::Data::Session Sess = Pool_->get();
 | 
								Poco::Data::Session Sess = Pool_->get();
 | 
				
			||||||
 | 
								Sess.begin();
 | 
				
			||||||
			Poco::Data::Statement Insert(Sess);
 | 
								Poco::Data::Statement Insert(Sess);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			std::string St{"INSERT INTO CommandList ( " + DB_Command_SelectFields + " ) VALUES( " +
 | 
								std::string St{"INSERT INTO CommandList ( " + DB_Command_SelectFields + " ) VALUES( " +
 | 
				
			||||||
@@ -156,7 +157,7 @@ namespace OpenWifi {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
			Insert << ConvertParams(St), Poco::Data::Keywords::use(R);
 | 
								Insert << ConvertParams(St), Poco::Data::Keywords::use(R);
 | 
				
			||||||
			Insert.execute();
 | 
								Insert.execute();
 | 
				
			||||||
 | 
								Sess.commit();
 | 
				
			||||||
			return true;
 | 
								return true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		} catch (const Poco::Exception &E) {
 | 
							} catch (const Poco::Exception &E) {
 | 
				
			||||||
@@ -215,6 +216,7 @@ namespace OpenWifi {
 | 
				
			|||||||
	bool Storage::DeleteCommands(std::string &SerialNumber, uint64_t FromDate, uint64_t ToDate) {
 | 
						bool Storage::DeleteCommands(std::string &SerialNumber, uint64_t FromDate, uint64_t ToDate) {
 | 
				
			||||||
		try {
 | 
							try {
 | 
				
			||||||
			Poco::Data::Session Sess = Pool_->get();
 | 
								Poco::Data::Session Sess = Pool_->get();
 | 
				
			||||||
 | 
								Sess.begin();
 | 
				
			||||||
			Poco::Data::Statement Delete(Sess);
 | 
								Poco::Data::Statement Delete(Sess);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			bool DatesIncluded = (FromDate != 0 || ToDate != 0);
 | 
								bool DatesIncluded = (FromDate != 0 || ToDate != 0);
 | 
				
			||||||
@@ -237,8 +239,7 @@ namespace OpenWifi {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
			Delete << IntroStatement + DateSelector;
 | 
								Delete << IntroStatement + DateSelector;
 | 
				
			||||||
			Delete.execute();
 | 
								Delete.execute();
 | 
				
			||||||
			Delete.reset(Sess);
 | 
								Sess.commit();
 | 
				
			||||||
 | 
					 | 
				
			||||||
			return true;
 | 
								return true;
 | 
				
			||||||
		} catch (const Poco::Exception &E) {
 | 
							} catch (const Poco::Exception &E) {
 | 
				
			||||||
			Logger().log(E);
 | 
								Logger().log(E);
 | 
				
			||||||
@@ -274,7 +275,6 @@ namespace OpenWifi {
 | 
				
			|||||||
				if (Records.size() < HowMany)
 | 
									if (Records.size() < HowMany)
 | 
				
			||||||
					Done = true;
 | 
										Done = true;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			Select.reset(Sess);
 | 
					 | 
				
			||||||
			return true;
 | 
								return true;
 | 
				
			||||||
		} catch (const Poco::Exception &E) {
 | 
							} catch (const Poco::Exception &E) {
 | 
				
			||||||
			Logger().log(E);
 | 
								Logger().log(E);
 | 
				
			||||||
@@ -286,6 +286,7 @@ namespace OpenWifi {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
		try {
 | 
							try {
 | 
				
			||||||
			Poco::Data::Session Sess = Pool_->get();
 | 
								Poco::Data::Session Sess = Pool_->get();
 | 
				
			||||||
 | 
								Sess.begin();
 | 
				
			||||||
			Poco::Data::Statement Update(Sess);
 | 
								Poco::Data::Statement Update(Sess);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			std::string St{"UPDATE CommandList SET Status=?,  Executed=?,  Completed=?,  "
 | 
								std::string St{"UPDATE CommandList SET Status=?,  Executed=?,  Completed=?,  "
 | 
				
			||||||
@@ -299,7 +300,7 @@ namespace OpenWifi {
 | 
				
			|||||||
				Poco::Data::Keywords::use(Command.ErrorCode), Poco::Data::Keywords::use(UUID);
 | 
									Poco::Data::Keywords::use(Command.ErrorCode), Poco::Data::Keywords::use(UUID);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			Update.execute();
 | 
								Update.execute();
 | 
				
			||||||
 | 
								Sess.commit();
 | 
				
			||||||
			return true;
 | 
								return true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		} catch (const Poco::Exception &E) {
 | 
							} catch (const Poco::Exception &E) {
 | 
				
			||||||
@@ -311,6 +312,7 @@ namespace OpenWifi {
 | 
				
			|||||||
	bool Storage::SetCommandExecuted(std::string &CommandUUID) {
 | 
						bool Storage::SetCommandExecuted(std::string &CommandUUID) {
 | 
				
			||||||
		try {
 | 
							try {
 | 
				
			||||||
			Poco::Data::Session Sess = Pool_->get();
 | 
								Poco::Data::Session Sess = Pool_->get();
 | 
				
			||||||
 | 
								Sess.begin();
 | 
				
			||||||
			Poco::Data::Statement Update(Sess);
 | 
								Poco::Data::Statement Update(Sess);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			auto Now = Utils::Now();
 | 
								auto Now = Utils::Now();
 | 
				
			||||||
@@ -321,6 +323,7 @@ namespace OpenWifi {
 | 
				
			|||||||
			Update << ConvertParams(St), Poco::Data::Keywords::use(Now),
 | 
								Update << ConvertParams(St), Poco::Data::Keywords::use(Now),
 | 
				
			||||||
				Poco::Data::Keywords::use(Status), Poco::Data::Keywords::use(CommandUUID);
 | 
									Poco::Data::Keywords::use(Status), Poco::Data::Keywords::use(CommandUUID);
 | 
				
			||||||
			Update.execute();
 | 
								Update.execute();
 | 
				
			||||||
 | 
								Sess.commit();
 | 
				
			||||||
			return true;
 | 
								return true;
 | 
				
			||||||
		} catch (const Poco::Exception &E) {
 | 
							} catch (const Poco::Exception &E) {
 | 
				
			||||||
			Logger().log(E);
 | 
								Logger().log(E);
 | 
				
			||||||
@@ -331,6 +334,7 @@ namespace OpenWifi {
 | 
				
			|||||||
	void Storage::RemovedExpiredCommands() {
 | 
						void Storage::RemovedExpiredCommands() {
 | 
				
			||||||
		try {
 | 
							try {
 | 
				
			||||||
			Poco::Data::Session Sess = Pool_->get();
 | 
								Poco::Data::Session Sess = Pool_->get();
 | 
				
			||||||
 | 
								Sess.begin();
 | 
				
			||||||
			Poco::Data::Statement Update(Sess);
 | 
								Poco::Data::Statement Update(Sess);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			auto Now = Utils::Now(), Window = Now - CommandManager()->CommandTimeout();
 | 
								auto Now = Utils::Now(), Window = Now - CommandManager()->CommandTimeout();
 | 
				
			||||||
@@ -341,8 +345,7 @@ namespace OpenWifi {
 | 
				
			|||||||
			Update << ConvertParams(St), Poco::Data::Keywords::use(Now),
 | 
								Update << ConvertParams(St), Poco::Data::Keywords::use(Now),
 | 
				
			||||||
				Poco::Data::Keywords::use(Status), Poco::Data::Keywords::use(Window);
 | 
									Poco::Data::Keywords::use(Status), Poco::Data::Keywords::use(Window);
 | 
				
			||||||
			Update.execute();
 | 
								Update.execute();
 | 
				
			||||||
			Update.reset(Sess);
 | 
								Sess.commit();
 | 
				
			||||||
 | 
					 | 
				
			||||||
		} catch (const Poco::Exception &E) {
 | 
							} catch (const Poco::Exception &E) {
 | 
				
			||||||
			Logger().log(E);
 | 
								Logger().log(E);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
@@ -351,6 +354,7 @@ namespace OpenWifi {
 | 
				
			|||||||
	bool Storage::SetCommandLastTry(std::string &CommandUUID) {
 | 
						bool Storage::SetCommandLastTry(std::string &CommandUUID) {
 | 
				
			||||||
		try {
 | 
							try {
 | 
				
			||||||
			Poco::Data::Session Sess = Pool_->get();
 | 
								Poco::Data::Session Sess = Pool_->get();
 | 
				
			||||||
 | 
								Sess.begin();
 | 
				
			||||||
			Poco::Data::Statement Update(Sess);
 | 
								Poco::Data::Statement Update(Sess);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			auto Now = Utils::Now();
 | 
								auto Now = Utils::Now();
 | 
				
			||||||
@@ -359,6 +363,7 @@ namespace OpenWifi {
 | 
				
			|||||||
			Update << ConvertParams(St), Poco::Data::Keywords::use(Now),
 | 
								Update << ConvertParams(St), Poco::Data::Keywords::use(Now),
 | 
				
			||||||
				Poco::Data::Keywords::use(CommandUUID);
 | 
									Poco::Data::Keywords::use(CommandUUID);
 | 
				
			||||||
			Update.execute();
 | 
								Update.execute();
 | 
				
			||||||
 | 
								Sess.commit();
 | 
				
			||||||
			return true;
 | 
								return true;
 | 
				
			||||||
		} catch (const Poco::Exception &E) {
 | 
							} catch (const Poco::Exception &E) {
 | 
				
			||||||
			Logger().log(E);
 | 
								Logger().log(E);
 | 
				
			||||||
@@ -369,6 +374,7 @@ namespace OpenWifi {
 | 
				
			|||||||
	void Storage::RemoveTimedOutCommands() {
 | 
						void Storage::RemoveTimedOutCommands() {
 | 
				
			||||||
		try {
 | 
							try {
 | 
				
			||||||
			Poco::Data::Session Sess = Pool_->get();
 | 
								Poco::Data::Session Sess = Pool_->get();
 | 
				
			||||||
 | 
								Sess.begin();
 | 
				
			||||||
			Poco::Data::Statement Update(Sess);
 | 
								Poco::Data::Statement Update(Sess);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			auto Now = Utils::Now(), Window = Now - CommandManager()->CommandTimeout();
 | 
								auto Now = Utils::Now(), Window = Now - CommandManager()->CommandTimeout();
 | 
				
			||||||
@@ -377,7 +383,7 @@ namespace OpenWifi {
 | 
				
			|||||||
			Update << ConvertParams(St), Poco::Data::Keywords::use(Now),
 | 
								Update << ConvertParams(St), Poco::Data::Keywords::use(Now),
 | 
				
			||||||
				Poco::Data::Keywords::use(Window);
 | 
									Poco::Data::Keywords::use(Window);
 | 
				
			||||||
			Update.execute();
 | 
								Update.execute();
 | 
				
			||||||
			Update.reset(Sess);
 | 
								Sess.commit();
 | 
				
			||||||
		} catch (const Poco::Exception &E) {
 | 
							} catch (const Poco::Exception &E) {
 | 
				
			||||||
			Logger().log(E);
 | 
								Logger().log(E);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
@@ -386,6 +392,7 @@ namespace OpenWifi {
 | 
				
			|||||||
	bool Storage::SetCommandTimedOut(std::string &CommandUUID) {
 | 
						bool Storage::SetCommandTimedOut(std::string &CommandUUID) {
 | 
				
			||||||
		try {
 | 
							try {
 | 
				
			||||||
			Poco::Data::Session Sess = Pool_->get();
 | 
								Poco::Data::Session Sess = Pool_->get();
 | 
				
			||||||
 | 
								Sess.begin();
 | 
				
			||||||
			Poco::Data::Statement Update(Sess);
 | 
								Poco::Data::Statement Update(Sess);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			auto Now = Utils::Now();
 | 
								auto Now = Utils::Now();
 | 
				
			||||||
@@ -395,6 +402,7 @@ namespace OpenWifi {
 | 
				
			|||||||
			Update << ConvertParams(St), Poco::Data::Keywords::use(Now),
 | 
								Update << ConvertParams(St), Poco::Data::Keywords::use(Now),
 | 
				
			||||||
				Poco::Data::Keywords::use(Status), Poco::Data::Keywords::use(CommandUUID);
 | 
									Poco::Data::Keywords::use(Status), Poco::Data::Keywords::use(CommandUUID);
 | 
				
			||||||
			Update.execute();
 | 
								Update.execute();
 | 
				
			||||||
 | 
								Sess.commit();
 | 
				
			||||||
			return true;
 | 
								return true;
 | 
				
			||||||
		} catch (const Poco::Exception &E) {
 | 
							} catch (const Poco::Exception &E) {
 | 
				
			||||||
			Logger().log(E);
 | 
								Logger().log(E);
 | 
				
			||||||
@@ -425,6 +433,7 @@ namespace OpenWifi {
 | 
				
			|||||||
	bool Storage::DeleteCommand(std::string &UUID) {
 | 
						bool Storage::DeleteCommand(std::string &UUID) {
 | 
				
			||||||
		try {
 | 
							try {
 | 
				
			||||||
			Poco::Data::Session Sess = Pool_->get();
 | 
								Poco::Data::Session Sess = Pool_->get();
 | 
				
			||||||
 | 
								Sess.begin();
 | 
				
			||||||
			Poco::Data::Statement Delete(Sess);
 | 
								Poco::Data::Statement Delete(Sess);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			std::string St{"DELETE FROM CommandList WHERE UUID=?"};
 | 
								std::string St{"DELETE FROM CommandList WHERE UUID=?"};
 | 
				
			||||||
@@ -435,8 +444,7 @@ namespace OpenWifi {
 | 
				
			|||||||
			St = "DELETE FROM FileUploads WHERE UUID=?";
 | 
								St = "DELETE FROM FileUploads WHERE UUID=?";
 | 
				
			||||||
			Delete << ConvertParams(St), Poco::Data::Keywords::use(UUID);
 | 
								Delete << ConvertParams(St), Poco::Data::Keywords::use(UUID);
 | 
				
			||||||
			Delete.execute();
 | 
								Delete.execute();
 | 
				
			||||||
			Delete.reset(Sess);
 | 
								Sess.commit();
 | 
				
			||||||
 | 
					 | 
				
			||||||
			return true;
 | 
								return true;
 | 
				
			||||||
		} catch (const Poco::Exception &E) {
 | 
							} catch (const Poco::Exception &E) {
 | 
				
			||||||
			Logger().log(E);
 | 
								Logger().log(E);
 | 
				
			||||||
@@ -510,6 +518,7 @@ namespace OpenWifi {
 | 
				
			|||||||
			auto Now = Utils::Now();
 | 
								auto Now = Utils::Now();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			Poco::Data::Session Sess = Pool_->get();
 | 
								Poco::Data::Session Sess = Pool_->get();
 | 
				
			||||||
 | 
								Sess.begin();
 | 
				
			||||||
			Poco::Data::Statement Update(Sess);
 | 
								Poco::Data::Statement Update(Sess);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			std::string St{"UPDATE CommandList SET Executed=? WHERE UUID=?"};
 | 
								std::string St{"UPDATE CommandList SET Executed=? WHERE UUID=?"};
 | 
				
			||||||
@@ -518,7 +527,7 @@ namespace OpenWifi {
 | 
				
			|||||||
				Poco::Data::Keywords::use(UUID);
 | 
									Poco::Data::Keywords::use(UUID);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			Update.execute();
 | 
								Update.execute();
 | 
				
			||||||
 | 
								Sess.commit();
 | 
				
			||||||
			return true;
 | 
								return true;
 | 
				
			||||||
		} catch (const Poco::Exception &E) {
 | 
							} catch (const Poco::Exception &E) {
 | 
				
			||||||
			Logger().log(E);
 | 
								Logger().log(E);
 | 
				
			||||||
@@ -555,6 +564,7 @@ namespace OpenWifi {
 | 
				
			|||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			Poco::Data::Session Sess = Pool_->get();
 | 
								Poco::Data::Session Sess = Pool_->get();
 | 
				
			||||||
 | 
								Sess.begin();
 | 
				
			||||||
			Poco::Data::Statement Update(Sess);
 | 
								Poco::Data::Statement Update(Sess);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			auto Status = to_string(Storage::CommandExecutionType::COMMAND_COMPLETED);
 | 
								auto Status = to_string(Storage::CommandExecutionType::COMMAND_COMPLETED);
 | 
				
			||||||
@@ -566,6 +576,7 @@ namespace OpenWifi {
 | 
				
			|||||||
				Poco::Data::Keywords::use(ResultStr), Poco::Data::Keywords::use(Status),
 | 
									Poco::Data::Keywords::use(ResultStr), Poco::Data::Keywords::use(Status),
 | 
				
			||||||
				Poco::Data::Keywords::use(tET), Poco::Data::Keywords::use(UUID);
 | 
									Poco::Data::Keywords::use(tET), Poco::Data::Keywords::use(UUID);
 | 
				
			||||||
			Update.execute();
 | 
								Update.execute();
 | 
				
			||||||
 | 
								Sess.commit();
 | 
				
			||||||
			return true;
 | 
								return true;
 | 
				
			||||||
		} catch (const Poco::Exception &E) {
 | 
							} catch (const Poco::Exception &E) {
 | 
				
			||||||
			Logger().log(E);
 | 
								Logger().log(E);
 | 
				
			||||||
@@ -603,6 +614,7 @@ namespace OpenWifi {
 | 
				
			|||||||
	bool Storage::CancelWaitFile(std::string &UUID, std::string &ErrorText) {
 | 
						bool Storage::CancelWaitFile(std::string &UUID, std::string &ErrorText) {
 | 
				
			||||||
		try {
 | 
							try {
 | 
				
			||||||
			Poco::Data::Session Sess = Pool_->get();
 | 
								Poco::Data::Session Sess = Pool_->get();
 | 
				
			||||||
 | 
								Sess.begin();
 | 
				
			||||||
			auto Now = Utils::Now();
 | 
								auto Now = Utils::Now();
 | 
				
			||||||
			uint64_t Size = 0, WaitForFile = 0;
 | 
								uint64_t Size = 0, WaitForFile = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -616,6 +628,7 @@ namespace OpenWifi {
 | 
				
			|||||||
				Poco::Data::Keywords::use(ErrorText), Poco::Data::Keywords::use(Now),
 | 
									Poco::Data::Keywords::use(ErrorText), Poco::Data::Keywords::use(Now),
 | 
				
			||||||
				Poco::Data::Keywords::use(UUID);
 | 
									Poco::Data::Keywords::use(UUID);
 | 
				
			||||||
			Update.execute();
 | 
								Update.execute();
 | 
				
			||||||
 | 
								Sess.commit();
 | 
				
			||||||
			return true;
 | 
								return true;
 | 
				
			||||||
		} catch (const Poco::Exception &E) {
 | 
							} catch (const Poco::Exception &E) {
 | 
				
			||||||
			Logger().log(E);
 | 
								Logger().log(E);
 | 
				
			||||||
@@ -631,6 +644,7 @@ namespace OpenWifi {
 | 
				
			|||||||
			uint64_t Size = FileContent.str().size();
 | 
								uint64_t Size = FileContent.str().size();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			Poco::Data::Session Sess = Pool_->get();
 | 
								Poco::Data::Session Sess = Pool_->get();
 | 
				
			||||||
 | 
								Sess.begin();
 | 
				
			||||||
			Poco::Data::Statement Statement(Sess);
 | 
								Poco::Data::Statement Statement(Sess);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			std::string StatementStr;
 | 
								std::string StatementStr;
 | 
				
			||||||
@@ -644,14 +658,14 @@ namespace OpenWifi {
 | 
				
			|||||||
				Poco::Data::Keywords::use(Now), Poco::Data::Keywords::use(Size),
 | 
									Poco::Data::Keywords::use(Now), Poco::Data::Keywords::use(Size),
 | 
				
			||||||
				Poco::Data::Keywords::use(UUID);
 | 
									Poco::Data::Keywords::use(UUID);
 | 
				
			||||||
			Statement.execute();
 | 
								Statement.execute();
 | 
				
			||||||
 | 
								Sess.commit();
 | 
				
			||||||
			if (Size < FileUploader()->MaxSize()) {
 | 
								if (Size < FileUploader()->MaxSize()) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				Poco::Data::BLOB TheBlob;
 | 
									Poco::Data::BLOB TheBlob;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				TheBlob.appendRaw((const unsigned char *)FileContent.str().c_str(),
 | 
									TheBlob.appendRaw((const unsigned char *)FileContent.str().c_str(),
 | 
				
			||||||
								  FileContent.str().size());
 | 
													  FileContent.str().size());
 | 
				
			||||||
 | 
									Sess.begin();
 | 
				
			||||||
				Poco::Data::Statement Insert(Sess);
 | 
									Poco::Data::Statement Insert(Sess);
 | 
				
			||||||
				std::string FileType{Type};
 | 
									std::string FileType{Type};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -662,10 +676,12 @@ namespace OpenWifi {
 | 
				
			|||||||
					Poco::Data::Keywords::use(FileType), Poco::Data::Keywords::use(Now),
 | 
										Poco::Data::Keywords::use(FileType), Poco::Data::Keywords::use(Now),
 | 
				
			||||||
					Poco::Data::Keywords::use(TheBlob);
 | 
										Poco::Data::Keywords::use(TheBlob);
 | 
				
			||||||
				Insert.execute();
 | 
									Insert.execute();
 | 
				
			||||||
				return true;
 | 
									Sess.commit();
 | 
				
			||||||
			} else {
 | 
								} else {
 | 
				
			||||||
				poco_warning(Logger(), fmt::format("File {} is too large.", UUID));
 | 
									poco_warning(Logger(), fmt::format("File {} is too large.", UUID));
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
								Sess.commit();
 | 
				
			||||||
 | 
								return true;
 | 
				
			||||||
		} catch (const Poco::Exception &E) {
 | 
							} catch (const Poco::Exception &E) {
 | 
				
			||||||
			Logger().log(E);
 | 
								Logger().log(E);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
@@ -712,6 +728,7 @@ namespace OpenWifi {
 | 
				
			|||||||
	bool Storage::SetCommandResult(std::string &UUID, std::string &Result) {
 | 
						bool Storage::SetCommandResult(std::string &UUID, std::string &Result) {
 | 
				
			||||||
		try {
 | 
							try {
 | 
				
			||||||
			Poco::Data::Session Sess = Pool_->get();
 | 
								Poco::Data::Session Sess = Pool_->get();
 | 
				
			||||||
 | 
								Sess.begin();
 | 
				
			||||||
			Poco::Data::Statement Update(Sess);
 | 
								Poco::Data::Statement Update(Sess);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			auto Now = Utils::Now();
 | 
								auto Now = Utils::Now();
 | 
				
			||||||
@@ -722,6 +739,7 @@ namespace OpenWifi {
 | 
				
			|||||||
				Poco::Data::Keywords::use(Result), Poco::Data::Keywords::use(Status),
 | 
									Poco::Data::Keywords::use(Result), Poco::Data::Keywords::use(Status),
 | 
				
			||||||
				Poco::Data::Keywords::use(UUID);
 | 
									Poco::Data::Keywords::use(UUID);
 | 
				
			||||||
			Update.execute();
 | 
								Update.execute();
 | 
				
			||||||
 | 
								Sess.commit();
 | 
				
			||||||
			return true;
 | 
								return true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		} catch (const Poco::Exception &E) {
 | 
							} catch (const Poco::Exception &E) {
 | 
				
			||||||
@@ -733,13 +751,14 @@ namespace OpenWifi {
 | 
				
			|||||||
	bool Storage::RemoveAttachedFile(std::string &UUID) {
 | 
						bool Storage::RemoveAttachedFile(std::string &UUID) {
 | 
				
			||||||
		try {
 | 
							try {
 | 
				
			||||||
			Poco::Data::Session Sess = Pool_->get();
 | 
								Poco::Data::Session Sess = Pool_->get();
 | 
				
			||||||
 | 
								Sess.begin();
 | 
				
			||||||
			Poco::Data::Statement Delete(Sess);
 | 
								Poco::Data::Statement Delete(Sess);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			std::string St{"DELETE FROM FileUploads WHERE UUID=?"};
 | 
								std::string St{"DELETE FROM FileUploads WHERE UUID=?"};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			Delete << ConvertParams(St), Poco::Data::Keywords::use(UUID);
 | 
								Delete << ConvertParams(St), Poco::Data::Keywords::use(UUID);
 | 
				
			||||||
			Delete.execute();
 | 
								Delete.execute();
 | 
				
			||||||
 | 
								Sess.commit();
 | 
				
			||||||
			return true;
 | 
								return true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		} catch (const Poco::Exception &E) {
 | 
							} catch (const Poco::Exception &E) {
 | 
				
			||||||
@@ -751,11 +770,13 @@ namespace OpenWifi {
 | 
				
			|||||||
	bool Storage::RemoveUploadedFilesRecordsOlderThan(uint64_t Date) {
 | 
						bool Storage::RemoveUploadedFilesRecordsOlderThan(uint64_t Date) {
 | 
				
			||||||
		try {
 | 
							try {
 | 
				
			||||||
			Poco::Data::Session Sess = Pool_->get();
 | 
								Poco::Data::Session Sess = Pool_->get();
 | 
				
			||||||
 | 
								Sess.begin();
 | 
				
			||||||
			Poco::Data::Statement Delete(Sess);
 | 
								Poco::Data::Statement Delete(Sess);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			std::string St1{"delete from FileUploads where Created<?"};
 | 
								std::string St1{"delete from FileUploads where Created<?"};
 | 
				
			||||||
			Delete << ConvertParams(St1), Poco::Data::Keywords::use(Date);
 | 
								Delete << ConvertParams(St1), Poco::Data::Keywords::use(Date);
 | 
				
			||||||
			Delete.execute();
 | 
								Delete.execute();
 | 
				
			||||||
 | 
								Sess.commit();
 | 
				
			||||||
			return true;
 | 
								return true;
 | 
				
			||||||
		} catch (const Poco::Exception &E) {
 | 
							} catch (const Poco::Exception &E) {
 | 
				
			||||||
			Logger().log(E);
 | 
								Logger().log(E);
 | 
				
			||||||
@@ -766,11 +787,13 @@ namespace OpenWifi {
 | 
				
			|||||||
	bool Storage::RemoveCommandListRecordsOlderThan(uint64_t Date) {
 | 
						bool Storage::RemoveCommandListRecordsOlderThan(uint64_t Date) {
 | 
				
			||||||
		try {
 | 
							try {
 | 
				
			||||||
			Poco::Data::Session Sess = Pool_->get();
 | 
								Poco::Data::Session Sess = Pool_->get();
 | 
				
			||||||
 | 
								Sess.begin();
 | 
				
			||||||
			Poco::Data::Statement Delete(Sess);
 | 
								Poco::Data::Statement Delete(Sess);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			std::string St1{"delete from CommandList where Submitted<?"};
 | 
								std::string St1{"delete from CommandList where Submitted<?"};
 | 
				
			||||||
			Delete << ConvertParams(St1), Poco::Data::Keywords::use(Date);
 | 
								Delete << ConvertParams(St1), Poco::Data::Keywords::use(Date);
 | 
				
			||||||
			Delete.execute();
 | 
								Delete.execute();
 | 
				
			||||||
 | 
								Sess.commit();
 | 
				
			||||||
			return true;
 | 
								return true;
 | 
				
			||||||
		} catch (const Poco::Exception &E) {
 | 
							} catch (const Poco::Exception &E) {
 | 
				
			||||||
			Logger().log(E);
 | 
								Logger().log(E);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -82,6 +82,7 @@ namespace OpenWifi {
 | 
				
			|||||||
			if (!TmpName.empty())
 | 
								if (!TmpName.empty())
 | 
				
			||||||
				return false;
 | 
									return false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								Sess.begin();
 | 
				
			||||||
			Poco::Data::Statement Insert(Sess);
 | 
								Poco::Data::Statement Insert(Sess);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			std::string St2{"INSERT INTO DefaultFirmwares ( " + DB_DefFirmware_SelectFields +
 | 
								std::string St2{"INSERT INTO DefaultFirmwares ( " + DB_DefFirmware_SelectFields +
 | 
				
			||||||
@@ -94,6 +95,7 @@ namespace OpenWifi {
 | 
				
			|||||||
			Insert << ConvertParams(St2),
 | 
								Insert << ConvertParams(St2),
 | 
				
			||||||
				Poco::Data::Keywords::use(R);
 | 
									Poco::Data::Keywords::use(R);
 | 
				
			||||||
			Insert.execute();
 | 
								Insert.execute();
 | 
				
			||||||
 | 
								Sess.commit();
 | 
				
			||||||
			return true;
 | 
								return true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		} catch (const Poco::Exception &E) {
 | 
							} catch (const Poco::Exception &E) {
 | 
				
			||||||
@@ -107,6 +109,7 @@ namespace OpenWifi {
 | 
				
			|||||||
		try {
 | 
							try {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			Poco::Data::Session Sess = Pool_->get();
 | 
								Poco::Data::Session Sess = Pool_->get();
 | 
				
			||||||
 | 
								Sess.begin();
 | 
				
			||||||
			Poco::Data::Statement Delete(Sess);
 | 
								Poco::Data::Statement Delete(Sess);
 | 
				
			||||||
			Poco::toLowerInPlace(deviceType);
 | 
								Poco::toLowerInPlace(deviceType);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -114,7 +117,7 @@ namespace OpenWifi {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
			Delete << ConvertParams(St), Poco::Data::Keywords::use(deviceType);
 | 
								Delete << ConvertParams(St), Poco::Data::Keywords::use(deviceType);
 | 
				
			||||||
			Delete.execute();
 | 
								Delete.execute();
 | 
				
			||||||
 | 
								Sess.commit();
 | 
				
			||||||
			return true;
 | 
								return true;
 | 
				
			||||||
		} catch (const Poco::Exception &E) {
 | 
							} catch (const Poco::Exception &E) {
 | 
				
			||||||
			poco_warning(Logger(), fmt::format("{}: Failed with: {}", std::string(__func__),
 | 
								poco_warning(Logger(), fmt::format("{}: Failed with: {}", std::string(__func__),
 | 
				
			||||||
@@ -125,9 +128,9 @@ namespace OpenWifi {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	bool Storage::UpdateDefaultFirmware(GWObjects::DefaultFirmware &DefFirmware) {
 | 
						bool Storage::UpdateDefaultFirmware(GWObjects::DefaultFirmware &DefFirmware) {
 | 
				
			||||||
		try {
 | 
							try {
 | 
				
			||||||
 | 
								uint64_t Now = Utils::Now();
 | 
				
			||||||
			Poco::Data::Session Sess = Pool_->get();
 | 
								Poco::Data::Session Sess = Pool_->get();
 | 
				
			||||||
 | 
								Sess.begin();
 | 
				
			||||||
			uint64_t Now = time(nullptr);
 | 
					 | 
				
			||||||
			Poco::Data::Statement Update(Sess);
 | 
								Poco::Data::Statement Update(Sess);
 | 
				
			||||||
			DefFirmware.LastModified = Now;
 | 
								DefFirmware.LastModified = Now;
 | 
				
			||||||
			Poco::toLowerInPlace(DefFirmware.deviceType);
 | 
								Poco::toLowerInPlace(DefFirmware.deviceType);
 | 
				
			||||||
@@ -143,7 +146,7 @@ namespace OpenWifi {
 | 
				
			|||||||
				Poco::Data::Keywords::use(R),
 | 
									Poco::Data::Keywords::use(R),
 | 
				
			||||||
				Poco::Data::Keywords::use(DefFirmware.deviceType);
 | 
									Poco::Data::Keywords::use(DefFirmware.deviceType);
 | 
				
			||||||
			Update.execute();
 | 
								Update.execute();
 | 
				
			||||||
 | 
								Sess.commit();
 | 
				
			||||||
			return true;
 | 
								return true;
 | 
				
			||||||
		} catch (const Poco::Exception &E) {
 | 
							} catch (const Poco::Exception &E) {
 | 
				
			||||||
			poco_warning(Logger(), fmt::format("{}: Failed with: {}", std::string(__func__),
 | 
								poco_warning(Logger(), fmt::format("{}: Failed with: {}", std::string(__func__),
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -72,6 +72,7 @@ namespace OpenWifi {
 | 
				
			|||||||
			Config::Config Cfg(DefConfig.Configuration);
 | 
								Config::Config Cfg(DefConfig.Configuration);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if (Cfg.Valid()) {
 | 
								if (Cfg.Valid()) {
 | 
				
			||||||
 | 
									Sess.begin();
 | 
				
			||||||
				Poco::Data::Statement Insert(Sess);
 | 
									Poco::Data::Statement Insert(Sess);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				std::string St{"INSERT INTO DefaultConfigs ( " + DB_DefConfig_SelectFields +
 | 
									std::string St{"INSERT INTO DefaultConfigs ( " + DB_DefConfig_SelectFields +
 | 
				
			||||||
@@ -83,6 +84,7 @@ namespace OpenWifi {
 | 
				
			|||||||
				Convert(DefConfig, R);
 | 
									Convert(DefConfig, R);
 | 
				
			||||||
				Insert << ConvertParams(St), Poco::Data::Keywords::use(R);
 | 
									Insert << ConvertParams(St), Poco::Data::Keywords::use(R);
 | 
				
			||||||
				Insert.execute();
 | 
									Insert.execute();
 | 
				
			||||||
 | 
									Sess.commit();
 | 
				
			||||||
				return true;
 | 
									return true;
 | 
				
			||||||
			} else {
 | 
								} else {
 | 
				
			||||||
				poco_warning(Logger(), "Cannot create device: invalid configuration.");
 | 
									poco_warning(Logger(), "Cannot create device: invalid configuration.");
 | 
				
			||||||
@@ -99,13 +101,14 @@ namespace OpenWifi {
 | 
				
			|||||||
		try {
 | 
							try {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			Poco::Data::Session Sess = Pool_->get();
 | 
								Poco::Data::Session Sess = Pool_->get();
 | 
				
			||||||
 | 
								Sess.begin();
 | 
				
			||||||
			Poco::Data::Statement Delete(Sess);
 | 
								Poco::Data::Statement Delete(Sess);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			std::string St{"DELETE FROM DefaultConfigs WHERE Name=?"};
 | 
								std::string St{"DELETE FROM DefaultConfigs WHERE Name=?"};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			Delete << ConvertParams(St), Poco::Data::Keywords::use(Name);
 | 
								Delete << ConvertParams(St), Poco::Data::Keywords::use(Name);
 | 
				
			||||||
			Delete.execute();
 | 
								Delete.execute();
 | 
				
			||||||
 | 
								Sess.commit();
 | 
				
			||||||
			return true;
 | 
								return true;
 | 
				
			||||||
		} catch (const Poco::Exception &E) {
 | 
							} catch (const Poco::Exception &E) {
 | 
				
			||||||
			poco_warning(Logger(), fmt::format("{}: Failed with: {}", std::string(__func__),
 | 
								poco_warning(Logger(), fmt::format("{}: Failed with: {}", std::string(__func__),
 | 
				
			||||||
@@ -117,9 +120,9 @@ namespace OpenWifi {
 | 
				
			|||||||
	bool Storage::UpdateDefaultConfiguration(std::string &Name,
 | 
						bool Storage::UpdateDefaultConfiguration(std::string &Name,
 | 
				
			||||||
											 GWObjects::DefaultConfiguration &DefConfig) {
 | 
																 GWObjects::DefaultConfiguration &DefConfig) {
 | 
				
			||||||
		try {
 | 
							try {
 | 
				
			||||||
 | 
								uint64_t Now = Utils::Now();
 | 
				
			||||||
			Poco::Data::Session Sess = Pool_->get();
 | 
								Poco::Data::Session Sess = Pool_->get();
 | 
				
			||||||
 | 
								Sess.begin();
 | 
				
			||||||
			uint64_t Now = time(nullptr);
 | 
					 | 
				
			||||||
			Poco::Data::Statement Update(Sess);
 | 
								Poco::Data::Statement Update(Sess);
 | 
				
			||||||
			DefConfig.LastModified = Now;
 | 
								DefConfig.LastModified = Now;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -132,6 +135,7 @@ namespace OpenWifi {
 | 
				
			|||||||
			Update << ConvertParams(St), Poco::Data::Keywords::use(R),
 | 
								Update << ConvertParams(St), Poco::Data::Keywords::use(R),
 | 
				
			||||||
				Poco::Data::Keywords::use(Name);
 | 
									Poco::Data::Keywords::use(Name);
 | 
				
			||||||
			Update.execute();
 | 
								Update.execute();
 | 
				
			||||||
 | 
								Sess.commit();
 | 
				
			||||||
			return true;
 | 
								return true;
 | 
				
			||||||
		} catch (const Poco::Exception &E) {
 | 
							} catch (const Poco::Exception &E) {
 | 
				
			||||||
			poco_warning(Logger(), fmt::format("{}: Failed with: {}", std::string(__func__),
 | 
								poco_warning(Logger(), fmt::format("{}: Failed with: {}", std::string(__func__),
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -210,7 +210,7 @@ namespace OpenWifi {
 | 
				
			|||||||
		return false;
 | 
							return false;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	bool Storage::UpdateDeviceConfiguration(std::string &SerialNumber, std::string &Configuration,
 | 
					/*	bool Storage::UpdateDeviceConfiguration(std::string &SerialNumber, std::string &Configuration,
 | 
				
			||||||
											uint64_t &NewUUID) {
 | 
																uint64_t &NewUUID) {
 | 
				
			||||||
		try {
 | 
							try {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -255,7 +255,7 @@ namespace OpenWifi {
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
		return false;
 | 
							return false;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
	bool Storage::RollbackDeviceConfigurationChange(std::string & SerialNumber) {
 | 
						bool Storage::RollbackDeviceConfigurationChange(std::string & SerialNumber) {
 | 
				
			||||||
		try {
 | 
							try {
 | 
				
			||||||
			GWObjects::Device D;
 | 
								GWObjects::Device D;
 | 
				
			||||||
@@ -268,6 +268,7 @@ namespace OpenWifi {
 | 
				
			|||||||
			ConfigurationCache().Add(Utils::SerialNumberToInt(SerialNumber), D.UUID);
 | 
								ConfigurationCache().Add(Utils::SerialNumberToInt(SerialNumber), D.UUID);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			Poco::Data::Session Sess = Pool_->get();
 | 
								Poco::Data::Session Sess = Pool_->get();
 | 
				
			||||||
 | 
								Sess.begin();
 | 
				
			||||||
			Poco::Data::Statement Update(Sess);
 | 
								Poco::Data::Statement Update(Sess);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			DeviceRecordTuple R;
 | 
								DeviceRecordTuple R;
 | 
				
			||||||
@@ -277,6 +278,7 @@ namespace OpenWifi {
 | 
				
			|||||||
			Update << ConvertParams(St2), Poco::Data::Keywords::use(R),
 | 
								Update << ConvertParams(St2), Poco::Data::Keywords::use(R),
 | 
				
			||||||
				Poco::Data::Keywords::use(SerialNumber);
 | 
									Poco::Data::Keywords::use(SerialNumber);
 | 
				
			||||||
			Update.execute();
 | 
								Update.execute();
 | 
				
			||||||
 | 
								Sess.commit();
 | 
				
			||||||
			return true;
 | 
								return true;
 | 
				
			||||||
		} catch (const Poco::Exception &E) {
 | 
							} catch (const Poco::Exception &E) {
 | 
				
			||||||
			Logger().log(E);
 | 
								Logger().log(E);
 | 
				
			||||||
@@ -285,6 +287,16 @@ namespace OpenWifi {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	bool Storage::CompleteDeviceConfigurationChange(std::string & SerialNumber) {
 | 
						bool Storage::CompleteDeviceConfigurationChange(std::string & SerialNumber) {
 | 
				
			||||||
 | 
							try {
 | 
				
			||||||
 | 
								auto Session = Pool_->get();
 | 
				
			||||||
 | 
								return CompleteDeviceConfigurationChange(Session, SerialNumber);
 | 
				
			||||||
 | 
							} catch (const Poco::Exception &E) {
 | 
				
			||||||
 | 
								Logger().log(E);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return false;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						bool Storage::CompleteDeviceConfigurationChange(Poco::Data::Session & Session, std::string & SerialNumber) {
 | 
				
			||||||
		try {
 | 
							try {
 | 
				
			||||||
			GWObjects::Device D;
 | 
								GWObjects::Device D;
 | 
				
			||||||
			if (!GetDevice(SerialNumber, D))
 | 
								if (!GetDevice(SerialNumber, D))
 | 
				
			||||||
@@ -300,8 +312,8 @@ namespace OpenWifi {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
			ConfigurationCache().Add(Utils::SerialNumberToInt(SerialNumber), D.UUID);
 | 
								ConfigurationCache().Add(Utils::SerialNumberToInt(SerialNumber), D.UUID);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			Poco::Data::Session Sess = Pool_->get();
 | 
								Session.begin();
 | 
				
			||||||
			Poco::Data::Statement Update(Sess);
 | 
								Poco::Data::Statement Update(Session);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			DeviceRecordTuple R;
 | 
								DeviceRecordTuple R;
 | 
				
			||||||
			ConvertDeviceRecord(D, R);
 | 
								ConvertDeviceRecord(D, R);
 | 
				
			||||||
@@ -310,6 +322,7 @@ namespace OpenWifi {
 | 
				
			|||||||
			Update << ConvertParams(St2), Poco::Data::Keywords::use(R),
 | 
								Update << ConvertParams(St2), Poco::Data::Keywords::use(R),
 | 
				
			||||||
				Poco::Data::Keywords::use(SerialNumber);
 | 
									Poco::Data::Keywords::use(SerialNumber);
 | 
				
			||||||
			Update.execute();
 | 
								Update.execute();
 | 
				
			||||||
 | 
								Session.commit();
 | 
				
			||||||
			return true;
 | 
								return true;
 | 
				
			||||||
		} catch (const Poco::Exception &E) {
 | 
							} catch (const Poco::Exception &E) {
 | 
				
			||||||
			Logger().log(E);
 | 
								Logger().log(E);
 | 
				
			||||||
@@ -328,13 +341,12 @@ namespace OpenWifi {
 | 
				
			|||||||
				return false;
 | 
									return false;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			Poco::Data::Session Sess = Pool_->get();
 | 
					 | 
				
			||||||
			Poco::Data::Statement Select(Sess);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
			GWObjects::Device D;
 | 
								GWObjects::Device D;
 | 
				
			||||||
			if (!GetDevice(SerialNumber, D))
 | 
								if (!GetDevice(SerialNumber, D))
 | 
				
			||||||
				return false;
 | 
									return false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			uint64_t Now = time(nullptr);
 | 
								uint64_t Now = time(nullptr);
 | 
				
			||||||
			if(NewUUID==0) {
 | 
								if(NewUUID==0) {
 | 
				
			||||||
				D.pendingUUID = NewUUID = (D.LastConfigurationChange == Now ? Now + 1 : Now);
 | 
									D.pendingUUID = NewUUID = (D.LastConfigurationChange == Now ? Now + 1 : Now);
 | 
				
			||||||
@@ -343,6 +355,8 @@ namespace OpenWifi {
 | 
				
			|||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if (Cfg.SetUUID(NewUUID)) {
 | 
								if (Cfg.SetUUID(NewUUID)) {
 | 
				
			||||||
 | 
									Poco::Data::Session Sess = Pool_->get();
 | 
				
			||||||
 | 
									Sess.begin();
 | 
				
			||||||
				Poco::Data::Statement Update(Sess);
 | 
									Poco::Data::Statement Update(Sess);
 | 
				
			||||||
				D.pendingConfiguration = Cfg.get();
 | 
									D.pendingConfiguration = Cfg.get();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -353,6 +367,7 @@ namespace OpenWifi {
 | 
				
			|||||||
				Update << ConvertParams(St2), Poco::Data::Keywords::use(R),
 | 
									Update << ConvertParams(St2), Poco::Data::Keywords::use(R),
 | 
				
			||||||
					Poco::Data::Keywords::use(SerialNumber);
 | 
										Poco::Data::Keywords::use(SerialNumber);
 | 
				
			||||||
				Update.execute();
 | 
									Update.execute();
 | 
				
			||||||
 | 
									Sess.commit();
 | 
				
			||||||
				poco_information(Logger(),
 | 
									poco_information(Logger(),
 | 
				
			||||||
								 fmt::format("DEVICE-PENDING-CONFIGURATION-UPDATED({}): New UUID is {}",
 | 
													 fmt::format("DEVICE-PENDING-CONFIGURATION-UPDATED({}): New UUID is {}",
 | 
				
			||||||
											 SerialNumber, NewUUID));
 | 
																 SerialNumber, NewUUID));
 | 
				
			||||||
@@ -366,68 +381,74 @@ namespace OpenWifi {
 | 
				
			|||||||
		return false;
 | 
							return false;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	bool Storage::SetDeviceLastRecordedContact(std::string &SerialNumber, std::uint64_t lastRecordedContact) {
 | 
						bool Storage::SetDeviceLastRecordedContact(LockedDbSession &Session, std::string &SerialNumber, std::uint64_t lastRecordedContact) {
 | 
				
			||||||
		try {
 | 
							try {
 | 
				
			||||||
			Poco::Data::Session 	Sess = Pool_->get();
 | 
								std::lock_guard		Lock(Session.Mutex());
 | 
				
			||||||
			Poco::Data::Statement 	Update(Sess);
 | 
								return SetDeviceLastRecordedContact(Session.Session(), SerialNumber, lastRecordedContact);
 | 
				
			||||||
			std::string St{"UPDATE Devices SET lastRecordedContact=?  WHERE SerialNumber=?"};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			Update << ConvertParams(St), Poco::Data::Keywords::use(lastRecordedContact),
 | 
					 | 
				
			||||||
				Poco::Data::Keywords::use(SerialNumber);
 | 
					 | 
				
			||||||
			Update.execute();
 | 
					 | 
				
			||||||
			return true;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		} catch (const Poco::Exception &E) {
 | 
							} catch (const Poco::Exception &E) {
 | 
				
			||||||
			Logger().log(E);
 | 
								Logger().log(E);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		return false;
 | 
							return false;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	bool Storage::CreateDevice(GWObjects::Device &DeviceDetails) {
 | 
						bool Storage::SetDeviceLastRecordedContact(Poco::Data::Session &Session, std::string &SerialNumber, std::uint64_t lastRecordedContact) {
 | 
				
			||||||
 | 
							try {
 | 
				
			||||||
 | 
								Session.begin();
 | 
				
			||||||
 | 
								Poco::Data::Statement 	Update(Session);
 | 
				
			||||||
 | 
								std::string St{"UPDATE Devices SET lastRecordedContact=?  WHERE SerialNumber=?"};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								Update << ConvertParams(St), Poco::Data::Keywords::use(lastRecordedContact),
 | 
				
			||||||
 | 
									Poco::Data::Keywords::use(SerialNumber);
 | 
				
			||||||
 | 
								Update.execute();
 | 
				
			||||||
 | 
								Session.commit();
 | 
				
			||||||
 | 
								return true;
 | 
				
			||||||
 | 
							} catch (const Poco::Exception &E) {
 | 
				
			||||||
 | 
								Logger().log(E);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return false;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						bool Storage::SetDeviceLastRecordedContact(std::string &SerialNumber, std::uint64_t lastRecordedContact) {
 | 
				
			||||||
 | 
							try {
 | 
				
			||||||
 | 
								auto Session = Pool_->get();
 | 
				
			||||||
 | 
								return SetDeviceLastRecordedContact(Session, SerialNumber, lastRecordedContact);
 | 
				
			||||||
 | 
							} catch (const Poco::Exception &E) {
 | 
				
			||||||
 | 
								Logger().log(E);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return false;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						bool Storage::CreateDevice(Poco::Data::Session &Sess, GWObjects::Device &DeviceDetails) {
 | 
				
			||||||
		std::string SerialNumber;
 | 
							std::string SerialNumber;
 | 
				
			||||||
		try {
 | 
							try {
 | 
				
			||||||
 | 
								Config::Config Cfg(DeviceDetails.Configuration);
 | 
				
			||||||
 | 
								uint64_t Now = Utils::Now();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			Poco::Data::Session Sess = Pool_->get();
 | 
								DeviceDetails.modified = Utils::Now();
 | 
				
			||||||
			Poco::Data::Statement Select(Sess);
 | 
								DeviceDetails.CreationTimestamp = DeviceDetails.LastConfigurationDownload =
 | 
				
			||||||
 | 
									DeviceDetails.UUID = DeviceDetails.LastConfigurationChange = Now;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			std::string St{"SELECT SerialNumber FROM Devices WHERE SerialNumber=?"};
 | 
								if (Cfg.Valid() && Cfg.SetUUID(DeviceDetails.UUID)) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
//			Select << ConvertParams(St), Poco::Data::Keywords::into(SerialNumber),
 | 
									DeviceDetails.Configuration = Cfg.get();
 | 
				
			||||||
//				Poco::Data::Keywords::use(DeviceDetails.SerialNumber);
 | 
									Sess.begin();
 | 
				
			||||||
//			Select.execute();
 | 
									Poco::Data::Statement Insert(Sess);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
//			if (Select.rowsExtracted() == 0) {
 | 
									std::string St2{"INSERT INTO Devices ( " + DB_DeviceSelectFields + " ) " +
 | 
				
			||||||
				Config::Config Cfg(DeviceDetails.Configuration);
 | 
													DB_DeviceInsertValues + " ON CONFLICT (SerialNumber) DO NOTHING"};
 | 
				
			||||||
				uint64_t Now = Utils::Now();
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
				DeviceDetails.modified = Utils::Now();
 | 
									SetCurrentConfigurationID(DeviceDetails.SerialNumber, DeviceDetails.UUID);
 | 
				
			||||||
				DeviceDetails.CreationTimestamp = DeviceDetails.LastConfigurationDownload =
 | 
									DeviceRecordTuple R;
 | 
				
			||||||
					DeviceDetails.UUID = DeviceDetails.LastConfigurationChange = Now;
 | 
									ConvertDeviceRecord(DeviceDetails, R);
 | 
				
			||||||
 | 
									Insert << ConvertParams(St2), Poco::Data::Keywords::use(R);
 | 
				
			||||||
				if (Cfg.Valid() && Cfg.SetUUID(DeviceDetails.UUID)) {
 | 
									Insert.execute();
 | 
				
			||||||
 | 
									Sess.commit();
 | 
				
			||||||
					DeviceDetails.Configuration = Cfg.get();
 | 
									SetCurrentConfigurationID(DeviceDetails.SerialNumber, DeviceDetails.UUID);
 | 
				
			||||||
					Poco::Data::Statement Insert(Sess);
 | 
									SerialNumberCache()->AddSerialNumber(DeviceDetails.SerialNumber);
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
					std::string St2{"INSERT INTO Devices ( " + DB_DeviceSelectFields + " ) " +
 | 
									poco_warning(Logger(), "Cannot create device: invalid configuration.");
 | 
				
			||||||
									DB_DeviceInsertValues + " ON CONFLICT (SerialNumber) DO NOTHING"};
 | 
									return false;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
					SetCurrentConfigurationID(DeviceDetails.SerialNumber, DeviceDetails.UUID);
 | 
					 | 
				
			||||||
					DeviceRecordTuple R;
 | 
					 | 
				
			||||||
					ConvertDeviceRecord(DeviceDetails, R);
 | 
					 | 
				
			||||||
					Insert << ConvertParams(St2), Poco::Data::Keywords::use(R);
 | 
					 | 
				
			||||||
					Insert.execute();
 | 
					 | 
				
			||||||
					SetCurrentConfigurationID(DeviceDetails.SerialNumber, DeviceDetails.UUID);
 | 
					 | 
				
			||||||
					SerialNumberCache()->AddSerialNumber(DeviceDetails.SerialNumber);
 | 
					 | 
				
			||||||
					return true;
 | 
					 | 
				
			||||||
				} else {
 | 
					 | 
				
			||||||
					poco_warning(Logger(), "Cannot create device: invalid configuration.");
 | 
					 | 
				
			||||||
					return false;
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
//			} else {
 | 
					 | 
				
			||||||
//				poco_warning(Logger(), fmt::format("Device {} already exists.", SerialNumber));
 | 
					 | 
				
			||||||
//				return false;
 | 
					 | 
				
			||||||
//			}
 | 
					 | 
				
			||||||
			return true;
 | 
								return true;
 | 
				
			||||||
		} catch (const Poco::Exception &E) {
 | 
							} catch (const Poco::Exception &E) {
 | 
				
			||||||
			Logger().log(E);
 | 
								Logger().log(E);
 | 
				
			||||||
@@ -435,6 +456,26 @@ namespace OpenWifi {
 | 
				
			|||||||
		return false;
 | 
							return false;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						bool Storage::CreateDevice(LockedDbSession &Session, GWObjects::Device &DeviceDetails) {
 | 
				
			||||||
 | 
							try {
 | 
				
			||||||
 | 
								std::lock_guard	Lock(Session.Mutex());
 | 
				
			||||||
 | 
								return CreateDevice(Session.Session(), DeviceDetails);
 | 
				
			||||||
 | 
							} catch (const Poco::Exception &E) {
 | 
				
			||||||
 | 
								Logger().log(E);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return false;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							bool Storage::CreateDevice(GWObjects::Device &DeviceDetails) {
 | 
				
			||||||
 | 
							try {
 | 
				
			||||||
 | 
								auto Session = Pool_->get();
 | 
				
			||||||
 | 
								return CreateDevice(Session, DeviceDetails);
 | 
				
			||||||
 | 
							} catch (const Poco::Exception &E) {
 | 
				
			||||||
 | 
								Logger().log(E);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return false;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	static std::string InsertRadiosCountyRegulation(std::string &Config,
 | 
						static std::string InsertRadiosCountyRegulation(std::string &Config,
 | 
				
			||||||
													const Poco::Net::IPAddress &IPAddress) {
 | 
																		const Poco::Net::IPAddress &IPAddress) {
 | 
				
			||||||
		std::string FoundCountry;
 | 
							std::string FoundCountry;
 | 
				
			||||||
@@ -487,16 +528,15 @@ namespace OpenWifi {
 | 
				
			|||||||
		return true;
 | 
							return true;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define __DBGLOG__ std::cout << __LINE__ << std::endl;
 | 
						bool Storage::CreateDefaultDevice(Poco::Data::Session &Session, std::string &SerialNumber, const Config::Capabilities &Caps,
 | 
				
			||||||
 | 
					 | 
				
			||||||
	bool Storage::CreateDefaultDevice(std::string &SerialNumber, const Config::Capabilities &Caps,
 | 
					 | 
				
			||||||
									  std::string &Firmware,
 | 
														  std::string &Firmware,
 | 
				
			||||||
									  const Poco::Net::IPAddress &IPAddress,
 | 
														  const Poco::Net::IPAddress &IPAddress,
 | 
				
			||||||
									  bool simulated) {
 | 
														  bool simulated) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		GWObjects::Device D;
 | 
							GWObjects::Device D;
 | 
				
			||||||
		poco_information(Logger(), fmt::format("AUTO-CREATION({})", SerialNumber));
 | 
					
 | 
				
			||||||
		uint64_t Now = time(nullptr);
 | 
							// poco_information(Logger(), fmt::format("AUTO-CREATION({}): Start.", SerialNumber));
 | 
				
			||||||
 | 
							uint64_t Now = Utils::Now();
 | 
				
			||||||
		GWObjects::DefaultConfiguration DefConfig;
 | 
							GWObjects::DefaultConfiguration DefConfig;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (!Caps.Platform().empty() && !Caps.Compatible().empty()) {
 | 
							if (!Caps.Platform().empty() && !Caps.Compatible().empty()) {
 | 
				
			||||||
@@ -539,12 +579,13 @@ namespace OpenWifi {
 | 
				
			|||||||
		D.Notes = SecurityObjects::NoteInfoVec{
 | 
							D.Notes = SecurityObjects::NoteInfoVec{
 | 
				
			||||||
			SecurityObjects::NoteInfo{(uint64_t)Utils::Now(), "", "Auto-provisioned."}};
 | 
								SecurityObjects::NoteInfo{(uint64_t)Utils::Now(), "", "Auto-provisioned."}};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		CreateDeviceCapabilities(SerialNumber, Caps);
 | 
							CreateDeviceCapabilities(Session, SerialNumber, Caps);
 | 
				
			||||||
 | 
							auto Result = CreateDevice(Session, D);
 | 
				
			||||||
		return CreateDevice(D);
 | 
							poco_information(Logger(), fmt::format("AUTO-CREATION({}): Done, Result={}", SerialNumber, Result));
 | 
				
			||||||
 | 
							return Result;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	bool Storage::GetDeviceFWUpdatePolicy(std::string &SerialNumber, std::string &Policy) {
 | 
					/*	bool Storage::GetDeviceFWUpdatePolicy(std::string &SerialNumber, std::string &Policy) {
 | 
				
			||||||
		try {
 | 
							try {
 | 
				
			||||||
			Poco::Data::Session Sess = Pool_->get();
 | 
								Poco::Data::Session Sess = Pool_->get();
 | 
				
			||||||
			Poco::Data::Statement Select(Sess);
 | 
								Poco::Data::Statement Select(Sess);
 | 
				
			||||||
@@ -559,46 +600,19 @@ namespace OpenWifi {
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
		return false;
 | 
							return false;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
	bool Storage::SetDevicePassword(std::string &SerialNumber, std::string &Password) {
 | 
						bool Storage::SetDevicePassword(LockedDbSession &Sess, std::string &SerialNumber, std::string &Password) {
 | 
				
			||||||
		try {
 | 
							try {
 | 
				
			||||||
			Poco::Data::Session Sess = Pool_->get();
 | 
								std::lock_guard		Lock(Sess.Mutex());
 | 
				
			||||||
			Poco::Data::Statement Update(Sess);
 | 
								Sess.Session().begin();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								Poco::Data::Statement Update(Sess.Session());
 | 
				
			||||||
			std::string St{"UPDATE Devices SET DevicePassword=?  WHERE SerialNumber=?"};
 | 
								std::string St{"UPDATE Devices SET DevicePassword=?  WHERE SerialNumber=?"};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			Update << ConvertParams(St), Poco::Data::Keywords::use(Password),
 | 
								Update << ConvertParams(St), Poco::Data::Keywords::use(Password),
 | 
				
			||||||
				Poco::Data::Keywords::use(SerialNumber);
 | 
									Poco::Data::Keywords::use(SerialNumber);
 | 
				
			||||||
			Update.execute();
 | 
								Update.execute();
 | 
				
			||||||
			return true;
 | 
								Sess.Session().commit();
 | 
				
			||||||
		} catch (const Poco::Exception &E) {
 | 
					 | 
				
			||||||
			Logger().log(E);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		return false;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	bool Storage::SetConnectInfo(std::string &SerialNumber, std::string &Firmware) {
 | 
					 | 
				
			||||||
		try {
 | 
					 | 
				
			||||||
			Poco::Data::Session Sess = Pool_->get();
 | 
					 | 
				
			||||||
			Poco::Data::Statement Select(Sess);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			//	Get the old version and if they do not match, set the last date
 | 
					 | 
				
			||||||
			std::string St{"SELECT Firmware FROM Devices  WHERE SerialNumber=?"};
 | 
					 | 
				
			||||||
			std::string TmpFirmware;
 | 
					 | 
				
			||||||
			Select << ConvertParams(St), Poco::Data::Keywords::into(TmpFirmware),
 | 
					 | 
				
			||||||
				Poco::Data::Keywords::use(SerialNumber);
 | 
					 | 
				
			||||||
			Select.execute();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			if (TmpFirmware != Firmware) {
 | 
					 | 
				
			||||||
				Poco::Data::Statement Update(Sess);
 | 
					 | 
				
			||||||
				std::string St2{
 | 
					 | 
				
			||||||
					"UPDATE Devices SET Firmware=?, LastFWUpdate=? WHERE SerialNumber=?"};
 | 
					 | 
				
			||||||
				uint64_t Now = Utils::Now();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				Update << ConvertParams(St2), Poco::Data::Keywords::use(Firmware),
 | 
					 | 
				
			||||||
					Poco::Data::Keywords::use(Now), Poco::Data::Keywords::use(SerialNumber);
 | 
					 | 
				
			||||||
				Update.execute();
 | 
					 | 
				
			||||||
				return true;
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			return true;
 | 
								return true;
 | 
				
			||||||
		} catch (const Poco::Exception &E) {
 | 
							} catch (const Poco::Exception &E) {
 | 
				
			||||||
			Logger().log(E);
 | 
								Logger().log(E);
 | 
				
			||||||
@@ -614,12 +628,14 @@ namespace OpenWifi {
 | 
				
			|||||||
			for (const auto &tableName : TableNames) {
 | 
								for (const auto &tableName : TableNames) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				Poco::Data::Session Sess = Pool_->get();
 | 
									Poco::Data::Session Sess = Pool_->get();
 | 
				
			||||||
 | 
									Sess.begin();
 | 
				
			||||||
				Poco::Data::Statement Delete(Sess);
 | 
									Poco::Data::Statement Delete(Sess);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				std::string St = fmt::format("DELETE FROM {} WHERE SerialNumber='{}'", tableName, SerialNumber);
 | 
									std::string St = fmt::format("DELETE FROM {} WHERE SerialNumber='{}'", tableName, SerialNumber);
 | 
				
			||||||
				try {
 | 
									try {
 | 
				
			||||||
					Delete << St;
 | 
										Delete << St;
 | 
				
			||||||
					Delete.execute();
 | 
										Delete.execute();
 | 
				
			||||||
 | 
										Sess.commit();
 | 
				
			||||||
				} catch (...) {
 | 
									} catch (...) {
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
@@ -692,11 +708,9 @@ namespace OpenWifi {
 | 
				
			|||||||
		return false;
 | 
							return false;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	bool Storage::GetDevice(std::string &SerialNumber, GWObjects::Device &DeviceDetails) {
 | 
						bool Storage::GetDevice(Poco::Data::Session &Session, std::string &SerialNumber, GWObjects::Device &DeviceDetails) {
 | 
				
			||||||
		try {
 | 
							try {
 | 
				
			||||||
			Poco::Data::Session Sess = Pool_->get();
 | 
								Poco::Data::Statement Select(Session);
 | 
				
			||||||
			Poco::Data::Statement Select(Sess);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			std::string St{"SELECT " + DB_DeviceSelectFields +
 | 
								std::string St{"SELECT " + DB_DeviceSelectFields +
 | 
				
			||||||
						   " FROM Devices WHERE SerialNumber=?"};
 | 
											   " FROM Devices WHERE SerialNumber=?"};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -715,6 +729,26 @@ namespace OpenWifi {
 | 
				
			|||||||
		return false;
 | 
							return false;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						bool Storage::GetDevice(std::string &SerialNumber, GWObjects::Device &DeviceDetails) {
 | 
				
			||||||
 | 
							try {
 | 
				
			||||||
 | 
								auto Sess = Pool_->get();
 | 
				
			||||||
 | 
								return GetDevice(Sess, SerialNumber, DeviceDetails);
 | 
				
			||||||
 | 
							} catch (const Poco::Exception &E) {
 | 
				
			||||||
 | 
								Logger().log(E);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return false;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						bool Storage::GetDevice(LockedDbSession &Session, std::string &SerialNumber, GWObjects::Device &DeviceDetails) {
 | 
				
			||||||
 | 
							try {
 | 
				
			||||||
 | 
								std::lock_guard		Lock(Session.Mutex());
 | 
				
			||||||
 | 
								return GetDevice(Session.Session(), SerialNumber, DeviceDetails);
 | 
				
			||||||
 | 
							} catch (const Poco::Exception &E) {
 | 
				
			||||||
 | 
								Logger().log(E);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return false;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	bool Storage::DeviceExists(std::string &SerialNumber) {
 | 
						bool Storage::DeviceExists(std::string &SerialNumber) {
 | 
				
			||||||
		try {
 | 
							try {
 | 
				
			||||||
			Poco::Data::Session Sess = Pool_->get();
 | 
								Poco::Data::Session Sess = Pool_->get();
 | 
				
			||||||
@@ -741,6 +775,26 @@ namespace OpenWifi {
 | 
				
			|||||||
	bool Storage::UpdateDevice(GWObjects::Device &NewDeviceDetails) {
 | 
						bool Storage::UpdateDevice(GWObjects::Device &NewDeviceDetails) {
 | 
				
			||||||
		try {
 | 
							try {
 | 
				
			||||||
			Poco::Data::Session Sess = Pool_->get();
 | 
								Poco::Data::Session Sess = Pool_->get();
 | 
				
			||||||
 | 
								return UpdateDevice(Sess, NewDeviceDetails);
 | 
				
			||||||
 | 
							} catch (const Poco::Exception &E) {
 | 
				
			||||||
 | 
								Logger().log(E);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return false;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						bool Storage::UpdateDevice(LockedDbSession &Session, GWObjects::Device &NewDeviceDetails) {
 | 
				
			||||||
 | 
							try {
 | 
				
			||||||
 | 
								std::lock_guard Lock(Session.Mutex());
 | 
				
			||||||
 | 
								return UpdateDevice(Session.Session(), NewDeviceDetails);
 | 
				
			||||||
 | 
							} catch (const Poco::Exception &E) {
 | 
				
			||||||
 | 
								Logger().log(E);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return false;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						bool Storage::UpdateDevice(Poco::Data::Session &Sess, GWObjects::Device &NewDeviceDetails) {
 | 
				
			||||||
 | 
							try {
 | 
				
			||||||
 | 
								Sess.begin();
 | 
				
			||||||
			Poco::Data::Statement Update(Sess);
 | 
								Poco::Data::Statement Update(Sess);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			DeviceRecordTuple R;
 | 
								DeviceRecordTuple R;
 | 
				
			||||||
@@ -753,6 +807,7 @@ namespace OpenWifi {
 | 
				
			|||||||
			Update << ConvertParams(St2), Poco::Data::Keywords::use(R),
 | 
								Update << ConvertParams(St2), Poco::Data::Keywords::use(R),
 | 
				
			||||||
				Poco::Data::Keywords::use(NewDeviceDetails.SerialNumber);
 | 
									Poco::Data::Keywords::use(NewDeviceDetails.SerialNumber);
 | 
				
			||||||
			Update.execute();
 | 
								Update.execute();
 | 
				
			||||||
 | 
								Sess.commit();
 | 
				
			||||||
			// GetDevice(NewDeviceDetails.SerialNumber,NewDeviceDetails);
 | 
								// GetDevice(NewDeviceDetails.SerialNumber,NewDeviceDetails);
 | 
				
			||||||
			return true;
 | 
								return true;
 | 
				
			||||||
		} catch (const Poco::Exception &E) {
 | 
							} catch (const Poco::Exception &E) {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -35,10 +35,11 @@ namespace OpenWifi {
 | 
				
			|||||||
		R.set<4>(H.Recorded);
 | 
							R.set<4>(H.Recorded);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	bool Storage::AddHealthCheckData(const GWObjects::HealthCheck &Check) {
 | 
						bool Storage::AddHealthCheckData(LockedDbSession &Session, const GWObjects::HealthCheck &Check) {
 | 
				
			||||||
		try {
 | 
							try {
 | 
				
			||||||
			Poco::Data::Session Sess = Pool_->get();
 | 
								std::lock_guard Guard(Session.Mutex());
 | 
				
			||||||
			Poco::Data::Statement Insert(Sess);
 | 
								Session.Session().begin();
 | 
				
			||||||
 | 
								Poco::Data::Statement Insert(Session.Session());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			std::string St{"INSERT INTO HealthChecks ( " + DB_HealthCheckSelectFields +
 | 
								std::string St{"INSERT INTO HealthChecks ( " + DB_HealthCheckSelectFields +
 | 
				
			||||||
						   " ) VALUES( " + DB_HealthCheckInsertValues + " )"};
 | 
											   " ) VALUES( " + DB_HealthCheckInsertValues + " )"};
 | 
				
			||||||
@@ -47,6 +48,7 @@ namespace OpenWifi {
 | 
				
			|||||||
			ConvertHealthCheckRecord(Check, R);
 | 
								ConvertHealthCheckRecord(Check, R);
 | 
				
			||||||
			Insert << ConvertParams(St), Poco::Data::Keywords::use(R);
 | 
								Insert << ConvertParams(St), Poco::Data::Keywords::use(R);
 | 
				
			||||||
			Insert.execute();
 | 
								Insert.execute();
 | 
				
			||||||
 | 
								Session.Session().commit();
 | 
				
			||||||
			return true;
 | 
								return true;
 | 
				
			||||||
		} catch (const Poco::Exception &E) {
 | 
							} catch (const Poco::Exception &E) {
 | 
				
			||||||
			poco_warning(Logger(), fmt::format("{}: Failed with: {}", std::string(__func__),
 | 
								poco_warning(Logger(), fmt::format("{}: Failed with: {}", std::string(__func__),
 | 
				
			||||||
@@ -134,7 +136,7 @@ namespace OpenWifi {
 | 
				
			|||||||
										uint64_t ToDate) {
 | 
															uint64_t ToDate) {
 | 
				
			||||||
		try {
 | 
							try {
 | 
				
			||||||
			Poco::Data::Session Sess = Pool_->get();
 | 
								Poco::Data::Session Sess = Pool_->get();
 | 
				
			||||||
 | 
								Sess.begin();
 | 
				
			||||||
			bool DatesIncluded = (FromDate != 0 || ToDate != 0);
 | 
								bool DatesIncluded = (FromDate != 0 || ToDate != 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			std::string Prefix{"DELETE FROM HealthChecks "};
 | 
								std::string Prefix{"DELETE FROM HealthChecks "};
 | 
				
			||||||
@@ -158,7 +160,7 @@ namespace OpenWifi {
 | 
				
			|||||||
			Delete << Statement + DateSelector;
 | 
								Delete << Statement + DateSelector;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			Delete.execute();
 | 
								Delete.execute();
 | 
				
			||||||
 | 
								Sess.commit();
 | 
				
			||||||
			return true;
 | 
								return true;
 | 
				
			||||||
		} catch (const Poco::Exception &E) {
 | 
							} catch (const Poco::Exception &E) {
 | 
				
			||||||
			poco_warning(Logger(), fmt::format("{}: Failed with: {}", std::string(__func__),
 | 
								poco_warning(Logger(), fmt::format("{}: Failed with: {}", std::string(__func__),
 | 
				
			||||||
@@ -170,11 +172,13 @@ namespace OpenWifi {
 | 
				
			|||||||
	bool Storage::RemoveHealthChecksRecordsOlderThan(uint64_t Date) {
 | 
						bool Storage::RemoveHealthChecksRecordsOlderThan(uint64_t Date) {
 | 
				
			||||||
		try {
 | 
							try {
 | 
				
			||||||
			Poco::Data::Session Sess = Pool_->get();
 | 
								Poco::Data::Session Sess = Pool_->get();
 | 
				
			||||||
 | 
								Sess.begin();
 | 
				
			||||||
			Poco::Data::Statement Delete(Sess);
 | 
								Poco::Data::Statement Delete(Sess);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			std::string St1{"delete from HealthChecks where recorded<?"};
 | 
								std::string St1{"delete from HealthChecks where recorded<?"};
 | 
				
			||||||
			Delete << ConvertParams(St1), Poco::Data::Keywords::use(Date);
 | 
								Delete << ConvertParams(St1), Poco::Data::Keywords::use(Date);
 | 
				
			||||||
			Delete.execute();
 | 
								Delete.execute();
 | 
				
			||||||
 | 
								Sess.commit();
 | 
				
			||||||
			return true;
 | 
								return true;
 | 
				
			||||||
		} catch (const Poco::Exception &E) {
 | 
							} catch (const Poco::Exception &E) {
 | 
				
			||||||
			poco_warning(Logger(), fmt::format("{}: Failed with: {}", std::string(__func__),
 | 
								poco_warning(Logger(), fmt::format("{}: Failed with: {}", std::string(__func__),
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -39,11 +39,11 @@ namespace OpenWifi {
 | 
				
			|||||||
		R.set<6>(Log.UUID);
 | 
							R.set<6>(Log.UUID);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	bool Storage::AddLog(const GWObjects::DeviceLog &Log) {
 | 
						bool Storage::AddLog(LockedDbSession &Session, const GWObjects::DeviceLog &Log) {
 | 
				
			||||||
		try {
 | 
							try {
 | 
				
			||||||
 | 
								std::lock_guard Guard(Session.Mutex());
 | 
				
			||||||
			Poco::Data::Session Sess = Pool_->get();
 | 
								Session.Session().begin();
 | 
				
			||||||
			Poco::Data::Statement Insert(Sess);
 | 
								Poco::Data::Statement Insert(Session.Session());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			std::string St{"INSERT INTO DeviceLogs (" + DB_LogsSelectFields + ") values( " +
 | 
								std::string St{"INSERT INTO DeviceLogs (" + DB_LogsSelectFields + ") values( " +
 | 
				
			||||||
						   DB_LogsInsertValues + " )"};
 | 
											   DB_LogsInsertValues + " )"};
 | 
				
			||||||
@@ -53,6 +53,7 @@ namespace OpenWifi {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
			Insert << ConvertParams(St), Poco::Data::Keywords::use(R);
 | 
								Insert << ConvertParams(St), Poco::Data::Keywords::use(R);
 | 
				
			||||||
			Insert.execute();
 | 
								Insert.execute();
 | 
				
			||||||
 | 
								Session.Session().commit();
 | 
				
			||||||
			return true;
 | 
								return true;
 | 
				
			||||||
		} catch (const Poco::Exception &E) {
 | 
							} catch (const Poco::Exception &E) {
 | 
				
			||||||
			poco_warning(Logger(), fmt::format("{}: Failed with: {}", std::string(__func__),
 | 
								poco_warning(Logger(), fmt::format("{}: Failed with: {}", std::string(__func__),
 | 
				
			||||||
@@ -114,7 +115,7 @@ namespace OpenWifi {
 | 
				
			|||||||
								uint64_t Type) {
 | 
													uint64_t Type) {
 | 
				
			||||||
		try {
 | 
							try {
 | 
				
			||||||
			Poco::Data::Session Sess = Pool_->get();
 | 
								Poco::Data::Session Sess = Pool_->get();
 | 
				
			||||||
 | 
								Sess.begin();
 | 
				
			||||||
			bool DatesIncluded = (FromDate != 0 || ToDate != 0);
 | 
								bool DatesIncluded = (FromDate != 0 || ToDate != 0);
 | 
				
			||||||
			bool HasWhere = DatesIncluded || !SerialNumber.empty();
 | 
								bool HasWhere = DatesIncluded || !SerialNumber.empty();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -141,7 +142,7 @@ namespace OpenWifi {
 | 
				
			|||||||
			Delete << StatementStr + DateSelector + TypeSelector;
 | 
								Delete << StatementStr + DateSelector + TypeSelector;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			Delete.execute();
 | 
								Delete.execute();
 | 
				
			||||||
			Delete.reset(Sess);
 | 
								Sess.commit();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			return true;
 | 
								return true;
 | 
				
			||||||
		} catch (const Poco::Exception &E) {
 | 
							} catch (const Poco::Exception &E) {
 | 
				
			||||||
@@ -183,11 +184,13 @@ namespace OpenWifi {
 | 
				
			|||||||
	bool Storage::RemoveDeviceLogsRecordsOlderThan(uint64_t Date) {
 | 
						bool Storage::RemoveDeviceLogsRecordsOlderThan(uint64_t Date) {
 | 
				
			||||||
		try {
 | 
							try {
 | 
				
			||||||
			Poco::Data::Session Sess = Pool_->get();
 | 
								Poco::Data::Session Sess = Pool_->get();
 | 
				
			||||||
 | 
								Sess.begin();
 | 
				
			||||||
			Poco::Data::Statement Delete(Sess);
 | 
								Poco::Data::Statement Delete(Sess);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			std::string St1{"delete from DeviceLogs where recorded<?"};
 | 
								std::string St1{"delete from DeviceLogs where recorded<?"};
 | 
				
			||||||
			Delete << ConvertParams(St1), Poco::Data::Keywords::use(Date);
 | 
								Delete << ConvertParams(St1), Poco::Data::Keywords::use(Date);
 | 
				
			||||||
			Delete.execute();
 | 
								Delete.execute();
 | 
				
			||||||
 | 
								Sess.commit();
 | 
				
			||||||
			return true;
 | 
								return true;
 | 
				
			||||||
		} catch (const Poco::Exception &E) {
 | 
							} catch (const Poco::Exception &E) {
 | 
				
			||||||
			poco_warning(Logger(), fmt::format("{}: Failed with: {}", std::string(__func__),
 | 
								poco_warning(Logger(), fmt::format("{}: Failed with: {}", std::string(__func__),
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -8,7 +8,6 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#include "AP_WS_Server.h"
 | 
					#include "AP_WS_Server.h"
 | 
				
			||||||
#include "StorageService.h"
 | 
					#include "StorageService.h"
 | 
				
			||||||
 | 
					 | 
				
			||||||
#include "fmt/format.h"
 | 
					#include "fmt/format.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace OpenWifi {
 | 
					namespace OpenWifi {
 | 
				
			||||||
@@ -33,10 +32,10 @@ namespace OpenWifi {
 | 
				
			|||||||
		R.set<3>(Stats.Recorded);
 | 
							R.set<3>(Stats.Recorded);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	bool Storage::AddStatisticsData(const GWObjects::Statistics &Stats) {
 | 
						bool Storage::AddStatisticsData(Poco::Data::Session &Session, const GWObjects::Statistics &Stats) {
 | 
				
			||||||
		try {
 | 
							try {
 | 
				
			||||||
			Poco::Data::Session Sess(Pool_->get());
 | 
								Session.begin();
 | 
				
			||||||
			Poco::Data::Statement Insert(Sess);
 | 
								Poco::Data::Statement Insert(Session);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			poco_trace(Logger(), fmt::format("{}: Adding stats. Size={}", Stats.SerialNumber,
 | 
								poco_trace(Logger(), fmt::format("{}: Adding stats. Size={}", Stats.SerialNumber,
 | 
				
			||||||
											 std::to_string(Stats.Data.size())));
 | 
																 std::to_string(Stats.Data.size())));
 | 
				
			||||||
@@ -46,6 +45,7 @@ namespace OpenWifi {
 | 
				
			|||||||
			ConvertStatsRecord(Stats, R);
 | 
								ConvertStatsRecord(Stats, R);
 | 
				
			||||||
			Insert << ConvertParams(St), Poco::Data::Keywords::use(R);
 | 
								Insert << ConvertParams(St), Poco::Data::Keywords::use(R);
 | 
				
			||||||
			Insert.execute();
 | 
								Insert.execute();
 | 
				
			||||||
 | 
								Session.commit();
 | 
				
			||||||
			return true;
 | 
								return true;
 | 
				
			||||||
		} catch (const Poco::Exception &E) {
 | 
							} catch (const Poco::Exception &E) {
 | 
				
			||||||
			poco_warning(Logger(), fmt::format("{}: Failed with: {}", std::string(__func__),
 | 
								poco_warning(Logger(), fmt::format("{}: Failed with: {}", std::string(__func__),
 | 
				
			||||||
@@ -167,7 +167,7 @@ namespace OpenWifi {
 | 
				
			|||||||
									   uint64_t ToDate) {
 | 
														   uint64_t ToDate) {
 | 
				
			||||||
		try {
 | 
							try {
 | 
				
			||||||
			Poco::Data::Session Sess = Pool_->get();
 | 
								Poco::Data::Session Sess = Pool_->get();
 | 
				
			||||||
 | 
								Sess.begin();
 | 
				
			||||||
			bool DatesIncluded = (FromDate != 0 || ToDate != 0);
 | 
								bool DatesIncluded = (FromDate != 0 || ToDate != 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			std::string Prefix{"DELETE FROM Statistics "};
 | 
								std::string Prefix{"DELETE FROM Statistics "};
 | 
				
			||||||
@@ -189,7 +189,7 @@ namespace OpenWifi {
 | 
				
			|||||||
			Poco::Data::Statement Select(Sess);
 | 
								Poco::Data::Statement Select(Sess);
 | 
				
			||||||
			Select << Statement + DateSelector;
 | 
								Select << Statement + DateSelector;
 | 
				
			||||||
			Select.execute();
 | 
								Select.execute();
 | 
				
			||||||
 | 
								Sess.commit();
 | 
				
			||||||
			return true;
 | 
								return true;
 | 
				
			||||||
		} catch (const Poco::Exception &E) {
 | 
							} catch (const Poco::Exception &E) {
 | 
				
			||||||
			poco_warning(Logger(), (fmt::format("{}: Failed with: {}", std::string(__func__),
 | 
								poco_warning(Logger(), (fmt::format("{}: Failed with: {}", std::string(__func__),
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user