mirror of
				https://github.com/Telecominfraproject/wlan-cloud-ucentralgw.git
				synced 2025-11-04 04:37:46 +00:00 
			
		
		
		
	Compare commits
	
		
			174 Commits
		
	
	
		
			sqlopt1
			...
			add_enroll
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					3b7a24ea30 | ||
| 
						 | 
					438309714f | ||
| 
						 | 
					a9130eeb75 | ||
| 
						 | 
					33068fca9e | ||
| 
						 | 
					d329151f6c | ||
| 
						 | 
					ec846006bb | ||
| 
						 | 
					242261de0a | ||
| 
						 | 
					31a4edead5 | ||
| 
						 | 
					f7b697f219 | ||
| 
						 | 
					e020da75fc | ||
| 
						 | 
					89702f56e0 | ||
| 
						 | 
					0ac97442c0 | ||
| 
						 | 
					e38b4c8a13 | ||
| 
						 | 
					9c5bbee834 | ||
| 
						 | 
					a5d1eebe6d | ||
| 
						 | 
					ee14f064c8 | ||
| 
						 | 
					dbf52c1f23 | ||
| 
						 | 
					9dc6a6bf97 | ||
| 
						 | 
					1c0556f8bf | ||
| 
						 | 
					d298139525 | ||
| 
						 | 
					a37c961f5b | ||
| 
						 | 
					75bcbd748c | ||
| 
						 | 
					b6eba2a96d | ||
| 
						 | 
					17082803d4 | ||
| 
						 | 
					26b9a96506 | ||
| 
						 | 
					5ce8dae9ec | ||
| 
						 | 
					7da135c1e5 | ||
| 
						 | 
					50ee4ba5cb | ||
| 
						 | 
					3a8109d7ad | ||
| 
						 | 
					56232966ec | ||
| 
						 | 
					1ecf98d712 | ||
| 
						 | 
					f5b60ced61 | ||
| 
						 | 
					e4d141bb8e | ||
| 
						 | 
					25b4288050 | ||
| 
						 | 
					82430c2d5d | ||
| 
						 | 
					7b68ec0536 | ||
| 
						 | 
					839f4fec44 | ||
| 
						 | 
					c4178209bb | ||
| 
						 | 
					79ab67db50 | ||
| 
						 | 
					00bc77feea | ||
| 
						 | 
					4f00d77d2b | ||
| 
						 | 
					c679d4ac40 | ||
| 
						 | 
					4a150a9fcb | ||
| 
						 | 
					83eb603f0a | ||
| 
						 | 
					38bc0f0d69 | ||
| 
						 | 
					e7362c2020 | ||
| 
						 | 
					9c9987e190 | ||
| 
						 | 
					4ac7b6ba0b | ||
| 
						 | 
					f9ee19af91 | ||
| 
						 | 
					cd2ab8660f | ||
| 
						 | 
					b9f00f6603 | ||
| 
						 | 
					596cfd49e1 | ||
| 
						 | 
					b3deba5606 | ||
| 
						 | 
					a97d49a06b | ||
| 
						 | 
					b1be0604d6 | ||
| 
						 | 
					b29f7f7dc4 | ||
| 
						 | 
					132b31b06b | ||
| 
						 | 
					3114ff8a32 | ||
| 
						 | 
					9c5aeda5dd | ||
| 
						 | 
					783ec99930 | ||
| 
						 | 
					0c661b8b93 | ||
| 
						 | 
					9d7f4da504 | ||
| 
						 | 
					a3b6e7c315 | ||
| 
						 | 
					451680cd5a | ||
| 
						 | 
					7be48c3cfc | ||
| 
						 | 
					b59d1cb4da | ||
| 
						 | 
					c3a709c2b9 | ||
| 
						 | 
					5d89107827 | ||
| 
						 | 
					3c15c6dc4f | ||
| 
						 | 
					7b33a692b2 | ||
| 
						 | 
					b118dcbcec | ||
| 
						 | 
					02a0eef44a | ||
| 
						 | 
					c7ed7fb264 | ||
| 
						 | 
					1d88bb50d9 | ||
| 
						 | 
					3b613ea159 | ||
| 
						 | 
					d00d409fca | ||
| 
						 | 
					8382818e2d | ||
| 
						 | 
					ed4670d239 | ||
| 
						 | 
					cca3619e91 | ||
| 
						 | 
					9a834c29a2 | ||
| 
						 | 
					2b06a0bcf6 | ||
| 
						 | 
					03dabed878 | ||
| 
						 | 
					e133a9c3ab | ||
| 
						 | 
					23b33fab20 | ||
| 
						 | 
					909b4c889e | ||
| 
						 | 
					a04c5336d2 | ||
| 
						 | 
					4df1bf985d | ||
| 
						 | 
					26a89f3eb5 | ||
| 
						 | 
					b055711993 | ||
| 
						 | 
					fcdb7423ef | ||
| 
						 | 
					f286d5fb48 | ||
| 
						 | 
					0d70601c64 | ||
| 
						 | 
					a493defc99 | ||
| 
						 | 
					fb3e1288ae | ||
| 
						 | 
					ce52e05104 | ||
| 
						 | 
					920b922121 | ||
| 
						 | 
					3732cfd07e | ||
| 
						 | 
					9e772b8c91 | ||
| 
						 | 
					92252d09dc | ||
| 
						 | 
					28636c3e1e | ||
| 
						 | 
					8e44f1e85c | ||
| 
						 | 
					b77d40fbf8 | ||
| 
						 | 
					574172b8bf | ||
| 
						 | 
					794b31591d | ||
| 
						 | 
					66aee07105 | ||
| 
						 | 
					86685f17d6 | ||
| 
						 | 
					08f683c15a | ||
| 
						 | 
					7fea477f55 | ||
| 
						 | 
					f22b3e3995 | ||
| 
						 | 
					3a1011a662 | ||
| 
						 | 
					6595b37ae4 | ||
| 
						 | 
					05b6a9474b | ||
| 
						 | 
					1de94be447 | ||
| 
						 | 
					aa8486c71b | ||
| 
						 | 
					e75d3cfdbb | ||
| 
						 | 
					1a0a6d4a70 | ||
| 
						 | 
					071922c555 | ||
| 
						 | 
					4e4b69e672 | ||
| 
						 | 
					3d8f7c1162 | ||
| 
						 | 
					2bf60dbb3f | ||
| 
						 | 
					44bc27e9d4 | ||
| 
						 | 
					f328a72b85 | ||
| 
						 | 
					4cbceb9366 | ||
| 
						 | 
					921267c00a | ||
| 
						 | 
					d63cbce602 | ||
| 
						 | 
					094bba4747 | ||
| 
						 | 
					5bee5b1372 | ||
| 
						 | 
					45357ad567 | ||
| 
						 | 
					8e984a8f0e | ||
| 
						 | 
					4e7babc25f | ||
| 
						 | 
					1acabd4986 | ||
| 
						 | 
					d839646dd8 | ||
| 
						 | 
					31b52f9bd2 | ||
| 
						 | 
					97bc19b949 | ||
| 
						 | 
					c252e6c5c7 | ||
| 
						 | 
					cef012c333 | ||
| 
						 | 
					6513980525 | ||
| 
						 | 
					adc055f3e8 | ||
| 
						 | 
					6d991e5a48 | ||
| 
						 | 
					ec5031ca83 | ||
| 
						 | 
					19e4e92d92 | ||
| 
						 | 
					37feb6a44c | ||
| 
						 | 
					2aaab1207b | ||
| 
						 | 
					7896b071da | ||
| 
						 | 
					e073576692 | ||
| 
						 | 
					65ad9ff96e | ||
| 
						 | 
					08e7900889 | ||
| 
						 | 
					8554481186 | ||
| 
						 | 
					2b246fe1ee | ||
| 
						 | 
					bd37534223 | ||
| 
						 | 
					aa862d3fcf | ||
| 
						 | 
					c6c6eaa4a5 | ||
| 
						 | 
					ffe86a3994 | ||
| 
						 | 
					52123f7dcc | ||
| 
						 | 
					e430c522ba | ||
| 
						 | 
					93c236aa79 | ||
| 
						 | 
					c802e35c12 | ||
| 
						 | 
					a59d49e096 | ||
| 
						 | 
					5756d59519 | ||
| 
						 | 
					35aa6fb99d | ||
| 
						 | 
					fa6d0aa714 | ||
| 
						 | 
					91147f3fbb | ||
| 
						 | 
					15f3eaa02e | ||
| 
						 | 
					6305e92399 | ||
| 
						 | 
					3714fd5f05 | ||
| 
						 | 
					19497b88ce | ||
| 
						 | 
					6a35dc93bf | ||
| 
						 | 
					8004aa6676 | ||
| 
						 | 
					2c654d3471 | ||
| 
						 | 
					df67141a98 | ||
| 
						 | 
					071330d7f8 | ||
| 
						 | 
					90f23dca73 | ||
| 
						 | 
					500688edb7 | ||
| 
						 | 
					222b98d019 | 
							
								
								
									
										2
									
								
								.github/workflows/ci.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.github/workflows/ci.yml
									
									
									
									
										vendored
									
									
								
							@@ -21,7 +21,7 @@ defaults:
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
jobs:
 | 
					jobs:
 | 
				
			||||||
  docker:
 | 
					  docker:
 | 
				
			||||||
    runs-on: ubuntu-20.04
 | 
					    runs-on: ubuntu-latest
 | 
				
			||||||
    env:
 | 
					    env:
 | 
				
			||||||
      DOCKER_REGISTRY_URL: tip-tip-wlan-cloud-ucentral.jfrog.io
 | 
					      DOCKER_REGISTRY_URL: tip-tip-wlan-cloud-ucentral.jfrog.io
 | 
				
			||||||
      DOCKER_REGISTRY_USERNAME: ucentral
 | 
					      DOCKER_REGISTRY_USERNAME: ucentral
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										2
									
								
								.github/workflows/release.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.github/workflows/release.yml
									
									
									
									
										vendored
									
									
								
							@@ -11,7 +11,7 @@ defaults:
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
jobs:
 | 
					jobs:
 | 
				
			||||||
  helm-package:
 | 
					  helm-package:
 | 
				
			||||||
    runs-on: ubuntu-20.04
 | 
					    runs-on: ubuntu-latest
 | 
				
			||||||
    env:
 | 
					    env:
 | 
				
			||||||
      HELM_REPO_URL: https://tip.jfrog.io/artifactory/tip-wlan-cloud-ucentral-helm/
 | 
					      HELM_REPO_URL: https://tip.jfrog.io/artifactory/tip-wlan-cloud-ucentral-helm/
 | 
				
			||||||
      HELM_REPO_USERNAME: ucentral
 | 
					      HELM_REPO_USERNAME: ucentral
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										4
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							@@ -21,10 +21,12 @@ _deps
 | 
				
			|||||||
/docker-compose/.env
 | 
					/docker-compose/.env
 | 
				
			||||||
/docker-compose/.env_*
 | 
					/docker-compose/.env_*
 | 
				
			||||||
/cmake-build/
 | 
					/cmake-build/
 | 
				
			||||||
/uploads/
 | 
					 | 
				
			||||||
test_scripts/curl/token.json
 | 
					test_scripts/curl/token.json
 | 
				
			||||||
.vscode/c_cpp_properties.json
 | 
					.vscode/c_cpp_properties.json
 | 
				
			||||||
test_scripts/curl/result.json
 | 
					test_scripts/curl/result.json
 | 
				
			||||||
*.swp
 | 
					*.swp
 | 
				
			||||||
helm/charts/*
 | 
					helm/charts/*
 | 
				
			||||||
!helm/charts/.gitkeep
 | 
					!helm/charts/.gitkeep
 | 
				
			||||||
 | 
					/portal-test/
 | 
				
			||||||
 | 
					/src/ow_version.h
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										2
									
								
								.idea/.gitignore
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.idea/.gitignore
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -6,3 +6,5 @@
 | 
				
			|||||||
/dataSources.local.xml
 | 
					/dataSources.local.xml
 | 
				
			||||||
# Editor-based HTTP Client requests
 | 
					# Editor-based HTTP Client requests
 | 
				
			||||||
/httpRequests/
 | 
					/httpRequests/
 | 
				
			||||||
 | 
					# GitHub Copilot persisted chat sessions
 | 
				
			||||||
 | 
					/copilot/chatSessions
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										3
									
								
								.idea/misc.xml
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										3
									
								
								.idea/misc.xml
									
									
									
										generated
									
									
									
								
							@@ -1,5 +1,8 @@
 | 
				
			|||||||
<?xml version="1.0" encoding="UTF-8"?>
 | 
					<?xml version="1.0" encoding="UTF-8"?>
 | 
				
			||||||
<project version="4">
 | 
					<project version="4">
 | 
				
			||||||
 | 
					  <component name="Black">
 | 
				
			||||||
 | 
					    <option name="sdkName" value="Python 3.9 (wlan-cloud-ucentralgw)" />
 | 
				
			||||||
 | 
					  </component>
 | 
				
			||||||
  <component name="CMakeWorkspace" PROJECT_DIR="$PROJECT_DIR$" />
 | 
					  <component name="CMakeWorkspace" PROJECT_DIR="$PROJECT_DIR$" />
 | 
				
			||||||
  <component name="CidrRootsConfiguration">
 | 
					  <component name="CidrRootsConfiguration">
 | 
				
			||||||
    <excludeRoots>
 | 
					    <excludeRoots>
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										62
									
								
								BUILDING.md
									
									
									
									
									
								
							
							
						
						
									
										62
									
								
								BUILDING.md
									
									
									
									
									
								
							@@ -1,5 +1,5 @@
 | 
				
			|||||||
# Building from source
 | 
					# Building from source
 | 
				
			||||||
In order to build the OWGW, you will need to install its dependencies, which includes the following:
 | 
					In order to build OWGW, you will need to install its dependencies, which includes the following:
 | 
				
			||||||
- cmake
 | 
					- cmake
 | 
				
			||||||
- boost
 | 
					- boost
 | 
				
			||||||
- POCO 1.10.1 or later
 | 
					- POCO 1.10.1 or later
 | 
				
			||||||
@@ -12,43 +12,43 @@ In order to build the OWGW, you will need to install its dependencies, which inc
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
The build is done in 2 parts. The first part is to build a local copy of the framework tailored to your environment. This
 | 
					The build is done in 2 parts. The first part is to build a local copy of the framework tailored to your environment. This
 | 
				
			||||||
framework is called [Poco](https://github.com/pocoproject/poco). The version used in this project has a couple of fixes
 | 
					framework is called [Poco](https://github.com/pocoproject/poco). The version used in this project has a couple of fixes
 | 
				
			||||||
from the master copy needed for cmake. Please use the version of this [Poco fix](https://github.com/AriliaWireless/poco). Building
 | 
					from the master copy needed for cmake. Please use the version of this [Poco fix](https://github.com/Telecominfraproject/wlan-cloud-lib-poco). Building
 | 
				
			||||||
Poco may take several minutes depending on the platform you are building on.
 | 
					Poco may take several minutes depending on the platform you are building on.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## Ubuntu
 | 
					## Ubuntu
 | 
				
			||||||
These instructions have proven to work on Ubuntu 20.4.
 | 
					These instructions have proven to work on Ubuntu 20.4.
 | 
				
			||||||
```bash
 | 
					```bash
 | 
				
			||||||
sudo apt install git cmake g++ libssl-dev libmariadb-dev 
 | 
					sudo apt install git cmake g++ libssl-dev libmariadb-dev \
 | 
				
			||||||
sudo apt install libpq-dev libaprutil1-dev apache2-dev libboost-all-dev
 | 
					    libpq-dev libaprutil1-dev apache2-dev libboost-all-dev \
 | 
				
			||||||
sudo apt install librdkafka-dev // default-libmysqlclient-dev
 | 
					    librdkafka-dev // default-libmysqlclient-dev \
 | 
				
			||||||
sudo apt install nlohmann-json-dev
 | 
					    nlohmann-json-dev
 | 
				
			||||||
 | 
					
 | 
				
			||||||
cd ~
 | 
					git clone https://github.com/Telecominfraproject/wlan-cloud-lib-poco --branch poco-tip-v1 poco
 | 
				
			||||||
git clone https://github.com/AriliaWireless/poco --branch poco-tip-v2
 | 
					 | 
				
			||||||
cd poco
 | 
					cd poco
 | 
				
			||||||
mkdir cmake-build
 | 
					mkdir cmake-build
 | 
				
			||||||
cd cmake-build
 | 
					cd cmake-build
 | 
				
			||||||
cmake ..
 | 
					cmake ..
 | 
				
			||||||
cmake --build . --config Release
 | 
					cmake --build . --config Release
 | 
				
			||||||
sudo cmake --build . --target install
 | 
					sudo cmake --build . --target install
 | 
				
			||||||
 | 
					cd ../..
 | 
				
			||||||
 | 
					
 | 
				
			||||||
cd ~
 | 
					git clone https://github.com/Telecominfraproject/wlan-cloud-lib-cppkafka --branch tip-v1 cppkafka
 | 
				
			||||||
git clone https://github.com/AriliaWireless/cppkafka --branch tip-v1
 | 
					 | 
				
			||||||
cd cppkafka
 | 
					cd cppkafka
 | 
				
			||||||
mkdir cmake-build
 | 
					mkdir cmake-build
 | 
				
			||||||
cd cmake-build
 | 
					cd cmake-build
 | 
				
			||||||
cmake ..
 | 
					cmake ..
 | 
				
			||||||
cmake --build . --config Release
 | 
					cmake --build . --config Release
 | 
				
			||||||
sudo cmake --build . --target install
 | 
					sudo cmake --build . --target install
 | 
				
			||||||
 | 
					cd ../..
 | 
				
			||||||
 | 
					
 | 
				
			||||||
cd ~
 | 
					git clone https://github.com/Telecominfraproject/wlan-cloud-lib-valijson --branch tip-v1 valijson
 | 
				
			||||||
git clone https://github.com/AriliaWireless/valijson --branch tip-v1
 | 
					 | 
				
			||||||
cd valijson
 | 
					cd valijson
 | 
				
			||||||
mkdir cmake-build
 | 
					mkdir cmake-build
 | 
				
			||||||
cd cmake-build
 | 
					cd cmake-build
 | 
				
			||||||
cmake ..
 | 
					cmake ..
 | 
				
			||||||
cmake --build . --config Release
 | 
					cmake --build . --config Release
 | 
				
			||||||
sudo cmake --build . --target install
 | 
					sudo cmake --build . --target install
 | 
				
			||||||
 | 
					cd ../..
 | 
				
			||||||
 | 
					
 | 
				
			||||||
git clone https://github.com/fmtlib/fmt --branch 9.0.0 /fmtlib
 | 
					git clone https://github.com/fmtlib/fmt --branch 9.0.0 /fmtlib
 | 
				
			||||||
cd fmtlib
 | 
					cd fmtlib
 | 
				
			||||||
@@ -57,56 +57,59 @@ cd cmake-build
 | 
				
			|||||||
cmake ..
 | 
					cmake ..
 | 
				
			||||||
make
 | 
					make
 | 
				
			||||||
make install
 | 
					make install
 | 
				
			||||||
 | 
					cd ../..
 | 
				
			||||||
 | 
					
 | 
				
			||||||
cd ~
 | 
					 | 
				
			||||||
git clone https://github.com/Telecominfraproject/wlan-cloud-ucentralgw
 | 
					git clone https://github.com/Telecominfraproject/wlan-cloud-ucentralgw
 | 
				
			||||||
cd wlan-cloud-ucentralgw
 | 
					cd wlan-cloud-ucentralgw
 | 
				
			||||||
mkdir cmake-build
 | 
					mkdir cmake-build
 | 
				
			||||||
cd cmake-build
 | 
					cd cmake-build
 | 
				
			||||||
cmake ..
 | 
					cmake ..
 | 
				
			||||||
make -j 8
 | 
					make -j 8
 | 
				
			||||||
 | 
					cd ../..
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## Fedora
 | 
					## Fedora
 | 
				
			||||||
The following instructions have proven to work on Fedora 33
 | 
					The following instructions have proven to work on Fedora 33
 | 
				
			||||||
```bash
 | 
					```bash
 | 
				
			||||||
sudo yum install cmake g++ openssl-devel mysql-devel mysql apr-util-devel boost boost-devel
 | 
					sudo yum install cmake g++ openssl-devel mysql-devel mysql apr-util-devel boost boost-devel \
 | 
				
			||||||
sudo yum install yaml-cpp-devel lua-devel 
 | 
					    yaml-cpp-devel lua-devel
 | 
				
			||||||
sudo dnf install postgresql.x86_64 librdkafka-devel
 | 
					sudo dnf install postgresql.x86_64 librdkafka-devel
 | 
				
			||||||
sudo dnf install postgresql-devel json-devel
 | 
					sudo dnf install postgresql-devel json-devel
 | 
				
			||||||
 | 
					
 | 
				
			||||||
git clone https://github.com/AriliaWireless/poco --branch poco-tip-v2
 | 
					git clone https://github.com/Telecominfraproject/wlan-cloud-lib-poco --branch poco-tip-v1 poco
 | 
				
			||||||
cd poco
 | 
					cd poco
 | 
				
			||||||
mkdir cmake-build
 | 
					mkdir cmake-build
 | 
				
			||||||
cd cmake-build
 | 
					cd cmake-build
 | 
				
			||||||
cmake ..
 | 
					cmake ..
 | 
				
			||||||
cmake --build . --config Release
 | 
					cmake --build . --config Release
 | 
				
			||||||
sudo cmake --build . --target install
 | 
					sudo cmake --build . --target install
 | 
				
			||||||
 | 
					cd ../..
 | 
				
			||||||
 | 
					
 | 
				
			||||||
git clone https://github.com/AriliaWireless/cppkafka --branch tip-v1
 | 
					git clone https://github.com/Telecominfraproject/wlan-cloud-lib-cppkafka --branch tip-v1 cppkafka
 | 
				
			||||||
cd cppkafka
 | 
					cd cppkafka
 | 
				
			||||||
mkdir cmake-build
 | 
					mkdir cmake-build
 | 
				
			||||||
cd cmake-build
 | 
					cd cmake-build
 | 
				
			||||||
cmake ..
 | 
					cmake ..
 | 
				
			||||||
cmake --build . --config Release
 | 
					cmake --build . --config Release
 | 
				
			||||||
sudo cmake --build . --target install
 | 
					sudo cmake --build . --target install
 | 
				
			||||||
 | 
					cd ../..
 | 
				
			||||||
 | 
					
 | 
				
			||||||
cd ~
 | 
					git clone https://github.com/Telecominfraproject/wlan-cloud-lib-valijson --branch tip-v1 valijson
 | 
				
			||||||
git clone https://github.com/AriliaWireless/valijson --branch tip-v1
 | 
					 | 
				
			||||||
cd valijson
 | 
					cd valijson
 | 
				
			||||||
mkdir cmake-build
 | 
					mkdir cmake-build
 | 
				
			||||||
cd cmake-build
 | 
					cd cmake-build
 | 
				
			||||||
cmake ..
 | 
					cmake ..
 | 
				
			||||||
cmake --build . --config Release
 | 
					cmake --build . --config Release
 | 
				
			||||||
sudo cmake --build . --target install
 | 
					sudo cmake --build . --target install
 | 
				
			||||||
 | 
					cd ../..
 | 
				
			||||||
 | 
					
 | 
				
			||||||
cd ~
 | 
					 | 
				
			||||||
git clone https://github.com/Telecominfraproject/wlan-cloud-ucentralgw
 | 
					git clone https://github.com/Telecominfraproject/wlan-cloud-ucentralgw
 | 
				
			||||||
cd wlan-cloud-ucentralgw
 | 
					cd wlan-cloud-ucentralgw
 | 
				
			||||||
mkdir cmake-build
 | 
					mkdir cmake-build
 | 
				
			||||||
cd cmake-build
 | 
					cd cmake-build
 | 
				
			||||||
cmake ..
 | 
					cmake ..
 | 
				
			||||||
make
 | 
					make
 | 
				
			||||||
 | 
					cd ../..
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## macOS Build
 | 
					## macOS Build
 | 
				
			||||||
@@ -125,7 +128,7 @@ brew install openssl \
 | 
				
			|||||||
	nlohmann-json \
 | 
						nlohmann-json \
 | 
				
			||||||
	fmt
 | 
						fmt
 | 
				
			||||||
 | 
					
 | 
				
			||||||
git clone https://github.com/AriliaWireless/poco --branch poco-tip-v2
 | 
					git clone https://github.com/Telecominfraproject/wlan-cloud-lib-poco --branch poco-tip-v1 poco
 | 
				
			||||||
pushd poco
 | 
					pushd poco
 | 
				
			||||||
mkdir cmake-build
 | 
					mkdir cmake-build
 | 
				
			||||||
push cmake-build
 | 
					push cmake-build
 | 
				
			||||||
@@ -135,7 +138,7 @@ sudo cmake --build . --target install
 | 
				
			|||||||
popd
 | 
					popd
 | 
				
			||||||
popd
 | 
					popd
 | 
				
			||||||
 | 
					
 | 
				
			||||||
git clone https://github.com/AriliaWireless/cppkafka --branch tip-v1
 | 
					git clone https://github.com/Telecominfraproject/wlan-cloud-lib-cppkafka --branch tip-v1 cppkafka
 | 
				
			||||||
pushd cppkafka
 | 
					pushd cppkafka
 | 
				
			||||||
mkdir cmake-build
 | 
					mkdir cmake-build
 | 
				
			||||||
pushd cmake-build
 | 
					pushd cmake-build
 | 
				
			||||||
@@ -145,10 +148,10 @@ sudo cmake --build . --target install
 | 
				
			|||||||
popd
 | 
					popd
 | 
				
			||||||
popd
 | 
					popd
 | 
				
			||||||
 | 
					
 | 
				
			||||||
git clone https://github.com/AriliaWireless/valijson --branch tip-v1
 | 
					git clone https://github.com/Telecominfraproject/wlan-cloud-lib-valijson --branch tip-v1 valijson
 | 
				
			||||||
cd valijson
 | 
					pushd valijson
 | 
				
			||||||
mkdir cmake-build
 | 
					mkdir cmake-build
 | 
				
			||||||
cd cmake-build
 | 
					pushd cmake-build
 | 
				
			||||||
cmake ..
 | 
					cmake ..
 | 
				
			||||||
cmake --build . --config Release
 | 
					cmake --build . --config Release
 | 
				
			||||||
sudo cmake --build . --target install
 | 
					sudo cmake --build . --target install
 | 
				
			||||||
@@ -171,20 +174,23 @@ support. You can build with only SQLite support by not installing the packages f
 | 
				
			|||||||
adding -DSMALL_BUILD=1 on the cmake build line.
 | 
					adding -DSMALL_BUILD=1 on the cmake build line.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
```bash
 | 
					```bash
 | 
				
			||||||
sudo apt install git cmake g++ libssl-dev libaprutil1-dev apache2-dev libboost-all-dev libyaml-cpp-dev
 | 
					sudo apt install git cmake g++ libssl-dev libaprutil1-dev apache2-dev \
 | 
				
			||||||
git clone https://github.com/stephb9959/poco
 | 
					    libboost-all-dev libyaml-cpp-dev
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					git clone https://github.com/Telecominfraproject/wlan-cloud-lib-poco --branch poco-tip-v1 poco
 | 
				
			||||||
cd poco
 | 
					cd poco
 | 
				
			||||||
mkdir cmake-build
 | 
					mkdir cmake-build
 | 
				
			||||||
cd cmake-build
 | 
					cd cmake-build
 | 
				
			||||||
cmake ..
 | 
					cmake ..
 | 
				
			||||||
cmake --build . --config Release
 | 
					cmake --build . --config Release
 | 
				
			||||||
sudo cmake --build . --target install
 | 
					sudo cmake --build . --target install
 | 
				
			||||||
 | 
					cd ../..
 | 
				
			||||||
 | 
					
 | 
				
			||||||
cd ~
 | 
					 | 
				
			||||||
git clone https://github.com/Telecominfraproject/wlan-cloud-ucentralgw
 | 
					git clone https://github.com/Telecominfraproject/wlan-cloud-ucentralgw
 | 
				
			||||||
cd wlan-cloud-ucentralgw
 | 
					cd wlan-cloud-ucentralgw
 | 
				
			||||||
mkdir cmake-build
 | 
					mkdir cmake-build
 | 
				
			||||||
cd cmake-build
 | 
					cd cmake-build
 | 
				
			||||||
cmake -DSMALL_BUILD=1 ..
 | 
					cmake -DSMALL_BUILD=1 ..
 | 
				
			||||||
make
 | 
					make
 | 
				
			||||||
 | 
					cd ../..
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,7 +1,8 @@
 | 
				
			|||||||
cmake_minimum_required(VERSION 3.13)
 | 
					cmake_minimum_required(VERSION 3.13)
 | 
				
			||||||
project(owgw VERSION 3.0.0)
 | 
					project(owgw VERSION 4.1.0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
set(CMAKE_CXX_STANDARD 17)
 | 
					set(CMAKE_CXX_STANDARD 20)
 | 
				
			||||||
 | 
					set(CMAKE_CXX_STANDARD_REQUIRED True)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
if(UNIX AND APPLE)
 | 
					if(UNIX AND APPLE)
 | 
				
			||||||
    set(OPENSSL_ROOT_DIR /usr/local/opt/openssl)
 | 
					    set(OPENSSL_ROOT_DIR /usr/local/opt/openssl)
 | 
				
			||||||
@@ -148,6 +149,7 @@ add_executable( owgw
 | 
				
			|||||||
        src/RESTAPI/RESTAPI_script_handler.cpp src/RESTAPI/RESTAPI_script_handler.h
 | 
					        src/RESTAPI/RESTAPI_script_handler.cpp src/RESTAPI/RESTAPI_script_handler.h
 | 
				
			||||||
        src/RESTAPI/RESTAPI_regulatory.cpp src/RESTAPI/RESTAPI_regulatory.h
 | 
					        src/RESTAPI/RESTAPI_regulatory.cpp src/RESTAPI/RESTAPI_regulatory.h
 | 
				
			||||||
        src/RESTAPI/RESTAPI_radiussessions_handler.cpp src/RESTAPI/RESTAPI_radiussessions_handler.h
 | 
					        src/RESTAPI/RESTAPI_radiussessions_handler.cpp src/RESTAPI/RESTAPI_radiussessions_handler.h
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        src/storage/storage_blacklist.cpp src/storage/storage_tables.cpp src/storage/storage_logs.cpp
 | 
					        src/storage/storage_blacklist.cpp src/storage/storage_tables.cpp src/storage/storage_logs.cpp
 | 
				
			||||||
        src/storage/storage_command.cpp src/storage/storage_healthcheck.cpp src/storage/storage_statistics.cpp
 | 
					        src/storage/storage_command.cpp src/storage/storage_healthcheck.cpp src/storage/storage_statistics.cpp
 | 
				
			||||||
        src/storage/storage_device.cpp src/storage/storage_capabilities.cpp src/storage/storage_defconfig.cpp
 | 
					        src/storage/storage_device.cpp src/storage/storage_capabilities.cpp src/storage/storage_defconfig.cpp
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										14
									
								
								Dockerfile
									
									
									
									
									
								
							
							
						
						
									
										14
									
								
								Dockerfile
									
									
									
									
									
								
							@@ -1,7 +1,7 @@
 | 
				
			|||||||
ARG DEBIAN_VERSION=11.5-slim
 | 
					ARG DEBIAN_VERSION=11.5-slim
 | 
				
			||||||
ARG POCO_VERSION=poco-tip-v2
 | 
					ARG POCO_VERSION=poco-tip-v2
 | 
				
			||||||
ARG CPPKAFKA_VERSION=tip-v1
 | 
					ARG CPPKAFKA_VERSION=tip-v1
 | 
				
			||||||
ARG VALIJASON_VERSION=tip-v1
 | 
					ARG VALIJASON_VERSION=tip-v1.0.2
 | 
				
			||||||
ARG APP_NAME=owgw
 | 
					ARG APP_NAME=owgw
 | 
				
			||||||
ARG APP_HOME_DIR=/openwifi
 | 
					ARG APP_HOME_DIR=/openwifi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -17,8 +17,8 @@ FROM build-base AS poco-build
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
ARG POCO_VERSION
 | 
					ARG POCO_VERSION
 | 
				
			||||||
 | 
					
 | 
				
			||||||
ADD https://api.github.com/repos/AriliaWireless/poco/git/refs/tags/${POCO_VERSION} version.json
 | 
					ADD https://api.github.com/repos/Telecominfraproject/wlan-cloud-lib-poco/git/refs/tags/${POCO_VERSION} version.json
 | 
				
			||||||
RUN git clone https://github.com/AriliaWireless/poco --branch ${POCO_VERSION} /poco
 | 
					RUN git clone https://github.com/Telecominfraproject/wlan-cloud-lib-poco --branch ${POCO_VERSION} /poco
 | 
				
			||||||
 | 
					
 | 
				
			||||||
WORKDIR /poco
 | 
					WORKDIR /poco
 | 
				
			||||||
RUN mkdir cmake-build
 | 
					RUN mkdir cmake-build
 | 
				
			||||||
@@ -31,8 +31,8 @@ FROM build-base AS cppkafka-build
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
ARG CPPKAFKA_VERSION
 | 
					ARG CPPKAFKA_VERSION
 | 
				
			||||||
 | 
					
 | 
				
			||||||
ADD https://api.github.com/repos/AriliaWireless/cppkafka/git/refs/tags/${CPPKAFKA_VERSION} version.json
 | 
					ADD https://api.github.com/repos/Telecominfraproject/wlan-cloud-lib-cppkafka/git/refs/tags/${CPPKAFKA_VERSION} version.json
 | 
				
			||||||
RUN git clone https://github.com/AriliaWireless/cppkafka --branch ${CPPKAFKA_VERSION} /cppkafka
 | 
					RUN git clone https://github.com/Telecominfraproject/wlan-cloud-lib-cppkafka --branch ${CPPKAFKA_VERSION} /cppkafka
 | 
				
			||||||
 | 
					
 | 
				
			||||||
WORKDIR /cppkafka
 | 
					WORKDIR /cppkafka
 | 
				
			||||||
RUN mkdir cmake-build
 | 
					RUN mkdir cmake-build
 | 
				
			||||||
@@ -45,8 +45,8 @@ FROM build-base AS valijson-build
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
ARG VALIJASON_VERSION
 | 
					ARG VALIJASON_VERSION
 | 
				
			||||||
 | 
					
 | 
				
			||||||
ADD https://api.github.com/repos/AriliaWireless/valijson/git/refs/tags/${VALIJASON_VERSION} version.json
 | 
					ADD https://api.github.com/repos/Telecominfraproject/wlan-cloud-lib-valijson/git/refs/tags/${VALIJASON_VERSION} version.json
 | 
				
			||||||
RUN git clone https://github.com/AriliaWireless/valijson --branch ${VALIJASON_VERSION} /valijson
 | 
					RUN git clone https://github.com/Telecominfraproject/wlan-cloud-lib-valijson --branch ${VALIJASON_VERSION} /valijson
 | 
				
			||||||
 | 
					
 | 
				
			||||||
WORKDIR /valijson
 | 
					WORKDIR /valijson
 | 
				
			||||||
RUN mkdir cmake-build
 | 
					RUN mkdir cmake-build
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										105
									
								
								PROTOCOL.md
									
									
									
									
									
								
							
							
						
						
									
										105
									
								
								PROTOCOL.md
									
									
									
									
									
								
							@@ -306,8 +306,54 @@ The device should answer:
 | 
				
			|||||||
         },
 | 
					         },
 | 
				
			||||||
     "id" : <same number>
 | 
					     "id" : <same number>
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#### Controller wants the device to apply a given fixed configuration
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Controller sends this command when it requires the device to apply fixed configuration, eg. country code. The device
 | 
				
			||||||
 | 
					should respond with message indicating failure or success.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```json
 | 
				
			||||||
 | 
					{   "jsonrpc" : "2.0",
 | 
				
			||||||
 | 
					    "method" : "fixedconfig",
 | 
				
			||||||
 | 
					    "params" : {
 | 
				
			||||||
 | 
					        "serial" : <serial number>,
 | 
				
			||||||
 | 
					        "when" : Optional - <UTC time when to apply this config, 0 means immediate, this is a suggestion>
 | 
				
			||||||
 | 
					        "country" : "<country-code>"
 | 
				
			||||||
 | 
					     },
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					If AP supports compressed configuration feature by inidcating `compress_cmd=true` in its capabilities, controller
 | 
				
			||||||
 | 
					will send a compressed configuration message where configuration payload (i.e. contents of `params`) is compressed
 | 
				
			||||||
 | 
					and encoded in base64 format:
 | 
				
			||||||
 | 
					```json
 | 
				
			||||||
 | 
					{   "jsonrpc" : "2.0",
 | 
				
			||||||
 | 
					    "method" : "configure",
 | 
				
			||||||
 | 
					    "params" : {
 | 
				
			||||||
 | 
					        "compress_64" : "<b64 encoded zlib compressed payload>",
 | 
				
			||||||
 | 
					        "compress_sz" : "<size of uncompressed data in bytes>"
 | 
				
			||||||
 | 
					     },
 | 
				
			||||||
 | 
					     "id" : <some number>
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The device should answer:
 | 
				
			||||||
 | 
					```json
 | 
				
			||||||
 | 
					{   "jsonrpc" : "2.0",
 | 
				
			||||||
 | 
					    "result" : {
 | 
				
			||||||
 | 
					        "serial": <serial number>,
 | 
				
			||||||
 | 
					        "status": {
 | 
				
			||||||
 | 
					            "error": 0 or an error number,
 | 
				
			||||||
 | 
					            "text": <description of the error or success, eg. "Applied fixed config, rebooting">
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "uuid": <UUID>
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
##### The Answer
 | 
					##### The Answer
 | 
				
			||||||
The device can answer and tell the controller it has rejected certain parts of the config and potentially replaced them with
 | 
					The device can answer and tell the controller it has rejected certain parts of the config and potentially replaced them with
 | 
				
			||||||
appropriate values. This could be used to allow a device to replace frequencies for the regions it is located in. The device 
 | 
					appropriate values. This could be used to allow a device to replace frequencies for the regions it is located in. The device 
 | 
				
			||||||
@@ -355,6 +401,39 @@ The device should answer:
 | 
				
			|||||||
- 1 : the device is busy but will reboot soon. `text` may indicate why.
 | 
					- 1 : the device is busy but will reboot soon. `text` may indicate why.
 | 
				
			||||||
- 2 : the device will not reboot. `text` contains information as to why.
 | 
					- 2 : the device will not reboot. `text` contains information as to why.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#### Controller wants to power-cycle PoE port(s)
 | 
				
			||||||
 | 
					Controller sends this command to power-cycle 1 or more PoE ports
 | 
				
			||||||
 | 
					```json
 | 
				
			||||||
 | 
					{    "jsonrpc" : "2.0" , 
 | 
				
			||||||
 | 
					     "method" : "powercycle" , 
 | 
				
			||||||
 | 
					     "params" : {
 | 
				
			||||||
 | 
						        "serial" : <serial number> ,
 | 
				
			||||||
 | 
					            "ports" : [ { "name" :  "Ethernet1", "cycle" : 5000}, { "name" :  "Ethernet8", "cycle" : 10000 } ],
 | 
				
			||||||
 | 
						        "when" : Optional - <UTC time when to reboot, 0 mean immediately, this is a suggestion>
 | 
				
			||||||
 | 
					     },
 | 
				
			||||||
 | 
					     "id" : <some number>
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The device should answer:
 | 
				
			||||||
 | 
					```json
 | 
				
			||||||
 | 
					{     "jsonrpc" : "2.0" , 
 | 
				
			||||||
 | 
					      "result" : {
 | 
				
			||||||
 | 
					      "serial" : <serial number> ,
 | 
				
			||||||
 | 
					      "status" : {
 | 
				
			||||||
 | 
						    "error" : 0 or an error number,
 | 
				
			||||||
 | 
						    "text" : [ "Error 1" , "Error 2" ],
 | 
				
			||||||
 | 
						    "when" : <time when this will be performed as UTC seconds>,
 | 
				
			||||||
 | 
					  	},
 | 
				
			||||||
 | 
					  "id" : <same id from request>
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					###### Error codes
 | 
				
			||||||
 | 
					- 0 : is rebooting at `when` seconds.
 | 
				
			||||||
 | 
					- 1 : the device is busy but will reboot soon. `text` may indicate why.
 | 
				
			||||||
 | 
					- 2 : the device will not reboot. `text` contains information as to why.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#### Controller wants the device to upgrade its firmware
 | 
					#### Controller wants the device to upgrade its firmware
 | 
				
			||||||
Controller sends this command when it believes the device should upgrade its firmware.
 | 
					Controller sends this command when it believes the device should upgrade its firmware.
 | 
				
			||||||
```json
 | 
					```json
 | 
				
			||||||
@@ -801,6 +880,32 @@ The device should answer:
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#### Controller wants the device to perform re-enrollment
 | 
				
			||||||
 | 
					Controller sends this command to trigger re-enrollment, i.e. update of operational certificate. Extreme care must be taken.
 | 
				
			||||||
 | 
					```json
 | 
				
			||||||
 | 
					{    "jsonrpc" : "2.0" , 
 | 
				
			||||||
 | 
					     "method" : "reenroll" , 
 | 
				
			||||||
 | 
					     "params" : {
 | 
				
			||||||
 | 
					        "serial" : <serial number>,
 | 
				
			||||||
 | 
					        "when" : Optional - <UTC time when to apply this config, 0 mean immediate, this is a suggestion>
 | 
				
			||||||
 | 
					     },
 | 
				
			||||||
 | 
					     "id" : <some number>
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The device should answer:
 | 
				
			||||||
 | 
					```json
 | 
				
			||||||
 | 
					{     "jsonrpc" : "2.0" , 
 | 
				
			||||||
 | 
					      "result" : {
 | 
				
			||||||
 | 
					          "serial" : <serial number> ,
 | 
				
			||||||
 | 
					          "status" : {
 | 
				
			||||||
 | 
					            "error" : <0 or the value of $? from the shell running the command, 255 signifies a timeout>,
 | 
				
			||||||
 | 
					            "txt" : <text describing the error or success>
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					  "id" : <same number as request>
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#### Controller wants the device to switch to another controller
 | 
					#### Controller wants the device to switch to another controller
 | 
				
			||||||
Controller sends this when the device should change the controller it connects to without looking up a new redirector.
 | 
					Controller sends this when the device should change the controller it connects to without looking up a new redirector.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										85
									
								
								ols_samples/sample1.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										85
									
								
								ols_samples/sample1.json
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,85 @@
 | 
				
			|||||||
 | 
					{
 | 
				
			||||||
 | 
					    "ethernet": [
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            "select-ports": [
 | 
				
			||||||
 | 
					                "Ethernet0",
 | 
				
			||||||
 | 
					                "Ethernet1",
 | 
				
			||||||
 | 
					                "Ethernet2",
 | 
				
			||||||
 | 
					                "Ethernet3",
 | 
				
			||||||
 | 
					                "Ethernet4",
 | 
				
			||||||
 | 
					                "Ethernet5",
 | 
				
			||||||
 | 
					                "Ethernet6",
 | 
				
			||||||
 | 
					                "Ethernet7"
 | 
				
			||||||
 | 
					            ],
 | 
				
			||||||
 | 
					            "speed": 2500,
 | 
				
			||||||
 | 
					            "duplex": "full",
 | 
				
			||||||
 | 
					            "enabled": true,
 | 
				
			||||||
 | 
					            "poe": {
 | 
				
			||||||
 | 
					                "admin-mode": true,
 | 
				
			||||||
 | 
					                "power-limit": 60000
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            "select-ports": [
 | 
				
			||||||
 | 
					                "Ethernet8",
 | 
				
			||||||
 | 
					                "Ethernet9"
 | 
				
			||||||
 | 
					            ],
 | 
				
			||||||
 | 
					            "speed": 10000,
 | 
				
			||||||
 | 
					            "duplex": "full",
 | 
				
			||||||
 | 
					            "media": "sfp-forced-1000sfp"
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    ],
 | 
				
			||||||
 | 
					    "interfaces": [
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            "name": "VLAN1",
 | 
				
			||||||
 | 
					            "vlan": {
 | 
				
			||||||
 | 
					                "id": 1
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            "ipv4": {
 | 
				
			||||||
 | 
					                "addressing": "dynamic"
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            "ethernet": [
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    "select-ports": [
 | 
				
			||||||
 | 
					                        "Ethernet0",
 | 
				
			||||||
 | 
					                        "Ethernet1",
 | 
				
			||||||
 | 
					                        "Ethernet2",
 | 
				
			||||||
 | 
					                        "Ethernet3",
 | 
				
			||||||
 | 
					                        "Ethernet4",
 | 
				
			||||||
 | 
					                        "Ethernet5",
 | 
				
			||||||
 | 
					                        "Ethernet6",
 | 
				
			||||||
 | 
					                        "Ethernet7",
 | 
				
			||||||
 | 
					                        "Ethernet8",
 | 
				
			||||||
 | 
					                        "Ethernet9"
 | 
				
			||||||
 | 
					                    ],
 | 
				
			||||||
 | 
					                    "vlan-tag": "un-tagged"
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            ]
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    ],
 | 
				
			||||||
 | 
					    "metrics": {
 | 
				
			||||||
 | 
					        "dhcp-snooping": {
 | 
				
			||||||
 | 
					            "filters": [
 | 
				
			||||||
 | 
					                "ack",
 | 
				
			||||||
 | 
					                "discover",
 | 
				
			||||||
 | 
					                "offer",
 | 
				
			||||||
 | 
					                "request",
 | 
				
			||||||
 | 
					                "solicit",
 | 
				
			||||||
 | 
					                "reply",
 | 
				
			||||||
 | 
					                "renew"
 | 
				
			||||||
 | 
					            ]
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "health": {
 | 
				
			||||||
 | 
					            "interval": 60
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "statistics": {
 | 
				
			||||||
 | 
					            "interval": 120,
 | 
				
			||||||
 | 
					            "types": []
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "unit": {
 | 
				
			||||||
 | 
					        "leds-active": true,
 | 
				
			||||||
 | 
					        "usage-threshold": 95
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "uuid": 1678263900
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -12,7 +12,7 @@ info:
 | 
				
			|||||||
    url: https://www.ucentral.info/support
 | 
					    url: https://www.ucentral.info/support
 | 
				
			||||||
 | 
					
 | 
				
			||||||
servers:
 | 
					servers:
 | 
				
			||||||
  - url: 'https://localhost:16001/api/v1'
 | 
					  - url: 'https://localhost:16002/api/v1'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
security:
 | 
					security:
 | 
				
			||||||
  - bearerAuth: []
 | 
					  - bearerAuth: []
 | 
				
			||||||
@@ -42,12 +42,10 @@ components:
 | 
				
			|||||||
  schemas:
 | 
					  schemas:
 | 
				
			||||||
    DeviceType:
 | 
					    DeviceType:
 | 
				
			||||||
      type: string
 | 
					      type: string
 | 
				
			||||||
      default: AP
 | 
					      default: ap
 | 
				
			||||||
      enum:
 | 
					      enum:
 | 
				
			||||||
        - AP
 | 
					        - ap
 | 
				
			||||||
        - SWITCH
 | 
					        - switch
 | 
				
			||||||
        - IOT
 | 
					 | 
				
			||||||
        - MESH
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    DeviceRestrictionsKeyInfo:
 | 
					    DeviceRestrictionsKeyInfo:
 | 
				
			||||||
      type: object
 | 
					      type: object
 | 
				
			||||||
@@ -157,6 +155,9 @@ components:
 | 
				
			|||||||
        lastRecordedContact:
 | 
					        lastRecordedContact:
 | 
				
			||||||
          type: integer
 | 
					          type: integer
 | 
				
			||||||
          format: int64
 | 
					          format: int64
 | 
				
			||||||
 | 
					        blackListed:
 | 
				
			||||||
 | 
					          type: boolean
 | 
				
			||||||
 | 
					          readOnly: true
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    DeviceWithStatus:
 | 
					    DeviceWithStatus:
 | 
				
			||||||
      type: object
 | 
					      type: object
 | 
				
			||||||
@@ -281,6 +282,9 @@ components:
 | 
				
			|||||||
          format: float
 | 
					          format: float
 | 
				
			||||||
        connectReason:
 | 
					        connectReason:
 | 
				
			||||||
          type: string
 | 
					          type: string
 | 
				
			||||||
 | 
					        blackListed:
 | 
				
			||||||
 | 
					          type: boolean
 | 
				
			||||||
 | 
					          readOnly: true
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    DeviceList:
 | 
					    DeviceList:
 | 
				
			||||||
      type: object
 | 
					      type: object
 | 
				
			||||||
@@ -545,6 +549,12 @@ components:
 | 
				
			|||||||
        lastModified:
 | 
					        lastModified:
 | 
				
			||||||
          type: integer
 | 
					          type: integer
 | 
				
			||||||
          format: int64
 | 
					          format: int64
 | 
				
			||||||
 | 
					        platform:
 | 
				
			||||||
 | 
					          type: string
 | 
				
			||||||
 | 
					          enum:
 | 
				
			||||||
 | 
					            - ap
 | 
				
			||||||
 | 
					            - switch
 | 
				
			||||||
 | 
					          default: ap
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    DefaultConfigurationList:
 | 
					    DefaultConfigurationList:
 | 
				
			||||||
      properties:
 | 
					      properties:
 | 
				
			||||||
@@ -1566,6 +1576,39 @@ components:
 | 
				
			|||||||
          format: base64
 | 
					          format: base64
 | 
				
			||||||
          description: This is a base64 encoded string of the certificate bundle (the current bundle .tar.gz file from the PKI portal)
 | 
					          description: This is a base64 encoded string of the certificate bundle (the current bundle .tar.gz file from the PKI portal)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    ReenrollRequest:
 | 
				
			||||||
 | 
					      type: object
 | 
				
			||||||
 | 
					      properties:
 | 
				
			||||||
 | 
					        serialNumber:
 | 
				
			||||||
 | 
					          type: string
 | 
				
			||||||
 | 
					        when:
 | 
				
			||||||
 | 
					          type: integer
 | 
				
			||||||
 | 
					          format: int64
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    PowerCycleRequest:
 | 
				
			||||||
 | 
					      type: object
 | 
				
			||||||
 | 
					      properties:
 | 
				
			||||||
 | 
					        serial:
 | 
				
			||||||
 | 
					          type: string
 | 
				
			||||||
 | 
					        when:
 | 
				
			||||||
 | 
					          type: integer
 | 
				
			||||||
 | 
					          format: int64
 | 
				
			||||||
 | 
					        ports:
 | 
				
			||||||
 | 
					          type: array
 | 
				
			||||||
 | 
					          items:
 | 
				
			||||||
 | 
					            type: object
 | 
				
			||||||
 | 
					            properties:
 | 
				
			||||||
 | 
					              name:
 | 
				
			||||||
 | 
					                type: string
 | 
				
			||||||
 | 
					                example:
 | 
				
			||||||
 | 
					                  - Ethernet0
 | 
				
			||||||
 | 
					              cycle:
 | 
				
			||||||
 | 
					                type: integer
 | 
				
			||||||
 | 
					                default: 10000
 | 
				
			||||||
 | 
					                minimum: 1
 | 
				
			||||||
 | 
					                maximum: 60000
 | 
				
			||||||
 | 
					                description: off time in milliseconds
 | 
				
			||||||
 | 
					
 | 
				
			||||||
paths:
 | 
					paths:
 | 
				
			||||||
  /devices:
 | 
					  /devices:
 | 
				
			||||||
    get:
 | 
					    get:
 | 
				
			||||||
@@ -1657,6 +1700,22 @@ paths:
 | 
				
			|||||||
            type: integer
 | 
					            type: integer
 | 
				
			||||||
            default: 70
 | 
					            default: 70
 | 
				
			||||||
          required: false
 | 
					          required: false
 | 
				
			||||||
 | 
					        - in: query
 | 
				
			||||||
 | 
					          description: return only devices matching a certain platform of AP or SWITCH
 | 
				
			||||||
 | 
					          name: platform
 | 
				
			||||||
 | 
					          schema:
 | 
				
			||||||
 | 
					            type: string
 | 
				
			||||||
 | 
					            default: ALL
 | 
				
			||||||
 | 
					            enum:
 | 
				
			||||||
 | 
					              - all
 | 
				
			||||||
 | 
					              - ap
 | 
				
			||||||
 | 
					              - switch
 | 
				
			||||||
 | 
					          required: false
 | 
				
			||||||
 | 
					        - in: query
 | 
				
			||||||
 | 
					          description: only devices which are not provisioned
 | 
				
			||||||
 | 
					          name: includeProvisioned
 | 
				
			||||||
 | 
					          schema:
 | 
				
			||||||
 | 
					            type: boolean
 | 
				
			||||||
      responses:
 | 
					      responses:
 | 
				
			||||||
        200:
 | 
					        200:
 | 
				
			||||||
          description: List devices
 | 
					          description: List devices
 | 
				
			||||||
@@ -3006,6 +3065,60 @@ paths:
 | 
				
			|||||||
        404:
 | 
					        404:
 | 
				
			||||||
          $ref: '#/components/responses/NotFound'
 | 
					          $ref: '#/components/responses/NotFound'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /device/{serialNumber}/reenroll:
 | 
				
			||||||
 | 
					    post:
 | 
				
			||||||
 | 
					      tags:
 | 
				
			||||||
 | 
					        - Commands
 | 
				
			||||||
 | 
					      summary: Reenroll operational certificate for the device.
 | 
				
			||||||
 | 
					      operationId: reenrollCertificate
 | 
				
			||||||
 | 
					      parameters:
 | 
				
			||||||
 | 
					        - in: path
 | 
				
			||||||
 | 
					          name: serialNumber
 | 
				
			||||||
 | 
					          schema:
 | 
				
			||||||
 | 
					            type: string
 | 
				
			||||||
 | 
					          required: true
 | 
				
			||||||
 | 
					      requestBody:
 | 
				
			||||||
 | 
					        description: Reenroll operational certificate for the device
 | 
				
			||||||
 | 
					        content:
 | 
				
			||||||
 | 
					          application/json:
 | 
				
			||||||
 | 
					            schema:
 | 
				
			||||||
 | 
					              $ref: '#/components/schemas/ReenrollRequest'
 | 
				
			||||||
 | 
					      responses:
 | 
				
			||||||
 | 
					        200:
 | 
				
			||||||
 | 
					          $ref: '#/components/responses/Success'
 | 
				
			||||||
 | 
					        403:
 | 
				
			||||||
 | 
					          $ref: '#/components/responses/Unauthorized'
 | 
				
			||||||
 | 
					        404:
 | 
				
			||||||
 | 
					          $ref: '#/components/responses/NotFound'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /device/{serialNumber}/powercycle:
 | 
				
			||||||
 | 
					    post:
 | 
				
			||||||
 | 
					      tags:
 | 
				
			||||||
 | 
					        - Commands
 | 
				
			||||||
 | 
					      summary: Perform PoE power cycle for some PoE ports.
 | 
				
			||||||
 | 
					      operationId: performPowerCycle
 | 
				
			||||||
 | 
					      parameters:
 | 
				
			||||||
 | 
					        - in: path
 | 
				
			||||||
 | 
					          name: serialNumber
 | 
				
			||||||
 | 
					          schema:
 | 
				
			||||||
 | 
					            type: string
 | 
				
			||||||
 | 
					          required: true
 | 
				
			||||||
 | 
					      requestBody:
 | 
				
			||||||
 | 
					        description: Certificate update details
 | 
				
			||||||
 | 
					        content:
 | 
				
			||||||
 | 
					          application/json:
 | 
				
			||||||
 | 
					            schema:
 | 
				
			||||||
 | 
					              type: array
 | 
				
			||||||
 | 
					              items:
 | 
				
			||||||
 | 
					                $ref: '#/components/schemas/PowerCycleRequest'
 | 
				
			||||||
 | 
					      responses:
 | 
				
			||||||
 | 
					        200:
 | 
				
			||||||
 | 
					          $ref: '#/components/responses/Success'
 | 
				
			||||||
 | 
					        403:
 | 
				
			||||||
 | 
					          $ref: '#/components/responses/Unauthorized'
 | 
				
			||||||
 | 
					        404:
 | 
				
			||||||
 | 
					          $ref: '#/components/responses/NotFound'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /ouis:
 | 
					  /ouis:
 | 
				
			||||||
    get:
 | 
					    get:
 | 
				
			||||||
      tags:
 | 
					      tags:
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -9,14 +9,14 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
namespace OpenWifi {
 | 
					namespace OpenWifi {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	int AP_WS_ConfigAutoUpgrader::Start() {
 | 
						int AP_WS_ConfigAutoUpgradeAgent::Start() {
 | 
				
			||||||
		poco_notice(Logger(), "Starting...");
 | 
							poco_notice(Logger(), "Starting...");
 | 
				
			||||||
		QueueManager_.start(*this);
 | 
							QueueManager_.start(*this);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		return 0;
 | 
							return 0;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	void AP_WS_ConfigAutoUpgrader::Stop() {
 | 
						void AP_WS_ConfigAutoUpgradeAgent::Stop() {
 | 
				
			||||||
		poco_notice(Logger(), "Stopping...");
 | 
							poco_notice(Logger(), "Stopping...");
 | 
				
			||||||
		Running_ = false;
 | 
							Running_ = false;
 | 
				
			||||||
		Queue_.wakeUpAll();
 | 
							Queue_.wakeUpAll();
 | 
				
			||||||
@@ -24,7 +24,7 @@ namespace OpenWifi {
 | 
				
			|||||||
		poco_notice(Logger(), "Stopped...");
 | 
							poco_notice(Logger(), "Stopped...");
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	void AP_WS_ConfigAutoUpgrader::run() {
 | 
						void AP_WS_ConfigAutoUpgradeAgent::run() {
 | 
				
			||||||
		Utils::SetThreadName("auto:cfgmgr");
 | 
							Utils::SetThreadName("auto:cfgmgr");
 | 
				
			||||||
		Running_ = true;
 | 
							Running_ = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -28,14 +28,14 @@ namespace OpenWifi {
 | 
				
			|||||||
		std::uint64_t pending_config_=0;
 | 
							std::uint64_t pending_config_=0;
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	class AP_WS_ConfigAutoUpgrader : public SubSystemServer, Poco::Runnable {
 | 
						class AP_WS_ConfigAutoUpgradeAgent : public SubSystemServer, Poco::Runnable {
 | 
				
			||||||
	  public:
 | 
						  public:
 | 
				
			||||||
		int Start() final;
 | 
							int Start() final;
 | 
				
			||||||
		void Stop() final;
 | 
							void Stop() final;
 | 
				
			||||||
		void run() final;
 | 
							void run() final;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		static auto instance() {
 | 
							static auto instance() {
 | 
				
			||||||
			static auto instance = new AP_WS_ConfigAutoUpgrader;
 | 
								static auto instance = new AP_WS_ConfigAutoUpgradeAgent;
 | 
				
			||||||
			return instance;
 | 
								return instance;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -126,12 +126,12 @@ namespace OpenWifi {
 | 
				
			|||||||
		mutable std::mutex			CacheMutex_;
 | 
							mutable std::mutex			CacheMutex_;
 | 
				
			||||||
		std::map<std::uint64_t, ConfigurationCacheEntry> Cache_;
 | 
							std::map<std::uint64_t, ConfigurationCacheEntry> Cache_;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		AP_WS_ConfigAutoUpgrader() noexcept
 | 
							AP_WS_ConfigAutoUpgradeAgent() noexcept
 | 
				
			||||||
			: SubSystemServer("AutoConfigUpgrade", "AUTO-CFG-MGR", "auto.config.updater") {
 | 
								: SubSystemServer("AutoConfigUpgrade", "AUTO-CFG-MGR", "auto.config.updater") {
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	inline auto AP_WS_ConfigAutoUpgrader() { return AP_WS_ConfigAutoUpgrader::instance(); }
 | 
						inline auto AP_WS_ConfigAutoUpgradeAgent() { return AP_WS_ConfigAutoUpgradeAgent::instance(); }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
} // namespace OpenWifi
 | 
					} // namespace OpenWifi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2,37 +2,32 @@
 | 
				
			|||||||
// Created by stephane bourque on 2022-02-03.
 | 
					// Created by stephane bourque on 2022-02-03.
 | 
				
			||||||
//
 | 
					//
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "AP_WS_Connection.h"
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "Poco/Base64Decoder.h"
 | 
					#include <Poco/Base64Decoder.h>
 | 
				
			||||||
#include "Poco/Net/Context.h"
 | 
					#include <Poco/Net/Context.h>
 | 
				
			||||||
#include "Poco/Net/HTTPServerRequestImpl.h"
 | 
					#include <Poco/Net/HTTPServerRequestImpl.h>
 | 
				
			||||||
#include "Poco/Net/HTTPServerResponseImpl.h"
 | 
					#include <Poco/Net/HTTPServerResponseImpl.h>
 | 
				
			||||||
#include "Poco/Net/NetException.h"
 | 
					#include <Poco/Net/NetException.h>
 | 
				
			||||||
#include "Poco/Net/SSLException.h"
 | 
					#include <Poco/Net/SSLException.h>
 | 
				
			||||||
#include "Poco/Net/SecureStreamSocketImpl.h"
 | 
					#include <Poco/Net/SecureStreamSocketImpl.h>
 | 
				
			||||||
#include "Poco/Net/WebSocketImpl.h"
 | 
					#include <Poco/Net/WebSocketImpl.h>
 | 
				
			||||||
#include "Poco/zlib.h"
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "AP_WS_Server.h"
 | 
					#include <framework/KafkaManager.h>
 | 
				
			||||||
#include "CentralConfig.h"
 | 
					#include <framework/MicroServiceFuncs.h>
 | 
				
			||||||
#include "CommandManager.h"
 | 
					#include <framework/utils.h>
 | 
				
			||||||
#include "ConfigurationCache.h"
 | 
					#include <framework/ow_constants.h>
 | 
				
			||||||
#include "StorageService.h"
 | 
					 | 
				
			||||||
#include "TelemetryStream.h"
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "GWKafkaEvents.h"
 | 
					#include <fmt/format.h>
 | 
				
			||||||
#include "UI_GW_WebSocketNotifications.h"
 | 
					 | 
				
			||||||
#include "framework/KafkaManager.h"
 | 
					 | 
				
			||||||
#include "framework/MicroServiceFuncs.h"
 | 
					 | 
				
			||||||
#include "framework/utils.h"
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "fmt/format.h"
 | 
					#include <AP_WS_Connection.h>
 | 
				
			||||||
 | 
					#include <AP_WS_Server.h>
 | 
				
			||||||
#include "framework/ow_constants.h"
 | 
					#include <CentralConfig.h>
 | 
				
			||||||
 | 
					#include <CommandManager.h>
 | 
				
			||||||
#include "RADIUSSessionTracker.h"
 | 
					#include <StorageService.h>
 | 
				
			||||||
#include "RADIUS_proxy_server.h"
 | 
					#include <RADIUSSessionTracker.h>
 | 
				
			||||||
 | 
					#include <RADIUS_proxy_server.h>
 | 
				
			||||||
 | 
					#include <GWKafkaEvents.h>
 | 
				
			||||||
 | 
					#include <UI_GW_WebSocketNotifications.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace OpenWifi {
 | 
					namespace OpenWifi {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -60,6 +55,8 @@ namespace OpenWifi {
 | 
				
			|||||||
		WS_->setKeepAlive(true);
 | 
							WS_->setKeepAlive(true);
 | 
				
			||||||
		WS_->setBlocking(false);
 | 
							WS_->setBlocking(false);
 | 
				
			||||||
		uuid_ = MicroServiceRandom(std::numeric_limits<std::uint64_t>::max()-1);
 | 
							uuid_ = MicroServiceRandom(std::numeric_limits<std::uint64_t>::max()-1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							AP_WS_Server()->IncrementConnectionCount();
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	void AP_WS_Connection::Start() {
 | 
						void AP_WS_Connection::Start() {
 | 
				
			||||||
@@ -79,14 +76,11 @@ namespace OpenWifi {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	AP_WS_Connection::~AP_WS_Connection() {
 | 
						AP_WS_Connection::~AP_WS_Connection() {
 | 
				
			||||||
//		poco_information(Logger_, fmt::format("DESTRUCTOR({}): 0 - Session={} Connection closed.", SerialNumber_,
 | 
					 | 
				
			||||||
//											  State_.sessionId));
 | 
					 | 
				
			||||||
		std::lock_guard G(ConnectionMutex_);
 | 
							std::lock_guard G(ConnectionMutex_);
 | 
				
			||||||
//		poco_information(Logger_, fmt::format("DESTRUCTOR({}): 1 - Session={} Connection closed.", SerialNumber_,
 | 
							AP_WS_Server()->DecrementConnectionCount();
 | 
				
			||||||
//											  State_.sessionId));
 | 
							EndConnection();
 | 
				
			||||||
		EndConnection(false);
 | 
					 | 
				
			||||||
		poco_debug(Logger_, fmt::format("TERMINATION({}): Session={}, Connection removed.", SerialNumber_,
 | 
							poco_debug(Logger_, fmt::format("TERMINATION({}): Session={}, Connection removed.", SerialNumber_,
 | 
				
			||||||
											  State_.sessionId));
 | 
															State_.sessionId));
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	static void NotifyKafkaDisconnect(const std::string &SerialNumber, std::uint64_t uuid) {
 | 
						static void NotifyKafkaDisconnect(const std::string &SerialNumber, std::uint64_t uuid) {
 | 
				
			||||||
@@ -102,7 +96,7 @@ namespace OpenWifi {
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	void AP_WS_Connection::EndConnection(bool Clean) {
 | 
						void AP_WS_Connection::EndConnection() {
 | 
				
			||||||
		bool expectedValue=false;
 | 
							bool expectedValue=false;
 | 
				
			||||||
		if (Dead_.compare_exchange_strong(expectedValue,true,std::memory_order_release,std::memory_order_relaxed)) {
 | 
							if (Dead_.compare_exchange_strong(expectedValue,true,std::memory_order_release,std::memory_order_relaxed)) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -128,9 +122,7 @@ namespace OpenWifi {
 | 
				
			|||||||
			if(!SerialNumber_.empty()) {
 | 
								if(!SerialNumber_.empty()) {
 | 
				
			||||||
				DeviceDisconnectionCleanup(SerialNumber_, uuid_);
 | 
									DeviceDisconnectionCleanup(SerialNumber_, uuid_);
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
								AP_WS_Server()->AddCleanupSession(State_.sessionId, SerialNumberInt_);
 | 
				
			||||||
			if(Clean)
 | 
					 | 
				
			||||||
				AP_WS_Server()->EndSession(State_.sessionId, SerialNumberInt_);
 | 
					 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -221,6 +213,7 @@ namespace OpenWifi {
 | 
				
			|||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			State_.certificateExpiryDate = PeerCert.expiresOn().timestamp().epochTime();
 | 
								State_.certificateExpiryDate = PeerCert.expiresOn().timestamp().epochTime();
 | 
				
			||||||
 | 
								State_.certificateIssuerName = PeerCert.issuerName();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			poco_trace(Logger_,
 | 
								poco_trace(Logger_,
 | 
				
			||||||
					   fmt::format("TLS-CONNECTION({}): Session={} CN={} Completed. (t={})", CId_,
 | 
										   fmt::format("TLS-CONNECTION({}): Session={} CN={} Completed. (t={})", CId_,
 | 
				
			||||||
@@ -569,14 +562,14 @@ 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_);
 | 
					//		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_);
 | 
					//		std::lock_guard	G(ConnectionMutex_);
 | 
				
			||||||
		return EndConnection();
 | 
							return EndConnection();
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -586,7 +579,7 @@ namespace OpenWifi {
 | 
				
			|||||||
		if (Dead_) //	we are dead, so we do not process anything.
 | 
							if (Dead_) //	we are dead, so we do not process anything.
 | 
				
			||||||
			return;
 | 
								return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		std::lock_guard	DeviceLock(ConnectionMutex_);
 | 
							std::lock_guard	G(ConnectionMutex_);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		State_.LastContact = LastContact_ = Utils::Now();
 | 
							State_.LastContact = LastContact_ = Utils::Now();
 | 
				
			||||||
		if (AP_WS_Server()->Running() && (DeviceValidated_ || ValidatedDevice())) {
 | 
							if (AP_WS_Server()->Running() && (DeviceValidated_ || ValidatedDevice())) {
 | 
				
			||||||
@@ -902,25 +895,25 @@ namespace OpenWifi {
 | 
				
			|||||||
		try {
 | 
							try {
 | 
				
			||||||
			Poco::JSON::Parser P;
 | 
								Poco::JSON::Parser P;
 | 
				
			||||||
			auto Stats = P.parse(LastStats).extract<Poco::JSON::Object::Ptr>();
 | 
								auto Stats = P.parse(LastStats).extract<Poco::JSON::Object::Ptr>();
 | 
				
			||||||
			hasGPS_ = Stats->isObject("gps");
 | 
								State_.hasGPS = Stats->isObject("gps");
 | 
				
			||||||
			auto Unit = Stats->getObject("unit");
 | 
								auto Unit = Stats->getObject("unit");
 | 
				
			||||||
			auto Memory = Unit->getObject("memory");
 | 
								auto Memory = Unit->getObject("memory");
 | 
				
			||||||
			std::uint64_t TotalMemory = Memory->get("total");
 | 
								std::uint64_t TotalMemory = Memory->get("total");
 | 
				
			||||||
			std::uint64_t FreeMemory = Memory->get("free");
 | 
								std::uint64_t FreeMemory = Memory->get("free");
 | 
				
			||||||
			if (TotalMemory > 0) {
 | 
								if (TotalMemory > 0) {
 | 
				
			||||||
				memory_used_ =
 | 
									State_.memoryUsed =
 | 
				
			||||||
					(100.0 * ((double)TotalMemory - (double)FreeMemory)) / (double)TotalMemory;
 | 
										(100.0 * ((double)TotalMemory - (double)FreeMemory)) / (double)TotalMemory;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			if (Unit->isArray("load")) {
 | 
								if (Unit->isArray("load")) {
 | 
				
			||||||
				Poco::JSON::Array::Ptr Load = Unit->getArray("load");
 | 
									Poco::JSON::Array::Ptr Load = Unit->getArray("load");
 | 
				
			||||||
				if (Load->size() > 1) {
 | 
									if (Load->size() > 1) {
 | 
				
			||||||
					cpu_load_ = Load->get(1);
 | 
										State_.load = Load->get(1);
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			if (Unit->isArray("temperature")) {
 | 
								if (Unit->isArray("temperature")) {
 | 
				
			||||||
				Poco::JSON::Array::Ptr Temperature = Unit->getArray("temperature");
 | 
									Poco::JSON::Array::Ptr Temperature = Unit->getArray("temperature");
 | 
				
			||||||
				if (Temperature->size() > 1) {
 | 
									if (Temperature->size() > 1) {
 | 
				
			||||||
					temperature_ = Temperature->get(0);
 | 
										State_.temperature = Temperature->get(0);
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		} catch (const Poco::Exception &E) {
 | 
							} catch (const Poco::Exception &E) {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -30,7 +30,7 @@ namespace OpenWifi {
 | 
				
			|||||||
								  Poco::Logger &L, std::pair<std::shared_ptr<Poco::Net::SocketReactor>, std::shared_ptr<LockedDbSession>> 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 Clean = true);
 | 
							void EndConnection();
 | 
				
			||||||
		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();
 | 
				
			||||||
@@ -79,14 +79,14 @@ namespace OpenWifi {
 | 
				
			|||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							inline GWObjects::DeviceRestrictions GetRestrictions() {
 | 
				
			||||||
 | 
								std::lock_guard G(ConnectionMutex_);
 | 
				
			||||||
 | 
								return Restrictions_;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		[[nodiscard]] inline bool HasGPS() const { return hasGPS_; }
 | 
							[[nodiscard]] inline bool HasGPS() const { return hasGPS_; }
 | 
				
			||||||
		[[nodiscard]] bool ValidatedDevice();
 | 
							[[nodiscard]] bool ValidatedDevice();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		inline void GetRestrictions(GWObjects::DeviceRestrictions &R) {
 | 
					 | 
				
			||||||
			std::lock_guard G(ConnectionMutex_);
 | 
					 | 
				
			||||||
			R = Restrictions_;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		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,
 | 
				
			||||||
@@ -105,14 +105,10 @@ namespace OpenWifi {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
		friend class AP_WS_Server;
 | 
							friend class AP_WS_Server;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		inline GWObjects::DeviceRestrictions Restrictions() {
 | 
					 | 
				
			||||||
			std::lock_guard G(ConnectionMutex_);
 | 
					 | 
				
			||||||
			return Restrictions_;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		void Start();
 | 
							void Start();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	  private:
 | 
						  private:
 | 
				
			||||||
		std::recursive_mutex ConnectionMutex_;
 | 
							mutable std::recursive_mutex ConnectionMutex_;
 | 
				
			||||||
		std::mutex TelemetryMutex_;
 | 
							std::mutex TelemetryMutex_;
 | 
				
			||||||
		Poco::Logger &Logger_;
 | 
							Poco::Logger &Logger_;
 | 
				
			||||||
		std::shared_ptr<Poco::Net::SocketReactor> 	Reactor_;
 | 
							std::shared_ptr<Poco::Net::SocketReactor> 	Reactor_;
 | 
				
			||||||
@@ -148,7 +144,7 @@ namespace OpenWifi {
 | 
				
			|||||||
		std::double_t 	memory_used_=0.0, cpu_load_ = 0.0, temperature_ = 0.0;
 | 
							std::double_t 	memory_used_=0.0, cpu_load_ = 0.0, temperature_ = 0.0;
 | 
				
			||||||
		std::uint64_t 	uuid_=0;
 | 
							std::uint64_t 	uuid_=0;
 | 
				
			||||||
		bool	Simulated_=false;
 | 
							bool	Simulated_=false;
 | 
				
			||||||
		std::uint64_t 	LastContact_=0;
 | 
							std::atomic_uint64_t 	LastContact_=0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		static inline std::atomic_uint64_t ConcurrentStartingDevices_ = 0;
 | 
							static inline std::atomic_uint64_t ConcurrentStartingDevices_ = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -11,78 +11,101 @@ namespace OpenWifi {
 | 
				
			|||||||
		if (UUID == 0)
 | 
							if (UUID == 0)
 | 
				
			||||||
			return false;
 | 
								return false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		uint64_t GoodConfig = ConfigurationCache().CurrentConfig(SerialNumberInt_);
 | 
							uint64_t GoodConfig = GetCurrentConfigurationID(SerialNumberInt_);
 | 
				
			||||||
		if (GoodConfig && (GoodConfig == UUID || GoodConfig == State_.PendingUUID)) {
 | 
							if (GoodConfig && (GoodConfig == UUID || GoodConfig == State_.PendingUUID)) {
 | 
				
			||||||
			UpgradedUUID = UUID;
 | 
								UpgradedUUID = UUID;
 | 
				
			||||||
 | 
								State_.PendingUUID = 0;
 | 
				
			||||||
			return false;
 | 
								return false;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		GWObjects::Device D;
 | 
							GWObjects::Device D;
 | 
				
			||||||
		if (StorageService()->GetDevice(Session,SerialNumber_, D)) {
 | 
							if (!StorageService()->GetDevice(Session,SerialNumber_, D)) {
 | 
				
			||||||
			if(D.pendingUUID!=0 && UUID==D.pendingUUID) {
 | 
								return false;
 | 
				
			||||||
				//	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);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if(State_.PendingUUID!=0 && UUID==State_.PendingUUID) {
 | 
				
			||||||
 | 
								//	so we sent an upgrade to a device, and now it is completing now...
 | 
				
			||||||
 | 
								UpgradedUUID = UUID;
 | 
				
			||||||
 | 
								StorageService()->CompleteDeviceConfigurationChange(Session, SerialNumber_);
 | 
				
			||||||
 | 
								State_.PendingUUID = 0;
 | 
				
			||||||
			return true;
 | 
								return true;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		return false;
 | 
					
 | 
				
			||||||
 | 
							// dont upgrade a switch if it does not have a real config. Config will always be more than 20 characters
 | 
				
			||||||
 | 
							if (D.DeviceType==Platforms::SWITCH && D.Configuration.size()<20) {
 | 
				
			||||||
 | 
								return false;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							Config::Config Cfg(D.Configuration);
 | 
				
			||||||
 | 
							//	if this is a broken device (UUID==0) just fix it
 | 
				
			||||||
 | 
							auto StoredConfigurationUUID = Cfg.UUID();
 | 
				
			||||||
 | 
							if(D.UUID==0) {
 | 
				
			||||||
 | 
								D.UUID = StoredConfigurationUUID;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (D.UUID == UUID) {
 | 
				
			||||||
 | 
								D.UUID = UpgradedUUID = UUID;
 | 
				
			||||||
 | 
								State_.PendingUUID = D.pendingUUID = 0;
 | 
				
			||||||
 | 
								D.pendingConfiguration.clear();
 | 
				
			||||||
 | 
								D.pendingConfigurationCmd.clear();
 | 
				
			||||||
 | 
								StorageService()->UpdateDevice(Session, D);
 | 
				
			||||||
 | 
								SetCurrentConfigurationID(SerialNumberInt_, UUID);
 | 
				
			||||||
 | 
					//			std::cout << __LINE__ << ": " << SerialNumber_ << "  GoodConfig: " << GoodConfig << "   UUID:" << UUID << "  Pending:" << State_.PendingUUID << std::endl;
 | 
				
			||||||
 | 
								return false;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							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;
 | 
				
			||||||
 | 
					//			std::cout << __LINE__ << ": " << SerialNumber_  << "  GoodConfig: " << GoodConfig << "   UUID:" << UUID << "  Pending:" << State_.PendingUUID << std::endl;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							Cfg.SetUUID(D.UUID);
 | 
				
			||||||
 | 
							D.Configuration = Cfg.get();
 | 
				
			||||||
 | 
							D.pendingUUID = State_.PendingUUID = UpgradedUUID = D.UUID;
 | 
				
			||||||
 | 
							StorageService()->UpdateDevice(Session, D);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							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);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//		std::cout << __LINE__ << ": " << SerialNumber_ << "  GoodConfig: " << GoodConfig << "   UUID:" << UUID <<
 | 
				
			||||||
 | 
					//			"  Pending:" << State_.PendingUUID << "  Upgraded:" << UpgradedUUID << std::endl;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							return true;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -83,6 +83,8 @@ namespace OpenWifi {
 | 
				
			|||||||
			State_.Address = Utils::FormatIPv6(WS_->peerAddress().toString());
 | 
								State_.Address = Utils::FormatIPv6(WS_->peerAddress().toString());
 | 
				
			||||||
			CId_ = SerialNumber_ + "@" + CId_;
 | 
								CId_ = SerialNumber_ + "@" + CId_;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								auto Platform = Poco::toLower(Caps.Platform());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if(ParamsObj->has("reason")) {
 | 
								if(ParamsObj->has("reason")) {
 | 
				
			||||||
				State_.connectReason = ParamsObj->get("reason").toString();
 | 
									State_.connectReason = ParamsObj->get("reason").toString();
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
@@ -204,8 +206,13 @@ namespace OpenWifi {
 | 
				
			|||||||
					++Updated;
 | 
										++Updated;
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				if (Compatible_ != DeviceInfo.DeviceType) {
 | 
									if (Compatible_ != DeviceInfo.Compatible) {
 | 
				
			||||||
					DeviceInfo.DeviceType = Compatible_;
 | 
										DeviceInfo.Compatible = Compatible_;
 | 
				
			||||||
 | 
										++Updated;
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									if (Platform != DeviceInfo.DeviceType) {
 | 
				
			||||||
 | 
										DeviceInfo.DeviceType = Platform;
 | 
				
			||||||
					++Updated;
 | 
										++Updated;
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -227,10 +234,11 @@ namespace OpenWifi {
 | 
				
			|||||||
				if (Updated) {
 | 
									if (Updated) {
 | 
				
			||||||
					StorageService()->UpdateDevice(DbSession_->Session(), DeviceInfo);
 | 
										StorageService()->UpdateDevice(DbSession_->Session(), DeviceInfo);
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				if(!Simulated_) {
 | 
								if(!Simulated_) {
 | 
				
			||||||
					uint64_t UpgradedUUID = 0;
 | 
									uint64_t UpgradedUUID = 0;
 | 
				
			||||||
					LookForUpgrade(DbSession_->Session(), UUID, UpgradedUUID);
 | 
									if (LookForUpgrade(DbSession_->Session(), UUID, UpgradedUUID)) {
 | 
				
			||||||
					State_.UUID = UpgradedUUID;
 | 
										State_.UUID = UpgradedUUID;
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -26,6 +26,7 @@ namespace OpenWifi {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
			uint64_t UUID = ParamsObj->get(uCentralProtocol::UUID);
 | 
								uint64_t UUID = ParamsObj->get(uCentralProtocol::UUID);
 | 
				
			||||||
			auto Sanity = ParamsObj->get(uCentralProtocol::SANITY);
 | 
								auto Sanity = ParamsObj->get(uCentralProtocol::SANITY);
 | 
				
			||||||
 | 
								State_.sanity = Sanity;
 | 
				
			||||||
			auto CheckData = ParamsObj->get(uCentralProtocol::DATA).toString();
 | 
								auto CheckData = ParamsObj->get(uCentralProtocol::DATA).toString();
 | 
				
			||||||
			if (CheckData.empty())
 | 
								if (CheckData.empty())
 | 
				
			||||||
				CheckData = uCentralProtocol::EMPTY_JSON_DOC;
 | 
									CheckData = uCentralProtocol::EMPTY_JSON_DOC;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -58,7 +58,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, State_.uptime);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if (KafkaManager()->Enabled() && !AP_WS_Server()->KafkaDisableState()) {
 | 
								if (KafkaManager()->Enabled() && !AP_WS_Server()->KafkaDisableState()) {
 | 
				
			||||||
				KafkaManager()->PostMessage(KafkaTopics::STATE, SerialNumber_, *ParamsObj);
 | 
									KafkaManager()->PostMessage(KafkaTopics::STATE, SerialNumber_, *ParamsObj);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -7,10 +7,12 @@
 | 
				
			|||||||
#include <mutex>
 | 
					#include <mutex>
 | 
				
			||||||
#include <string>
 | 
					#include <string>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "Poco/Environment.h"
 | 
					#include <framework/utils.h>
 | 
				
			||||||
#include "Poco/Net/SocketAcceptor.h"
 | 
					
 | 
				
			||||||
 | 
					#include <Poco/Environment.h>
 | 
				
			||||||
 | 
					#include <Poco/Net/SocketAcceptor.h>
 | 
				
			||||||
#include <Poco/Data/SessionPool.h>
 | 
					#include <Poco/Data/SessionPool.h>
 | 
				
			||||||
#include "framework/utils.h"
 | 
					
 | 
				
			||||||
#include <StorageService.h>
 | 
					#include <StorageService.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace OpenWifi {
 | 
					namespace OpenWifi {
 | 
				
			||||||
@@ -55,7 +57,7 @@ namespace OpenWifi {
 | 
				
			|||||||
			DbSessions_.clear();
 | 
								DbSessions_.clear();
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		std::pair<std::shared_ptr<Poco::Net::SocketReactor>, std::shared_ptr<LockedDbSession> > NextReactor() {
 | 
							auto NextReactor() {
 | 
				
			||||||
			std::lock_guard Lock(Mutex_);
 | 
								std::lock_guard Lock(Mutex_);
 | 
				
			||||||
			NextReactor_++;
 | 
								NextReactor_++;
 | 
				
			||||||
			NextReactor_ %= NumberOfThreads_;
 | 
								NextReactor_ %= NumberOfThreads_;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -6,21 +6,23 @@
 | 
				
			|||||||
//	Arilia Wireless Inc.
 | 
					//	Arilia Wireless Inc.
 | 
				
			||||||
//
 | 
					//
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "Poco/Net/Context.h"
 | 
					#include <Poco/Net/Context.h>
 | 
				
			||||||
#include "Poco/Net/HTTPHeaderStream.h"
 | 
					#include <Poco/Net/HTTPHeaderStream.h>
 | 
				
			||||||
#include "Poco/Net/HTTPServerRequest.h"
 | 
					#include <Poco/Net/HTTPServerRequest.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "AP_WS_Connection.h"
 | 
					#include <AP_WS_Connection.h>
 | 
				
			||||||
#include "AP_WS_Server.h"
 | 
					#include <AP_WS_Server.h>
 | 
				
			||||||
#include "ConfigurationCache.h"
 | 
					#include <ConfigurationCache.h>
 | 
				
			||||||
#include "TelemetryStream.h"
 | 
					#include <TelemetryStream.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "UI_GW_WebSocketNotifications.h"
 | 
					#include <fmt/format.h>
 | 
				
			||||||
#include "fmt/format.h"
 | 
					
 | 
				
			||||||
#include "framework/MicroServiceFuncs.h"
 | 
					#include <framework/MicroServiceFuncs.h>
 | 
				
			||||||
#include "framework/utils.h"
 | 
					#include <framework/utils.h>
 | 
				
			||||||
#include <framework/KafkaManager.h>
 | 
					#include <framework/KafkaManager.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <UI_GW_WebSocketNotifications.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace OpenWifi {
 | 
					namespace OpenWifi {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	class AP_WS_RequestHandler : public Poco::Net::HTTPRequestHandler {
 | 
						class AP_WS_RequestHandler : public Poco::Net::HTTPRequestHandler {
 | 
				
			||||||
@@ -69,14 +71,18 @@ namespace OpenWifi {
 | 
				
			|||||||
	bool AP_WS_Server::ValidateCertificate(const std::string &ConnectionId,
 | 
						bool AP_WS_Server::ValidateCertificate(const std::string &ConnectionId,
 | 
				
			||||||
										   const Poco::Crypto::X509Certificate &Certificate) {
 | 
															   const Poco::Crypto::X509Certificate &Certificate) {
 | 
				
			||||||
		if (IsCertOk()) {
 | 
							if (IsCertOk()) {
 | 
				
			||||||
			if (!Certificate.issuedBy(*IssuerCert_)) {
 | 
								// validate certificate agains trusted chain
 | 
				
			||||||
				poco_warning(
 | 
								for (const auto &cert : ClientCasCerts_) {
 | 
				
			||||||
					Logger(),
 | 
									if (Certificate.issuedBy(cert)) {
 | 
				
			||||||
					fmt::format("CERTIFICATE({}): issuer mismatch. Local='{}' Incoming='{}'",
 | 
										return true;
 | 
				
			||||||
								ConnectionId, IssuerCert_->issuerName(), Certificate.issuerName()));
 | 
									}
 | 
				
			||||||
				return false;
 | 
					 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			return true;
 | 
								poco_warning(
 | 
				
			||||||
 | 
										Logger(),
 | 
				
			||||||
 | 
										fmt::format(
 | 
				
			||||||
 | 
											"CERTIFICATE({}): issuer mismatch. Certificate not issued by any trusted CA",
 | 
				
			||||||
 | 
											ConnectionId)
 | 
				
			||||||
 | 
										);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		return false;
 | 
							return false;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -131,6 +137,13 @@ namespace OpenWifi {
 | 
				
			|||||||
			Context->addChainCertificate(Issuing);
 | 
								Context->addChainCertificate(Issuing);
 | 
				
			||||||
			Context->addCertificateAuthority(Issuing);
 | 
								Context->addCertificateAuthority(Issuing);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								// add certificates from clientcas to trust chain
 | 
				
			||||||
 | 
								ClientCasCerts_ = Poco::Net::X509Certificate::readPEM(Svr.ClientCas());
 | 
				
			||||||
 | 
								for (const auto &cert : ClientCasCerts_) {
 | 
				
			||||||
 | 
									Context->addChainCertificate(cert);
 | 
				
			||||||
 | 
									Context->addCertificateAuthority(cert);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			Poco::Crypto::RSAKey Key("", Svr.KeyFile(), Svr.KeyFilePassword());
 | 
								Poco::Crypto::RSAKey Key("", Svr.KeyFile(), Svr.KeyFilePassword());
 | 
				
			||||||
			Context->usePrivateKey(Key);
 | 
								Context->usePrivateKey(Key);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -198,9 +211,53 @@ namespace OpenWifi {
 | 
				
			|||||||
		Running_ = true;
 | 
							Running_ = true;
 | 
				
			||||||
		GarbageCollector_.setName("ws:garbage");
 | 
							GarbageCollector_.setName("ws:garbage");
 | 
				
			||||||
		GarbageCollector_.start(*this);
 | 
							GarbageCollector_.start(*this);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							std::thread CleanupThread([this](){ CleanupSessions(); });
 | 
				
			||||||
 | 
							CleanupThread.detach();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		return 0;
 | 
							return 0;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						bool AP_WS_Server::Disconnect(uint64_t SerialNumber) {
 | 
				
			||||||
 | 
							std::shared_ptr<AP_WS_Connection> Connection;
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								auto hashIndex = MACHash::Hash(SerialNumber);
 | 
				
			||||||
 | 
								std::lock_guard DeviceLock(SerialNumbersMutex_[hashIndex]);
 | 
				
			||||||
 | 
								auto DeviceHint = SerialNumbers_[hashIndex].find(SerialNumber);
 | 
				
			||||||
 | 
								if (DeviceHint == SerialNumbers_[hashIndex].end() || DeviceHint->second == nullptr) {
 | 
				
			||||||
 | 
									return false;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								Connection = DeviceHint->second;
 | 
				
			||||||
 | 
								SerialNumbers_[hashIndex].erase(DeviceHint);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								auto H = SessionHash::Hash(Connection->State_.sessionId);
 | 
				
			||||||
 | 
								std::lock_guard SessionLock(SessionMutex_[H]);
 | 
				
			||||||
 | 
								Sessions_[H].erase(Connection->State_.sessionId);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							return true;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						void AP_WS_Server::CleanupSessions() {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							while(Running_) {
 | 
				
			||||||
 | 
								std::this_thread::sleep_for(std::chrono::seconds(10));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								while(Running_ && !CleanupSessions_.empty()) {
 | 
				
			||||||
 | 
									std::pair<uint64_t, uint64_t> Session;
 | 
				
			||||||
 | 
									{
 | 
				
			||||||
 | 
										std::lock_guard G(CleanupMutex_);
 | 
				
			||||||
 | 
										Session = CleanupSessions_.front();
 | 
				
			||||||
 | 
										CleanupSessions_.pop_front();
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									poco_trace(this->Logger(),fmt::format("Cleaning up session: {} for device: {}", Session.first, Utils::IntToSerialNumber(Session.second)));
 | 
				
			||||||
 | 
									EndSession(Session.first, Session.second);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	void AP_WS_Server::run() {
 | 
						void AP_WS_Server::run() {
 | 
				
			||||||
		uint64_t last_log = Utils::Now(),
 | 
							uint64_t last_log = Utils::Now(),
 | 
				
			||||||
				 last_zombie_run = 0,
 | 
									 last_zombie_run = 0,
 | 
				
			||||||
@@ -223,7 +280,6 @@ namespace OpenWifi {
 | 
				
			|||||||
				try {
 | 
									try {
 | 
				
			||||||
					poco_information(LocalLogger,
 | 
										poco_information(LocalLogger,
 | 
				
			||||||
									 fmt::format("Garbage collecting zombies... (step 1)"));
 | 
														 fmt::format("Garbage collecting zombies... (step 1)"));
 | 
				
			||||||
					NumberOfConnectedDevices_ = 0;
 | 
					 | 
				
			||||||
					NumberOfConnectingDevices_ = 0;
 | 
										NumberOfConnectingDevices_ = 0;
 | 
				
			||||||
					AverageDeviceConnectionTime_ = 0;
 | 
										AverageDeviceConnectionTime_ = 0;
 | 
				
			||||||
					int waits = 0;
 | 
										int waits = 0;
 | 
				
			||||||
@@ -235,55 +291,49 @@ namespace OpenWifi {
 | 
				
			|||||||
								waits = 0;
 | 
													waits = 0;
 | 
				
			||||||
								auto hint = SerialNumbers_[hashIndex].begin();
 | 
													auto hint = SerialNumbers_[hashIndex].begin();
 | 
				
			||||||
								while (hint != end(SerialNumbers_[hashIndex])) {
 | 
													while (hint != end(SerialNumbers_[hashIndex])) {
 | 
				
			||||||
 | 
					 | 
				
			||||||
									if (hint->second == nullptr) {
 | 
														if (hint->second == nullptr) {
 | 
				
			||||||
										poco_information(
 | 
															poco_information(
 | 
				
			||||||
											LocalLogger,
 | 
																LocalLogger,
 | 
				
			||||||
											fmt::format("Dead device found in hash index {}", hashIndex));
 | 
																fmt::format("Dead device found in hash index {}", hashIndex));
 | 
				
			||||||
										// hint = SerialNumbers_[hashIndex].erase(hint);
 | 
															hint = SerialNumbers_[hashIndex].erase(hint);
 | 
				
			||||||
										hint++;
 | 
														} else {
 | 
				
			||||||
										continue;
 | 
															auto Device = hint->second;
 | 
				
			||||||
									}
 | 
					 | 
				
			||||||
									auto Device = hint->second;
 | 
					 | 
				
			||||||
									if(Device->ConnectionMutex_.try_lock()) {
 | 
					 | 
				
			||||||
										auto RightNow = Utils::Now();
 | 
															auto RightNow = Utils::Now();
 | 
				
			||||||
										if (RightNow > Device->LastContact_ &&
 | 
															if (Device->Dead_) {
 | 
				
			||||||
											(RightNow - Device->LastContact_) > SessionTimeOut_) {
 | 
																AddCleanupSession(Device->State_.sessionId, Device->SerialNumberInt_);
 | 
				
			||||||
 | 
																++hint;
 | 
				
			||||||
 | 
																// hint = SerialNumbers_[hashIndex].erase(hint);
 | 
				
			||||||
 | 
															} else if (RightNow > Device->LastContact_ &&
 | 
				
			||||||
 | 
																	   (RightNow - Device->LastContact_) > SessionTimeOut_) {
 | 
				
			||||||
											poco_information(
 | 
																poco_information(
 | 
				
			||||||
												LocalLogger,
 | 
																	LocalLogger,
 | 
				
			||||||
												fmt::format("{}: Session seems idle. Controller disconnecting device.",
 | 
																	fmt::format(
 | 
				
			||||||
															Device->SerialNumber_));
 | 
																		"{}: Session seems idle. Controller disconnecting device.",
 | 
				
			||||||
											hint = SerialNumbers_[hashIndex].erase(hint);
 | 
																		Device->SerialNumber_));
 | 
				
			||||||
										} else if (Device->State_.Connected) {
 | 
																// hint = SerialNumbers_[hashIndex].erase(hint);
 | 
				
			||||||
											NumberOfConnectedDevices_++;
 | 
																AddCleanupSession(Device->State_.sessionId, Device->SerialNumberInt_);
 | 
				
			||||||
											total_connected_time +=
 | 
					 | 
				
			||||||
												(RightNow - Device->State_.started);
 | 
					 | 
				
			||||||
											++hint;
 | 
																++hint;
 | 
				
			||||||
										} else {
 | 
															} else {
 | 
				
			||||||
 | 
																if (Device->State_.Connected) {
 | 
				
			||||||
 | 
																	total_connected_time +=
 | 
				
			||||||
 | 
																		(RightNow - Device->State_.started);
 | 
				
			||||||
 | 
																}
 | 
				
			||||||
											++hint;
 | 
																++hint;
 | 
				
			||||||
										}
 | 
															}
 | 
				
			||||||
										Device->ConnectionMutex_.unlock();
 | 
					 | 
				
			||||||
										continue;
 | 
					 | 
				
			||||||
									} else {
 | 
					 | 
				
			||||||
										poco_warning(LocalLogger, fmt::format("Could not lock device mutex for {}",
 | 
					 | 
				
			||||||
																			   Device->SerialNumber_));
 | 
					 | 
				
			||||||
									}
 | 
														}
 | 
				
			||||||
									++NumberOfConnectingDevices_;
 | 
					 | 
				
			||||||
									++hint;
 | 
					 | 
				
			||||||
								}
 | 
													}
 | 
				
			||||||
								SerialNumbersMutex_[hashIndex].unlock();
 | 
													SerialNumbersMutex_[hashIndex].unlock();
 | 
				
			||||||
								break;
 | 
													break;
 | 
				
			||||||
							} else if (waits < 5) {
 | 
												} else if (waits < 5) {
 | 
				
			||||||
								waits++;
 | 
													waits++;
 | 
				
			||||||
								std::this_thread::sleep_for(std::chrono::milliseconds(10));
 | 
													Poco::Thread::trySleep(10);
 | 
				
			||||||
							} else {
 | 
												} else {
 | 
				
			||||||
								break;
 | 
													break;
 | 
				
			||||||
							}
 | 
												}
 | 
				
			||||||
						}
 | 
											}
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
					poco_information(LocalLogger,
 | 
										poco_information(LocalLogger, fmt::format("Garbage collecting zombies... (step 2)"));
 | 
				
			||||||
									 fmt::format("Garbage collecting zombies... (step 2)"));
 | 
					 | 
				
			||||||
					LeftOverSessions_ = 0;
 | 
										LeftOverSessions_ = 0;
 | 
				
			||||||
					for (int i = 0; i < SessionHash::HashMax(); i++) {
 | 
										for (int i = 0; i < SessionHash::HashMax(); i++) {
 | 
				
			||||||
						waits = 0;
 | 
											waits = 0;
 | 
				
			||||||
@@ -295,6 +345,10 @@ namespace OpenWifi {
 | 
				
			|||||||
								while (hint != end(Sessions_[i])) {
 | 
													while (hint != end(Sessions_[i])) {
 | 
				
			||||||
									if (hint->second == nullptr) {
 | 
														if (hint->second == nullptr) {
 | 
				
			||||||
										hint = Sessions_[i].erase(hint);
 | 
															hint = Sessions_[i].erase(hint);
 | 
				
			||||||
 | 
														} else if (hint->second->Dead_) {
 | 
				
			||||||
 | 
															// hint = Sessions_[i].erase(hint);
 | 
				
			||||||
 | 
															AddCleanupSession(hint->second->State_.sessionId, hint->second->SerialNumberInt_);
 | 
				
			||||||
 | 
															++hint;
 | 
				
			||||||
									} else if (RightNow > hint->second->LastContact_ &&
 | 
														} else if (RightNow > hint->second->LastContact_ &&
 | 
				
			||||||
											   (RightNow - hint->second->LastContact_) >
 | 
																   (RightNow - hint->second->LastContact_) >
 | 
				
			||||||
												   SessionTimeOut_) {
 | 
																	   SessionTimeOut_) {
 | 
				
			||||||
@@ -302,7 +356,9 @@ namespace OpenWifi {
 | 
				
			|||||||
											LocalLogger,
 | 
																LocalLogger,
 | 
				
			||||||
											fmt::format("{}: Session seems idle. Controller disconnecting device.",
 | 
																fmt::format("{}: Session seems idle. Controller disconnecting device.",
 | 
				
			||||||
														hint->second->SerialNumber_));
 | 
																			hint->second->SerialNumber_));
 | 
				
			||||||
										hint = Sessions_[i].erase(hint);
 | 
															AddCleanupSession(hint->second->State_.sessionId, hint->second->SerialNumberInt_);
 | 
				
			||||||
 | 
															++hint;
 | 
				
			||||||
 | 
															// hint = Sessions_[i].erase(hint);
 | 
				
			||||||
									} else {
 | 
														} else {
 | 
				
			||||||
										++LeftOverSessions_;
 | 
															++LeftOverSessions_;
 | 
				
			||||||
										++hint;
 | 
															++hint;
 | 
				
			||||||
@@ -311,7 +367,7 @@ namespace OpenWifi {
 | 
				
			|||||||
								SessionMutex_[i].unlock();
 | 
													SessionMutex_[i].unlock();
 | 
				
			||||||
								break;
 | 
													break;
 | 
				
			||||||
							} else if (waits < 5) {
 | 
												} else if (waits < 5) {
 | 
				
			||||||
								std::this_thread::sleep_for(std::chrono::milliseconds(10));
 | 
													Poco::Thread::trySleep(10);
 | 
				
			||||||
								waits++;
 | 
													waits++;
 | 
				
			||||||
							} else {
 | 
												} else {
 | 
				
			||||||
								break;
 | 
													break;
 | 
				
			||||||
@@ -319,10 +375,9 @@ namespace OpenWifi {
 | 
				
			|||||||
						}
 | 
											}
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
					AverageDeviceConnectionTime_ =
 | 
										AverageDeviceConnectionTime_ = NumberOfConnectedDevices_ > 0
 | 
				
			||||||
						NumberOfConnectedDevices_ > 0
 | 
																		   ? total_connected_time / NumberOfConnectedDevices_
 | 
				
			||||||
							? total_connected_time / NumberOfConnectedDevices_
 | 
																		   : 0;
 | 
				
			||||||
							: 0;
 | 
					 | 
				
			||||||
					poco_information(LocalLogger, fmt::format("Garbage collecting zombies done..."));
 | 
										poco_information(LocalLogger, fmt::format("Garbage collecting zombies done..."));
 | 
				
			||||||
				} catch (const Poco::Exception &E) {
 | 
									} catch (const Poco::Exception &E) {
 | 
				
			||||||
					poco_error(LocalLogger, fmt::format("Poco::Exception: Garbage collecting zombies failed: {}", E.displayText()));
 | 
										poco_error(LocalLogger, fmt::format("Poco::Exception: Garbage collecting zombies failed: {}", E.displayText()));
 | 
				
			||||||
@@ -332,47 +387,49 @@ namespace OpenWifi {
 | 
				
			|||||||
					poco_error(LocalLogger, fmt::format("exception:Garbage collecting zombies failed: {}", "unknown"));
 | 
										poco_error(LocalLogger, fmt::format("exception:Garbage collecting zombies failed: {}", "unknown"));
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			} else {
 | 
								}
 | 
				
			||||||
				NumberOfConnectedDevices_=0;
 | 
					
 | 
				
			||||||
				for(int i=0;i<MACHash::HashMax();i++) {
 | 
								if(NumberOfConnectedDevices_) {
 | 
				
			||||||
					std::lock_guard Lock(SerialNumbersMutex_[i]);
 | 
									if (last_garbage_run > 0) {
 | 
				
			||||||
					NumberOfConnectedDevices_ += SerialNumbers_[i].size();
 | 
										AverageDeviceConnectionTime_ += (now - last_garbage_run);
 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
				if(NumberOfConnectedDevices_) {
 | 
					 | 
				
			||||||
					if (last_garbage_run > 0) {
 | 
					 | 
				
			||||||
						AverageDeviceConnectionTime_ += (now - last_garbage_run);
 | 
					 | 
				
			||||||
					}
 | 
					 | 
				
			||||||
				} else {
 | 
					 | 
				
			||||||
					AverageDeviceConnectionTime_ = 0;
 | 
					 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if ((now - last_log) > 60) {
 | 
								try {
 | 
				
			||||||
				last_log = now;
 | 
									if ((now - last_log) > 60) {
 | 
				
			||||||
				poco_information(LocalLogger,
 | 
										last_log = now;
 | 
				
			||||||
								 fmt::format("Active AP connections: {} Connecting: {} Average connection time: {} seconds. Left Over Sessions: {}",
 | 
										poco_information(
 | 
				
			||||||
											 NumberOfConnectedDevices_, NumberOfConnectingDevices_,
 | 
											LocalLogger,
 | 
				
			||||||
											 AverageDeviceConnectionTime_, LeftOverSessions_));
 | 
											fmt::format("Active AP connections: {} Connecting: {} Average connection time: {} seconds. Left Over Sessions: {}",
 | 
				
			||||||
 | 
														NumberOfConnectedDevices_, NumberOfConnectingDevices_,
 | 
				
			||||||
 | 
														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;
 | 
				
			||||||
 | 
								} catch (const Poco::Exception &E) {
 | 
				
			||||||
 | 
									LocalLogger.error(fmt::format("Poco::Exception: Garbage collecting failed: {}", E.displayText()));
 | 
				
			||||||
 | 
								} catch (const std::exception &E) {
 | 
				
			||||||
 | 
									LocalLogger.error(fmt::format("std::exception: Garbage collecting failed: {}", E.what()));
 | 
				
			||||||
 | 
								} catch (...) {
 | 
				
			||||||
 | 
									LocalLogger.error(fmt::format("exception:Garbage collecting failed: {}", "unknown"));
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					 | 
				
			||||||
			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."	));
 | 
							LocalLogger.information(fmt::format("Garbage collector done for the day."	));
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -409,15 +466,17 @@ namespace OpenWifi {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	bool AP_WS_Server::GetStatistics(uint64_t SerialNumber, std::string &Statistics) const {
 | 
						bool AP_WS_Server::GetStatistics(uint64_t SerialNumber, std::string &Statistics) const {
 | 
				
			||||||
 | 
							std::shared_ptr<AP_WS_Connection> Connection;
 | 
				
			||||||
		auto hashIndex = MACHash::Hash(SerialNumber);
 | 
							{
 | 
				
			||||||
		std::lock_guard Lock(SerialNumbersMutex_[hashIndex]);
 | 
								auto hashIndex = MACHash::Hash(SerialNumber);
 | 
				
			||||||
		auto Device = SerialNumbers_[hashIndex].find(SerialNumber);
 | 
								std::lock_guard DeviceLock(SerialNumbersMutex_[hashIndex]);
 | 
				
			||||||
		if (Device == SerialNumbers_[hashIndex].end() || Device->second == nullptr) {
 | 
								auto DeviceHint = SerialNumbers_[hashIndex].find(SerialNumber);
 | 
				
			||||||
			return false;
 | 
								if (DeviceHint == SerialNumbers_[hashIndex].end() || DeviceHint->second == nullptr) {
 | 
				
			||||||
 | 
									return false;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								Connection = DeviceHint->second;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		Device->second->GetLastStats(Statistics);
 | 
							Connection->GetLastStats(Statistics);
 | 
				
			||||||
 | 
					 | 
				
			||||||
		return true;
 | 
							return true;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -439,49 +498,63 @@ namespace OpenWifi {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	bool AP_WS_Server::GetHealthcheck(uint64_t SerialNumber,
 | 
						bool AP_WS_Server::GetHealthcheck(uint64_t SerialNumber,
 | 
				
			||||||
									  GWObjects::HealthCheck &CheckData) const {
 | 
														  GWObjects::HealthCheck &CheckData) const {
 | 
				
			||||||
 | 
							std::shared_ptr<AP_WS_Connection> Connection;
 | 
				
			||||||
		auto hashIndex = MACHash::Hash(SerialNumber);
 | 
							{
 | 
				
			||||||
		std::lock_guard Lock(SerialNumbersMutex_[hashIndex]);
 | 
								auto hashIndex = MACHash::Hash(SerialNumber);
 | 
				
			||||||
		auto Device = SerialNumbers_[hashIndex].find(SerialNumber);
 | 
								std::lock_guard DeviceLock(SerialNumbersMutex_[hashIndex]);
 | 
				
			||||||
		if (Device == SerialNumbers_[hashIndex].end() || Device->second == nullptr) {
 | 
								auto Device = SerialNumbers_[hashIndex].find(SerialNumber);
 | 
				
			||||||
			return false;
 | 
								if (Device == SerialNumbers_[hashIndex].end() || Device->second == nullptr) {
 | 
				
			||||||
 | 
									return false;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								Connection = Device->second;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		Device->second->GetLastHealthCheck(CheckData);
 | 
							Connection->GetLastHealthCheck(CheckData);
 | 
				
			||||||
		return true;
 | 
							return true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	void AP_WS_Server::StartSession(uint64_t session_id, uint64_t SerialNumber) {
 | 
						void AP_WS_Server::StartSession(uint64_t session_id, uint64_t SerialNumber) {
 | 
				
			||||||
		auto deviceHash = MACHash::Hash(SerialNumber);
 | 
					 | 
				
			||||||
		auto sessionHash = SessionHash::Hash(session_id);
 | 
							auto sessionHash = SessionHash::Hash(session_id);
 | 
				
			||||||
		std::lock_guard SessionLock(SessionMutex_[sessionHash]);
 | 
							std::shared_ptr<AP_WS_Connection> Connection;
 | 
				
			||||||
		auto SessionHint = Sessions_[sessionHash].find(session_id);
 | 
							{
 | 
				
			||||||
		if (SessionHint != end(Sessions_[sessionHash])) {
 | 
								std::lock_guard SessionLock(SessionMutex_[sessionHash]);
 | 
				
			||||||
			std::lock_guard Lock(SerialNumbersMutex_[deviceHash]);
 | 
								auto SessionHint = Sessions_[sessionHash].find(session_id);
 | 
				
			||||||
			SerialNumbers_[deviceHash][SerialNumber] = SessionHint->second;
 | 
								if (SessionHint == end(Sessions_[sessionHash])) {
 | 
				
			||||||
 | 
									return;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								Connection = SessionHint->second;
 | 
				
			||||||
			Sessions_[sessionHash].erase(SessionHint);
 | 
								Sessions_[sessionHash].erase(SessionHint);
 | 
				
			||||||
		} else {
 | 
					 | 
				
			||||||
			poco_error(Logger(), fmt::format("StartSession: Could not find session '{}'", session_id));
 | 
					 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							auto deviceHash = MACHash::Hash(SerialNumber);
 | 
				
			||||||
 | 
							std::lock_guard DeviceLock(SerialNumbersMutex_[deviceHash]);
 | 
				
			||||||
 | 
							SerialNumbers_[deviceHash][SerialNumber] = Connection;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	bool AP_WS_Server::EndSession(uint64_t session_id, uint64_t SerialNumber) {
 | 
						bool AP_WS_Server::EndSession(uint64_t session_id, uint64_t SerialNumber) {
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
 | 
								poco_trace(Logger(), fmt::format("Ending session 1: {} for device: {}", session_id, Utils::IntToSerialNumber(SerialNumber)));
 | 
				
			||||||
			auto sessionHash = SessionHash::Hash(session_id);
 | 
								auto sessionHash = SessionHash::Hash(session_id);
 | 
				
			||||||
			std::lock_guard SessionLock(SessionMutex_[sessionHash]);
 | 
								std::lock_guard SessionLock(SessionMutex_[sessionHash]);
 | 
				
			||||||
			Sessions_[sessionHash].erase(session_id);
 | 
								Sessions_[sessionHash].erase(session_id);
 | 
				
			||||||
 | 
								poco_trace(Logger(), fmt::format("Ended session 1: {} for device: {}", session_id, Utils::IntToSerialNumber(SerialNumber)));
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			auto hashIndex = MACHash::Hash(SerialNumber);
 | 
								auto hashIndex = MACHash::Hash(SerialNumber);
 | 
				
			||||||
 | 
								poco_trace(Logger(), fmt::format("Ending session 2.0: {} for device: {} hi:{}", session_id, Utils::IntToSerialNumber(SerialNumber), hashIndex));
 | 
				
			||||||
			std::lock_guard DeviceLock(SerialNumbersMutex_[hashIndex]);
 | 
								std::lock_guard DeviceLock(SerialNumbersMutex_[hashIndex]);
 | 
				
			||||||
 | 
								poco_trace(Logger(), fmt::format("Ending session 2.1: {} for device: {} hi:{}", session_id, Utils::IntToSerialNumber(SerialNumber), hashIndex));
 | 
				
			||||||
			auto DeviceHint = SerialNumbers_[hashIndex].find(SerialNumber);
 | 
								auto DeviceHint = SerialNumbers_[hashIndex].find(SerialNumber);
 | 
				
			||||||
 | 
								poco_trace(Logger(), fmt::format("Ending session 2.2: {} for device: {} hi:{}", session_id, Utils::IntToSerialNumber(SerialNumber), hashIndex));
 | 
				
			||||||
			if (DeviceHint == SerialNumbers_[hashIndex].end()
 | 
								if (DeviceHint == SerialNumbers_[hashIndex].end()
 | 
				
			||||||
				|| DeviceHint->second == nullptr
 | 
									|| DeviceHint->second == nullptr
 | 
				
			||||||
				|| DeviceHint->second->State_.sessionId != session_id) {
 | 
									|| DeviceHint->second->State_.sessionId != session_id) {
 | 
				
			||||||
 | 
									poco_trace(Logger(), fmt::format("Did not end session 2: {} for device: {}", session_id, Utils::IntToSerialNumber(SerialNumber)));
 | 
				
			||||||
				return false;
 | 
									return false;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			SerialNumbers_[hashIndex].erase(DeviceHint);
 | 
								SerialNumbers_[hashIndex].erase(DeviceHint);
 | 
				
			||||||
 | 
								poco_trace(Logger(), fmt::format("Ended session 2: {} for device: {}", session_id, Utils::IntToSerialNumber(SerialNumber)));
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		return true;
 | 
							return true;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -489,47 +562,62 @@ namespace OpenWifi {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	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 = MACHash::Hash(SerialNumber);
 | 
							std::shared_ptr<AP_WS_Connection> Connection;
 | 
				
			||||||
		std::lock_guard DeviceLock(SerialNumbersMutex_[hashIndex]);
 | 
							{
 | 
				
			||||||
		auto DeviceHint = SerialNumbers_[hashIndex].find(SerialNumber);
 | 
								auto hashIndex = MACHash::Hash(SerialNumber);
 | 
				
			||||||
		if (DeviceHint == end(SerialNumbers_[hashIndex]) || DeviceHint->second == nullptr) {
 | 
								std::lock_guard DeviceLock(SerialNumbersMutex_[hashIndex]);
 | 
				
			||||||
 | 
								auto DeviceHint = SerialNumbers_[hashIndex].find(SerialNumber);
 | 
				
			||||||
 | 
								if (DeviceHint == end(SerialNumbers_[hashIndex]) || DeviceHint->second == nullptr) {
 | 
				
			||||||
 | 
									return false;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								Connection = DeviceHint->second;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if(Connection->Dead_) {
 | 
				
			||||||
			return false;
 | 
								return false;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		if(!DeviceHint->second->Dead_) {
 | 
							Restrictions = Connection->GetRestrictions();
 | 
				
			||||||
			DeviceHint->second->GetRestrictions(Restrictions);
 | 
							return Connection->State_.Connected;
 | 
				
			||||||
			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 = MACHash::Hash(SerialNumber);
 | 
							std::shared_ptr<AP_WS_Connection> Connection;
 | 
				
			||||||
		std::lock_guard Lock(SerialNumbersMutex_[hashIndex]);
 | 
							{
 | 
				
			||||||
		auto DeviceHint = SerialNumbers_[hashIndex].find(SerialNumber);
 | 
								auto hashIndex = MACHash::Hash(SerialNumber);
 | 
				
			||||||
		if (DeviceHint == end(SerialNumbers_[hashIndex]) || DeviceHint->second == nullptr) {
 | 
								std::lock_guard DeviceLock(SerialNumbersMutex_[hashIndex]);
 | 
				
			||||||
 | 
								auto DeviceHint = SerialNumbers_[hashIndex].find(SerialNumber);
 | 
				
			||||||
 | 
								if (DeviceHint == end(SerialNumbers_[hashIndex]) || DeviceHint->second == nullptr) {
 | 
				
			||||||
 | 
									return false;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								Connection = DeviceHint->second;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if(Connection->Dead_) {
 | 
				
			||||||
			return false;
 | 
								return false;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		if(!DeviceHint->second->Dead_) {
 | 
							return Connection->State_.Connected;
 | 
				
			||||||
			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 = MACHash::Hash(SerialNumber);
 | 
							auto hashIndex = MACHash::Hash(SerialNumber);
 | 
				
			||||||
		std::lock_guard Lock(SerialNumbersMutex_[hashIndex]);
 | 
					
 | 
				
			||||||
		auto DeviceHint = SerialNumbers_[hashIndex].find(SerialNumber);
 | 
							std::shared_ptr<AP_WS_Connection> Connection;
 | 
				
			||||||
		if (DeviceHint == end(SerialNumbers_[hashIndex]) || DeviceHint->second == nullptr) {
 | 
							{
 | 
				
			||||||
			return false;
 | 
								std::lock_guard DeviceLock(SerialNumbersMutex_[hashIndex]);
 | 
				
			||||||
 | 
								auto DeviceHint = SerialNumbers_[hashIndex].find(SerialNumber);
 | 
				
			||||||
 | 
								if (DeviceHint == end(SerialNumbers_[hashIndex]) || DeviceHint->second == nullptr) {
 | 
				
			||||||
 | 
									return false;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								Connection = DeviceHint->second;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if(DeviceHint->second->Dead_) {
 | 
							if(Connection->Dead_) {
 | 
				
			||||||
			return false;
 | 
								return false;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		try {
 | 
							try {
 | 
				
			||||||
			return DeviceHint->second->Send(Payload);
 | 
								return Connection->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)));
 | 
				
			||||||
@@ -538,48 +626,64 @@ 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 = MACHash::Hash(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 == end(SerialNumbers_[hashIndex]) || Device->second == nullptr) {
 | 
								std::lock_guard DeviceLock(SerialNumbersMutex_[hashIndex]);
 | 
				
			||||||
			return;
 | 
								auto Device = SerialNumbers_[hashIndex].find(SerialNumber);
 | 
				
			||||||
 | 
								if (Device == end(SerialNumbers_[hashIndex]) || Device->second == nullptr) {
 | 
				
			||||||
 | 
									return;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								Connection = Device->second;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		Device->second->StopWebSocketTelemetry(RPCID);
 | 
							Connection->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 = MACHash::Hash(SerialNumber);
 | 
							std::shared_ptr<AP_WS_Connection> Connection;
 | 
				
			||||||
		std::lock_guard DeviceLock(SerialNumbersMutex_[hashIndex]);
 | 
							{
 | 
				
			||||||
		auto DeviceHint = SerialNumbers_[hashIndex].find(SerialNumber);
 | 
								auto hashIndex = MACHash::Hash(SerialNumber);
 | 
				
			||||||
		if (DeviceHint == end(SerialNumbers_[hashIndex]) || DeviceHint->second == nullptr) {
 | 
								std::lock_guard DeviceLock(SerialNumbersMutex_[hashIndex]);
 | 
				
			||||||
			return;
 | 
								auto DeviceHint = SerialNumbers_[hashIndex].find(SerialNumber);
 | 
				
			||||||
 | 
								if (DeviceHint == end(SerialNumbers_[hashIndex]) || DeviceHint->second == nullptr) {
 | 
				
			||||||
 | 
									return;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								Connection = DeviceHint->second;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		DeviceHint->second->SetWebSocketTelemetryReporting(RPCID, Interval, Lifetime, TelemetryTypes);
 | 
							Connection->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 = MACHash::Hash(SerialNumber);
 | 
							std::shared_ptr<AP_WS_Connection> Connection;
 | 
				
			||||||
		std::lock_guard Lock(SerialNumbersMutex_[hashIndex]);
 | 
							{
 | 
				
			||||||
		auto DeviceHint = SerialNumbers_[hashIndex].find(SerialNumber);
 | 
								auto hashIndex = MACHash::Hash(SerialNumber);
 | 
				
			||||||
		if (DeviceHint == end(SerialNumbers_[hashIndex]) || DeviceHint->second == nullptr) {
 | 
								std::lock_guard DeviceLock(SerialNumbersMutex_[hashIndex]);
 | 
				
			||||||
			return;
 | 
								auto DeviceHint = SerialNumbers_[hashIndex].find(SerialNumber);
 | 
				
			||||||
 | 
								if (DeviceHint == end(SerialNumbers_[hashIndex]) || DeviceHint->second == nullptr) {
 | 
				
			||||||
 | 
									return;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								Connection = DeviceHint->second;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		DeviceHint->second->SetKafkaTelemetryReporting(RPCID, Interval, Lifetime, TelemetryTypes);
 | 
							Connection->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 = MACHash::Hash(SerialNumber);
 | 
							std::shared_ptr<AP_WS_Connection> Connection;
 | 
				
			||||||
		std::lock_guard DevicesLock(SerialNumbersMutex_[hashIndex]);
 | 
							{
 | 
				
			||||||
		auto DeviceHint = SerialNumbers_[hashIndex].find(SerialNumber);
 | 
								auto hashIndex = MACHash::Hash(SerialNumber);
 | 
				
			||||||
		if (DeviceHint == end(SerialNumbers_[hashIndex]) || DeviceHint->second == nullptr) {
 | 
								std::lock_guard DevicesLock(SerialNumbersMutex_[hashIndex]);
 | 
				
			||||||
			return;
 | 
								auto DeviceHint = SerialNumbers_[hashIndex].find(SerialNumber);
 | 
				
			||||||
 | 
								if (DeviceHint == end(SerialNumbers_[hashIndex]) || DeviceHint->second == nullptr) {
 | 
				
			||||||
 | 
									return;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								Connection = DeviceHint->second;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		DeviceHint->second->StopKafkaTelemetry(RPCID);
 | 
							Connection->StopKafkaTelemetry(RPCID);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	void AP_WS_Server::GetTelemetryParameters(
 | 
						void AP_WS_Server::GetTelemetryParameters(
 | 
				
			||||||
@@ -588,14 +692,18 @@ 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 = MACHash::Hash(SerialNumber);
 | 
							std::shared_ptr<AP_WS_Connection> Connection;
 | 
				
			||||||
		std::lock_guard DevicesLock(SerialNumbersMutex_[hashIndex]);
 | 
							{
 | 
				
			||||||
		auto DeviceHint = SerialNumbers_[hashIndex].find(SerialNumber);
 | 
								auto hashIndex = MACHash::Hash(SerialNumber);
 | 
				
			||||||
		if (DeviceHint == end(SerialNumbers_[hashIndex]) || DeviceHint->second == nullptr) {
 | 
								std::lock_guard DevicesLock(SerialNumbersMutex_[hashIndex]);
 | 
				
			||||||
			return;
 | 
								auto DeviceHint = SerialNumbers_[hashIndex].find(SerialNumber);
 | 
				
			||||||
 | 
								if (DeviceHint == end(SerialNumbers_[hashIndex]) || DeviceHint->second == nullptr) {
 | 
				
			||||||
 | 
									return;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								Connection = DeviceHint->second;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		DeviceHint->second->GetTelemetryParameters(TelemetryRunning, TelemetryInterval,
 | 
							Connection->GetTelemetryParameters(TelemetryRunning, TelemetryInterval,
 | 
				
			||||||
										  TelemetryWebSocketTimer, TelemetryKafkaTimer,
 | 
															  TelemetryWebSocketTimer, TelemetryKafkaTimer,
 | 
				
			||||||
										  TelemetryWebSocketCount, TelemetryKafkaCount,
 | 
															  TelemetryWebSocketCount, TelemetryKafkaCount,
 | 
				
			||||||
										  TelemetryWebSocketPackets, TelemetryKafkaPackets);
 | 
															  TelemetryWebSocketPackets, TelemetryKafkaPackets);
 | 
				
			||||||
@@ -604,20 +712,24 @@ namespace OpenWifi {
 | 
				
			|||||||
	bool AP_WS_Server::SendRadiusAccountingData(const std::string &SerialNumber,
 | 
						bool AP_WS_Server::SendRadiusAccountingData(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);
 | 
							std::shared_ptr<AP_WS_Connection> Connection;
 | 
				
			||||||
		auto hashIndex = MACHash::Hash(IntSerialNumber);
 | 
							{
 | 
				
			||||||
		std::lock_guard DevicesLock(SerialNumbersMutex_[hashIndex]);
 | 
								auto IntSerialNumber = Utils::SerialNumberToInt(SerialNumber);
 | 
				
			||||||
		auto DeviceHint = SerialNumbers_[hashIndex].find(IntSerialNumber);
 | 
								auto hashIndex = MACHash::Hash(IntSerialNumber);
 | 
				
			||||||
		if (DeviceHint == end(SerialNumbers_[hashIndex]) || DeviceHint->second == nullptr) {
 | 
								std::lock_guard DevicesLock(SerialNumbersMutex_[hashIndex]);
 | 
				
			||||||
			return false;
 | 
								auto DeviceHint = SerialNumbers_[hashIndex].find(IntSerialNumber);
 | 
				
			||||||
 | 
								if (DeviceHint == end(SerialNumbers_[hashIndex]) || DeviceHint->second == nullptr) {
 | 
				
			||||||
 | 
									return false;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								Connection = DeviceHint->second;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if(DeviceHint->second->Dead_) {
 | 
							if(Connection->Dead_) {
 | 
				
			||||||
			return false;
 | 
								return false;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		try {
 | 
							try {
 | 
				
			||||||
			return DeviceHint->second->SendRadiusAccountingData(buffer, size);
 | 
								return Connection->SendRadiusAccountingData(buffer, size);
 | 
				
			||||||
		} catch (...) {
 | 
							} catch (...) {
 | 
				
			||||||
			poco_debug(
 | 
								poco_debug(
 | 
				
			||||||
				Logger(),
 | 
									Logger(),
 | 
				
			||||||
@@ -629,20 +741,24 @@ 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);
 | 
							std::shared_ptr<AP_WS_Connection> Connection;
 | 
				
			||||||
		auto hashIndex = MACHash::Hash(IntSerialNumber);
 | 
							{
 | 
				
			||||||
		std::lock_guard DevicesLock(SerialNumbersMutex_[hashIndex]);
 | 
								auto IntSerialNumber = Utils::SerialNumberToInt(SerialNumber);
 | 
				
			||||||
		auto DeviceHint = SerialNumbers_[hashIndex].find(IntSerialNumber);
 | 
								auto hashIndex = MACHash::Hash(IntSerialNumber);
 | 
				
			||||||
		if (DeviceHint == end(SerialNumbers_[hashIndex]) || DeviceHint->second == nullptr) {
 | 
								std::lock_guard DevicesLock(SerialNumbersMutex_[hashIndex]);
 | 
				
			||||||
			return false;
 | 
								auto DeviceHint = SerialNumbers_[hashIndex].find(IntSerialNumber);
 | 
				
			||||||
 | 
								if (DeviceHint == end(SerialNumbers_[hashIndex]) || DeviceHint->second == nullptr) {
 | 
				
			||||||
 | 
									return false;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								Connection = DeviceHint->second;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if(DeviceHint->second->Dead_) {
 | 
							if(Connection->Dead_) {
 | 
				
			||||||
			return false;
 | 
								return false;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		try {
 | 
							try {
 | 
				
			||||||
			return DeviceHint->second->SendRadiusAuthenticationData(buffer, size);
 | 
								return Connection->SendRadiusAuthenticationData(buffer, size);
 | 
				
			||||||
		} catch (...) {
 | 
							} catch (...) {
 | 
				
			||||||
			poco_debug(
 | 
								poco_debug(
 | 
				
			||||||
				Logger(),
 | 
									Logger(),
 | 
				
			||||||
@@ -654,19 +770,23 @@ 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);
 | 
							std::shared_ptr<AP_WS_Connection> Connection;
 | 
				
			||||||
		auto hashIndex = MACHash::Hash(IntSerialNumber);
 | 
							{
 | 
				
			||||||
		std::lock_guard DevicesGuard(SerialNumbersMutex_[hashIndex]);
 | 
								auto IntSerialNumber = Utils::SerialNumberToInt(SerialNumber);
 | 
				
			||||||
		auto DeviceHint = SerialNumbers_[hashIndex].find(IntSerialNumber);
 | 
								auto hashIndex = MACHash::Hash(IntSerialNumber);
 | 
				
			||||||
		if (DeviceHint == end(SerialNumbers_[hashIndex]) || DeviceHint->second == nullptr) {
 | 
								std::lock_guard DeviceLock(SerialNumbersMutex_[hashIndex]);
 | 
				
			||||||
			return false;
 | 
								auto DeviceHint = SerialNumbers_[hashIndex].find(IntSerialNumber);
 | 
				
			||||||
 | 
								if (DeviceHint == end(SerialNumbers_[hashIndex]) || DeviceHint->second == nullptr) {
 | 
				
			||||||
 | 
									return false;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								Connection = DeviceHint->second;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if(DeviceHint->second->Dead_) {
 | 
							if(Connection->Dead_) {
 | 
				
			||||||
			return false;
 | 
								return false;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		try {
 | 
							try {
 | 
				
			||||||
			return DeviceHint->second->SendRadiusCoAData(buffer, size);
 | 
								return Connection->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 '{}'",
 | 
				
			||||||
@@ -675,32 +795,4 @@ namespace OpenWifi {
 | 
				
			|||||||
		return false;
 | 
							return false;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	bool AP_WS_Server::ExtendedAttributes(const std::string &serialNumber,
 | 
					} // namespace OpenWifi
 | 
				
			||||||
								   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
 | 
					 | 
				
			||||||
 
 | 
				
			|||||||
@@ -103,20 +103,23 @@ namespace OpenWifi {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
		inline void AddConnection(std::shared_ptr<AP_WS_Connection> Connection) {
 | 
							inline void AddConnection(std::shared_ptr<AP_WS_Connection> Connection) {
 | 
				
			||||||
			std::uint64_t sessionHash = SessionHash::Hash(Connection->State_.sessionId);
 | 
								std::uint64_t sessionHash = SessionHash::Hash(Connection->State_.sessionId);
 | 
				
			||||||
			std::lock_guard Lock(SessionMutex_[sessionHash]);
 | 
								std::lock_guard SessionLock(SessionMutex_[sessionHash]);
 | 
				
			||||||
			if(Sessions_[sessionHash].find(Connection->State_.sessionId)==end(Sessions_[sessionHash])) {
 | 
								if(Sessions_[sessionHash].find(Connection->State_.sessionId)==end(Sessions_[sessionHash])) {
 | 
				
			||||||
				Sessions_[sessionHash][Connection->State_.sessionId] = std::move(Connection);
 | 
									Sessions_[sessionHash][Connection->State_.sessionId] = std::move(Connection);
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		[[nodiscard]] inline bool DeviceRequiresSecureRTTY(uint64_t serialNumber) const {
 | 
							[[nodiscard]] inline bool DeviceRequiresSecureRTTY(uint64_t serialNumber) const {
 | 
				
			||||||
			auto hashIndex = MACHash::Hash(serialNumber);
 | 
								std::shared_ptr<AP_WS_Connection> Connection;
 | 
				
			||||||
			std::lock_guard	G(SerialNumbersMutex_[hashIndex]);
 | 
								{
 | 
				
			||||||
 | 
									auto hashIndex = MACHash::Hash(serialNumber);
 | 
				
			||||||
			auto Connection = SerialNumbers_[hashIndex].find(serialNumber);
 | 
									std::lock_guard DeviceLock(SerialNumbersMutex_[hashIndex]);
 | 
				
			||||||
			if (Connection==end(SerialNumbers_[hashIndex]) || Connection->second==nullptr)
 | 
									auto DeviceHint = SerialNumbers_[hashIndex].find(serialNumber);
 | 
				
			||||||
				return false;
 | 
									if (DeviceHint == end(SerialNumbers_[hashIndex]) || DeviceHint->second == nullptr)
 | 
				
			||||||
			return Connection->second->RTTYMustBeSecure_;
 | 
										return false;
 | 
				
			||||||
 | 
									Connection = DeviceHint->second;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								return Connection->RTTYMustBeSecure_;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		inline bool GetStatistics(const std::string &SerialNumber, std::string &Statistics) const {
 | 
							inline bool GetStatistics(const std::string &SerialNumber, std::string &Statistics) const {
 | 
				
			||||||
@@ -138,6 +141,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;
 | 
				
			||||||
 | 
							bool Disconnect(uint64_t SerialNumber);
 | 
				
			||||||
		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);
 | 
				
			||||||
@@ -165,8 +169,8 @@ namespace OpenWifi {
 | 
				
			|||||||
									uint64_t &TelemetryKafkaPackets);
 | 
														uint64_t &TelemetryKafkaPackets);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		bool GetHealthDevices(std::uint64_t lowLimit, std::uint64_t  highLimit, std::vector<std::string> & SerialNumbers);
 | 
							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,
 | 
					//		bool ExtendedAttributes(const std::string &serialNumber, bool & hasGPS, std::uint64_t &Sanity,
 | 
				
			||||||
								std::double_t &MemoryUsed, std::double_t &Load, std::double_t &Temperature);
 | 
					//								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 {
 | 
				
			||||||
@@ -195,15 +199,31 @@ namespace OpenWifi {
 | 
				
			|||||||
		bool KafkaDisableState() const { return KafkaDisableState_; }
 | 
							bool KafkaDisableState() const { return KafkaDisableState_; }
 | 
				
			||||||
		bool KafkaDisableHealthChecks() const { return KafkaDisableHealthChecks_; }
 | 
							bool KafkaDisableHealthChecks() const { return KafkaDisableHealthChecks_; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							inline void IncrementConnectionCount() {
 | 
				
			||||||
 | 
								++NumberOfConnectedDevices_;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							inline void DecrementConnectionCount() {
 | 
				
			||||||
 | 
								--NumberOfConnectedDevices_;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							inline void AddCleanupSession(uint64_t session_id, uint64_t SerialNumber) {
 | 
				
			||||||
 | 
								std::lock_guard G(CleanupMutex_);
 | 
				
			||||||
 | 
								CleanupSessions_.emplace_back(session_id, SerialNumber);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							void CleanupSessions();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	  private:
 | 
						  private:
 | 
				
			||||||
		std::array<std::mutex,SessionHashMax> 			SessionMutex_;
 | 
							std::array<std::mutex,SessionHashMax> 			SessionMutex_;
 | 
				
			||||||
		std::array<std::map<std::uint64_t, std::shared_ptr<AP_WS_Connection>>,SessionHashMax> Sessions_;
 | 
							std::array<std::map<std::uint64_t, std::shared_ptr<AP_WS_Connection>>,SessionHashMax> Sessions_;
 | 
				
			||||||
		using SerialNumberMap = std::map<uint64_t /* serial number */,
 | 
							using SerialNumberMap = std::map<uint64_t /* serial number */,
 | 
				
			||||||
										 std::shared_ptr<AP_WS_Connection>>;
 | 
															 std::shared_ptr<AP_WS_Connection>>;
 | 
				
			||||||
		std::array<SerialNumberMap,MACHashMax>			SerialNumbers_;
 | 
							std::array<SerialNumberMap,MACHashMax>			SerialNumbers_;
 | 
				
			||||||
		mutable std::array<std::recursive_mutex,MACHashMax>		SerialNumbersMutex_;
 | 
							mutable std::array<std::mutex,MACHashMax>		SerialNumbersMutex_;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		std::unique_ptr<Poco::Crypto::X509Certificate> IssuerCert_;
 | 
							std::unique_ptr<Poco::Crypto::X509Certificate> IssuerCert_;
 | 
				
			||||||
 | 
							std::vector<Poco::Crypto::X509Certificate> ClientCasCerts_;
 | 
				
			||||||
		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::ThreadPool DeviceConnectionPool_{"ws:dev-pool", 4, 256};
 | 
				
			||||||
		Poco::Net::SocketReactor Reactor_;
 | 
							Poco::Net::SocketReactor Reactor_;
 | 
				
			||||||
@@ -214,12 +234,17 @@ namespace OpenWifi {
 | 
				
			|||||||
		bool SimulatorEnabled_ = false;
 | 
							bool SimulatorEnabled_ = false;
 | 
				
			||||||
		bool AllowSerialNumberMismatch_ = true;
 | 
							bool AllowSerialNumberMismatch_ = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							Poco::Thread            CleanupThread_;
 | 
				
			||||||
 | 
							std::mutex              CleanupMutex_;
 | 
				
			||||||
 | 
							std::deque<std::pair<uint64_t, uint64_t>> CleanupSessions_;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		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::uint64_t 			MismatchDepth_ = 2;
 | 
							std::uint64_t 			MismatchDepth_ = 2;
 | 
				
			||||||
		std::uint64_t 			NumberOfConnectedDevices_ = 0;
 | 
					
 | 
				
			||||||
		std::uint64_t 			AverageDeviceConnectionTime_ = 0;
 | 
							std::atomic_uint64_t 	NumberOfConnectedDevices_ = 0;
 | 
				
			||||||
 | 
							std::atomic_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::uint64_t 			LeftOverSessions_ = 0;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -10,6 +10,7 @@
 | 
				
			|||||||
#include <string>
 | 
					#include <string>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "framework/MicroServiceFuncs.h"
 | 
					#include "framework/MicroServiceFuncs.h"
 | 
				
			||||||
 | 
					#include "framework/ow_constants.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "CentralConfig.h"
 | 
					#include "CentralConfig.h"
 | 
				
			||||||
#include "nlohmann/json.hpp"
 | 
					#include "nlohmann/json.hpp"
 | 
				
			||||||
@@ -34,7 +35,7 @@ namespace OpenWifi {
 | 
				
			|||||||
			std::lock_guard G(Mutex_);
 | 
								std::lock_guard G(Mutex_);
 | 
				
			||||||
			if (!PlatformsLoaded_)
 | 
								if (!PlatformsLoaded_)
 | 
				
			||||||
				LoadPlatforms();
 | 
									LoadPlatforms();
 | 
				
			||||||
			auto P = Poco::toUpper(Caps.Platform());
 | 
								auto P = Poco::toLower(Caps.Platform());
 | 
				
			||||||
			auto Hint = Platforms_.find(Caps.Compatible());
 | 
								auto Hint = Platforms_.find(Caps.Compatible());
 | 
				
			||||||
			if (Hint == Platforms_.end()) {
 | 
								if (Hint == Platforms_.end()) {
 | 
				
			||||||
				Platforms_.insert(std::make_pair(Caps.Compatible(), P));
 | 
									Platforms_.insert(std::make_pair(Caps.Compatible(), P));
 | 
				
			||||||
@@ -68,7 +69,7 @@ namespace OpenWifi {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
			auto Hint = Platforms_.find(DeviceType);
 | 
								auto Hint = Platforms_.find(DeviceType);
 | 
				
			||||||
			if (Hint == Platforms_.end())
 | 
								if (Hint == Platforms_.end())
 | 
				
			||||||
				return "AP";
 | 
									return Platforms::AP;
 | 
				
			||||||
			return Hint->second;
 | 
								return Hint->second;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -110,7 +111,7 @@ namespace OpenWifi {
 | 
				
			|||||||
				i >> cache;
 | 
									i >> cache;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				for (const auto &[Type, Platform] : cache.items()) {
 | 
									for (const auto &[Type, Platform] : cache.items()) {
 | 
				
			||||||
					Platforms_[Type] = Platform;
 | 
										Platforms_[Type] = Poco::toLower(Platform.get<std::string>());
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			} catch (...) {
 | 
								} catch (...) {
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -204,6 +204,17 @@ namespace OpenWifi::Config {
 | 
				
			|||||||
		return false;
 | 
							return false;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						std::uint64_t Config::UUID() {
 | 
				
			||||||
 | 
							try {
 | 
				
			||||||
 | 
								Poco::JSON::Parser Parser;
 | 
				
			||||||
 | 
								auto object = Parser.parse(Config_).extract<Poco::JSON::Object::Ptr>();
 | 
				
			||||||
 | 
								if (object->has("uuid"))
 | 
				
			||||||
 | 
									return object->get("uuid");
 | 
				
			||||||
 | 
							} catch (...) {
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	bool Config::Valid() {
 | 
						bool Config::Valid() {
 | 
				
			||||||
		try {
 | 
							try {
 | 
				
			||||||
			Poco::JSON::Parser Parser;
 | 
								Poco::JSON::Parser Parser;
 | 
				
			||||||
@@ -254,7 +265,11 @@ namespace OpenWifi::Config {
 | 
				
			|||||||
				Model_ = Caps->get("model").toString();
 | 
									Model_ = Caps->get("model").toString();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if (Caps->has("platform"))
 | 
								if (Caps->has("platform"))
 | 
				
			||||||
				Platform_ = Caps->get("platform").toString();
 | 
									Platform_ = Poco::toLower(Caps->get("platform").toString());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if(Compatible_.empty()) {
 | 
				
			||||||
 | 
									Compatible_ = Model_;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			std::ostringstream OS;
 | 
								std::ostringstream OS;
 | 
				
			||||||
			Caps->stringify(OS);
 | 
								Caps->stringify(OS);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -23,6 +23,7 @@ namespace OpenWifi::Config {
 | 
				
			|||||||
		[[nodiscard]] std::string get() { return Config_; };
 | 
							[[nodiscard]] std::string get() { return Config_; };
 | 
				
			||||||
		[[nodiscard]] std::string Default();
 | 
							[[nodiscard]] std::string Default();
 | 
				
			||||||
		[[nodiscard]] Poco::JSON::Object::Ptr to_json();
 | 
							[[nodiscard]] Poco::JSON::Object::Ptr to_json();
 | 
				
			||||||
 | 
							[[nodiscard]] std::uint64_t UUID();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	  private:
 | 
						  private:
 | 
				
			||||||
		void Init();
 | 
							void Init();
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -11,12 +11,12 @@
 | 
				
			|||||||
namespace OpenWifi {
 | 
					namespace OpenWifi {
 | 
				
			||||||
	class ConfigurationCache {
 | 
						class ConfigurationCache {
 | 
				
			||||||
	  public:
 | 
						  public:
 | 
				
			||||||
		static ConfigurationCache &instance() {
 | 
							static auto instance() {
 | 
				
			||||||
			static ConfigurationCache instance;
 | 
								static auto instance = new ConfigurationCache;
 | 
				
			||||||
			return instance;
 | 
								return instance;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		inline uint64_t CurrentConfig(uint64_t SerialNumber) {
 | 
							inline uint64_t GetCurrentConfig(std::uint64_t SerialNumber) {
 | 
				
			||||||
			std::lock_guard G(Mutex_);
 | 
								std::lock_guard G(Mutex_);
 | 
				
			||||||
			const auto Hint = Cache_.find(SerialNumber);
 | 
								const auto Hint = Cache_.find(SerialNumber);
 | 
				
			||||||
			if (Hint == end(Cache_))
 | 
								if (Hint == end(Cache_))
 | 
				
			||||||
@@ -24,25 +24,25 @@ namespace OpenWifi {
 | 
				
			|||||||
			return Hint->second;
 | 
								return Hint->second;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		inline void Add(uint64_t SerialNumber, uint64_t Id) {
 | 
							inline void SetCurrentConfig(std::uint64_t SerialNumber, uint64_t Id) {
 | 
				
			||||||
			std::lock_guard G(Mutex_);
 | 
								std::lock_guard G(Mutex_);
 | 
				
			||||||
			Cache_[SerialNumber] = Id;
 | 
								Cache_[SerialNumber] = Id;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	  private:
 | 
						  private:
 | 
				
			||||||
		std::recursive_mutex Mutex_;
 | 
							std::mutex Mutex_;
 | 
				
			||||||
		std::map<uint64_t, uint64_t> Cache_;
 | 
							std::map<uint64_t, uint64_t> Cache_;
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	inline uint64_t GetCurrentConfigurationID(uint64_t SerialNumber) {
 | 
						inline auto GetCurrentConfigurationID(std::uint64_t SerialNumber) {
 | 
				
			||||||
		return ConfigurationCache::instance().CurrentConfig(SerialNumber);
 | 
							return ConfigurationCache::instance()->GetCurrentConfig(SerialNumber);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	inline void SetCurrentConfigurationID(const std::string &SerialNumber, uint64_t ID) {
 | 
						inline void SetCurrentConfigurationID(const std::string &SerialNumber, std::uint64_t ID) {
 | 
				
			||||||
		return ConfigurationCache::instance().Add(Utils::SerialNumberToInt(SerialNumber), ID);
 | 
							return ConfigurationCache::instance()->SetCurrentConfig(Utils::SerialNumberToInt(SerialNumber), ID);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	inline void SetCurrentConfigurationID(uint64_t SerialNumber, uint64_t ID) {
 | 
						inline void SetCurrentConfigurationID(uint64_t SerialNumber, std::uint64_t ID) {
 | 
				
			||||||
		return ConfigurationCache::instance().Add(SerialNumber, ID);
 | 
							return ConfigurationCache::instance()->SetCurrentConfig(SerialNumber, ID);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
} // namespace OpenWifi
 | 
					} // namespace OpenWifi
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -49,7 +49,7 @@ namespace OpenWifi {
 | 
				
			|||||||
				SignatureManager(), AP_WS_Server(),
 | 
									SignatureManager(), AP_WS_Server(),
 | 
				
			||||||
				RegulatoryInfo(),
 | 
									RegulatoryInfo(),
 | 
				
			||||||
				RADIUSSessionTracker(),
 | 
									RADIUSSessionTracker(),
 | 
				
			||||||
				AP_WS_ConfigAutoUpgrader(),
 | 
								 	AP_WS_ConfigAutoUpgradeAgent(),
 | 
				
			||||||
				FirmwareRevisionCache()
 | 
									FirmwareRevisionCache()
 | 
				
			||||||
			});
 | 
								});
 | 
				
			||||||
		return &instance;
 | 
							return &instance;
 | 
				
			||||||
@@ -78,7 +78,7 @@ namespace OpenWifi {
 | 
				
			|||||||
			if (Id == DeviceType)
 | 
								if (Id == DeviceType)
 | 
				
			||||||
				return Type;
 | 
									return Type;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		return "AP";
 | 
							return Platforms::AP;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	void DaemonPostInitialization(Poco::Util::Application &self) {
 | 
						void DaemonPostInitialization(Poco::Util::Application &self) {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -8,12 +8,12 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#pragma once
 | 
					#pragma once
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "Poco/Net/HTTPRequestHandler.h"
 | 
					#include <Poco/Net/HTTPRequestHandler.h>
 | 
				
			||||||
#include "Poco/Net/HTTPRequestHandlerFactory.h"
 | 
					#include <Poco/Net/HTTPRequestHandlerFactory.h>
 | 
				
			||||||
#include "Poco/Net/HTTPServer.h"
 | 
					#include <Poco/Net/HTTPServer.h>
 | 
				
			||||||
#include "Poco/Net/HTTPServerRequest.h"
 | 
					#include <Poco/Net/HTTPServerRequest.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "framework/SubSystemServer.h"
 | 
					#include <framework/SubSystemServer.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace OpenWifi {
 | 
					namespace OpenWifi {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -50,12 +50,22 @@ namespace OpenWifi {
 | 
				
			|||||||
	class DeviceConfigurationChangeKafkaEvent : public GWKafkaEvents {
 | 
						class DeviceConfigurationChangeKafkaEvent : public GWKafkaEvents {
 | 
				
			||||||
	  public:
 | 
						  public:
 | 
				
			||||||
		DeviceConfigurationChangeKafkaEvent(std::uint64_t serialNumber,
 | 
							DeviceConfigurationChangeKafkaEvent(std::uint64_t serialNumber,
 | 
				
			||||||
											std::uint64_t timestamp, const Poco::JSON::Object::Ptr config)
 | 
																std::uint64_t timestamp,
 | 
				
			||||||
 | 
																const Poco::JSON::Object::Ptr config)
 | 
				
			||||||
			: GWKafkaEvents(serialNumber, "unit.configuration_change", timestamp), config_(config) {
 | 
								: GWKafkaEvents(serialNumber, "unit.configuration_change", timestamp), config_(config) {
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		~DeviceConfigurationChangeKafkaEvent() {
 | 
							~DeviceConfigurationChangeKafkaEvent() {
 | 
				
			||||||
			payload_->set("configuration", *config_);
 | 
								if(config_!= nullptr) {
 | 
				
			||||||
 | 
									std::ostringstream os;
 | 
				
			||||||
 | 
									config_->stringify(os);
 | 
				
			||||||
 | 
									if(os.str().size()> KafkaManager()->KafkaManagerMaximumPayloadSize()) {
 | 
				
			||||||
 | 
										payload_->set("configuration", "{}");
 | 
				
			||||||
 | 
										payload_->set("configurationTooBig", true);
 | 
				
			||||||
 | 
									} else {
 | 
				
			||||||
 | 
										payload_->set("configuration", *config_);
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
			Send();
 | 
								Send();
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -75,8 +75,10 @@ namespace OpenWifi {
 | 
				
			|||||||
				} else if ((Utils::Now() - LastKeepAlive) > Pool_.radsecKeepAlive) {
 | 
									} else if ((Utils::Now() - LastKeepAlive) > Pool_.radsecKeepAlive) {
 | 
				
			||||||
					RADIUS::RadiusOutputPacket P(Pool_.authConfig.servers[ServerIndex_].radsecSecret);
 | 
										RADIUS::RadiusOutputPacket P(Pool_.authConfig.servers[ServerIndex_].radsecSecret);
 | 
				
			||||||
					P.MakeStatusMessage(Pool_.authConfig.servers[ServerIndex_].name);
 | 
										P.MakeStatusMessage(Pool_.authConfig.servers[ServerIndex_].name);
 | 
				
			||||||
					poco_trace(Logger_, fmt::format("{}: Keep-Alive message.", Pool_.authConfig.servers[ServerIndex_].name));
 | 
										if(Type_!=GWObjects::RadiusEndpointType::generic) {
 | 
				
			||||||
					Socket_->sendBytes(P.Data(), P.Len());
 | 
											poco_trace(Logger_, fmt::format("{}: Keep-Alive message.", Pool_.authConfig.servers[ServerIndex_].name));
 | 
				
			||||||
 | 
											Socket_->sendBytes(P.Data(), P.Len());
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
					LastKeepAlive = Utils::Now();
 | 
										LastKeepAlive = Utils::Now();
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
				Poco::Thread::trySleep(2000);
 | 
									Poco::Thread::trySleep(2000);
 | 
				
			||||||
@@ -163,17 +165,16 @@ namespace OpenWifi {
 | 
				
			|||||||
									 fmt::format("Unknown packet: Type: {} (type={}) Length={}",
 | 
														 fmt::format("Unknown packet: Type: {} (type={}) Length={}",
 | 
				
			||||||
												 P.PacketType(), P.PacketTypeInt(), P.BufferLen()));
 | 
																	 P.PacketType(), P.PacketTypeInt(), P.BufferLen()));
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
 | 
										return;
 | 
				
			||||||
				} else {
 | 
									} else {
 | 
				
			||||||
					poco_warning(Logger_, "Invalid packet received. Resetting the connection.");
 | 
										poco_warning(Logger_, "Invalid packet received. Resetting the connection.");
 | 
				
			||||||
					Disconnect();
 | 
					 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			} catch (const Poco::Exception &E) {
 | 
								} catch (const Poco::Exception &E) {
 | 
				
			||||||
				Logger_.log(E);
 | 
									Logger_.log(E);
 | 
				
			||||||
				Disconnect();
 | 
					 | 
				
			||||||
			} catch (...) {
 | 
								} catch (...) {
 | 
				
			||||||
				Disconnect();
 | 
					 | 
				
			||||||
				poco_warning(Logger_, "Exception occurred. Resetting the connection.");
 | 
									poco_warning(Logger_, "Exception occurred. Resetting the connection.");
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
								Disconnect();
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		inline void
 | 
							inline void
 | 
				
			||||||
@@ -324,7 +325,7 @@ namespace OpenWifi {
 | 
				
			|||||||
				ofs << OpenRoamingRootCert;
 | 
									ofs << OpenRoamingRootCert;
 | 
				
			||||||
				ofs.close();
 | 
									ofs.close();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				Poco::Net::Context::Ptr SecureContext = Poco::AutoPtr<Poco::Net::Context>(
 | 
									auto SecureContext = Poco::AutoPtr<Poco::Net::Context>(
 | 
				
			||||||
					new Poco::Net::Context(Poco::Net::Context::TLS_CLIENT_USE, ""));
 | 
										new Poco::Net::Context(Poco::Net::Context::TLS_CLIENT_USE, ""));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				if (Pool_.acctConfig.servers[ServerIndex_].allowSelfSigned) {
 | 
									if (Pool_.acctConfig.servers[ServerIndex_].allowSelfSigned) {
 | 
				
			||||||
@@ -430,7 +431,7 @@ namespace OpenWifi {
 | 
				
			|||||||
					DecodeFile(CaCertFiles_[CaCertFiles_.size() - 1]->path(), cert);
 | 
										DecodeFile(CaCertFiles_[CaCertFiles_.size() - 1]->path(), cert);
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				Poco::Net::Context::Ptr SecureContext =
 | 
									auto SecureContext =
 | 
				
			||||||
					Poco::AutoPtr<Poco::Net::Context>(new Poco::Net::Context(
 | 
										Poco::AutoPtr<Poco::Net::Context>(new Poco::Net::Context(
 | 
				
			||||||
						Poco::Net::Context::TLS_CLIENT_USE, KeyFile_.path(), CertFile_.path(), ""));
 | 
											Poco::Net::Context::TLS_CLIENT_USE, KeyFile_.path(), CertFile_.path(), ""));
 | 
				
			||||||
				if (Pool_.acctConfig.servers[ServerIndex_].allowSelfSigned) {
 | 
									if (Pool_.acctConfig.servers[ServerIndex_].allowSelfSigned) {
 | 
				
			||||||
@@ -498,7 +499,9 @@ namespace OpenWifi {
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		inline bool Connect_Generic() {
 | 
							inline bool Connect_Generic() {
 | 
				
			||||||
			if (TryAgain_) {
 | 
								poco_information(Logger_, fmt::format("Connecting {}", Pool_.name));
 | 
				
			||||||
 | 
								if (TryAgain_ && !Connected_) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				std::lock_guard G(LocalMutex_);
 | 
									std::lock_guard G(LocalMutex_);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				Poco::Net::SocketAddress AuthSockAddrV4(
 | 
									Poco::Net::SocketAddress AuthSockAddrV4(
 | 
				
			||||||
@@ -520,26 +523,6 @@ namespace OpenWifi {
 | 
				
			|||||||
					MicroServiceConfigGetInt("radius.proxy.coa.port", DEFAULT_RADIUS_CoA_PORT));
 | 
										MicroServiceConfigGetInt("radius.proxy.coa.port", DEFAULT_RADIUS_CoA_PORT));
 | 
				
			||||||
				CoASocketV4_ = std::make_unique<Poco::Net::DatagramSocket>(CoASockAddrV4, true, true);
 | 
									CoASocketV4_ = std::make_unique<Poco::Net::DatagramSocket>(CoASockAddrV4, true, true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
				AuthenticationSocketV6_ =
 | 
					 | 
				
			||||||
					std::make_unique<Poco::Net::DatagramSocket>(AuthSockAddrV6, true, true);
 | 
					 | 
				
			||||||
 				Poco::Net::SocketAddress AuthSockAddrV6(
 | 
					 | 
				
			||||||
					Poco::Net::AddressFamily::IPv6,
 | 
					 | 
				
			||||||
					MicroServiceConfigGetInt("radius.proxy.authentication.port",
 | 
					 | 
				
			||||||
											 DEFAULT_RADIUS_AUTHENTICATION_PORT));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				Poco::Net::SocketAddress AcctSockAddrV6(
 | 
					 | 
				
			||||||
					Poco::Net::AddressFamily::IPv6,
 | 
					 | 
				
			||||||
					MicroServiceConfigGetInt("radius.proxy.accounting.port",
 | 
					 | 
				
			||||||
											 DEFAULT_RADIUS_ACCOUNTING_PORT));
 | 
					 | 
				
			||||||
				AccountingSocketV6_ =
 | 
					 | 
				
			||||||
					std::make_unique<Poco::Net::DatagramSocket>(AcctSockAddrV6, true, true);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				Poco::Net::SocketAddress CoASockAddrV6(
 | 
					 | 
				
			||||||
					Poco::Net::AddressFamily::IPv6,
 | 
					 | 
				
			||||||
					MicroServiceConfigGetInt("radius.proxy.coa.port", DEFAULT_RADIUS_CoA_PORT));
 | 
					 | 
				
			||||||
				CoASocketV6_ = std::make_unique<Poco::Net::DatagramSocket>(CoASockAddrV6, true, true);
 | 
					 | 
				
			||||||
*/
 | 
					 | 
				
			||||||
				Reactor_.addEventHandler(
 | 
									Reactor_.addEventHandler(
 | 
				
			||||||
					*AuthenticationSocketV4_,
 | 
										*AuthenticationSocketV4_,
 | 
				
			||||||
					Poco::NObserver<RADIUS_Destination, Poco::Net::ReadableNotification>(
 | 
										Poco::NObserver<RADIUS_Destination, Poco::Net::ReadableNotification>(
 | 
				
			||||||
@@ -551,7 +534,27 @@ namespace OpenWifi {
 | 
				
			|||||||
				Reactor_.addEventHandler(
 | 
									Reactor_.addEventHandler(
 | 
				
			||||||
					*CoASocketV4_, Poco::NObserver<RADIUS_Destination, Poco::Net::ReadableNotification>(
 | 
										*CoASocketV4_, Poco::NObserver<RADIUS_Destination, Poco::Net::ReadableNotification>(
 | 
				
			||||||
									   *this, &RADIUS_Destination::OnCoASocketReadable));
 | 
														   *this, &RADIUS_Destination::OnCoASocketReadable));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 | 
									Poco::Net::SocketAddress AuthSockAddrV6(
 | 
				
			||||||
 | 
										Poco::Net::AddressFamily::IPv6,
 | 
				
			||||||
 | 
										MicroServiceConfigGetInt("radius.proxy.authentication.port",
 | 
				
			||||||
 | 
																 DEFAULT_RADIUS_AUTHENTICATION_PORT));
 | 
				
			||||||
 | 
									AuthenticationSocketV6_ =
 | 
				
			||||||
 | 
										std::make_unique<Poco::Net::DatagramSocket>(AuthSockAddrV6, true, true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									Poco::Net::SocketAddress AcctSockAddrV6(
 | 
				
			||||||
 | 
										Poco::Net::AddressFamily::IPv6,
 | 
				
			||||||
 | 
										MicroServiceConfigGetInt("radius.proxy.accounting.port",
 | 
				
			||||||
 | 
																 DEFAULT_RADIUS_AUTHENTICATION_PORT));
 | 
				
			||||||
 | 
									AccountingSocketV6_ =
 | 
				
			||||||
 | 
										std::make_unique<Poco::Net::DatagramSocket>(AcctSockAddrV6, true, true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									Poco::Net::SocketAddress CoASockAddrV6(
 | 
				
			||||||
 | 
										Poco::Net::AddressFamily::IPv6,
 | 
				
			||||||
 | 
										MicroServiceConfigGetInt("radius.proxy.coa.port", DEFAULT_RADIUS_CoA_PORT));
 | 
				
			||||||
 | 
									CoASocketV6_ = std::make_unique<Poco::Net::DatagramSocket>(CoASockAddrV6, true, true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				Reactor_.addEventHandler(
 | 
									Reactor_.addEventHandler(
 | 
				
			||||||
					*AuthenticationSocketV6_,
 | 
										*AuthenticationSocketV6_,
 | 
				
			||||||
					Poco::NObserver<RADIUS_Destination, Poco::Net::ReadableNotification>(
 | 
										Poco::NObserver<RADIUS_Destination, Poco::Net::ReadableNotification>(
 | 
				
			||||||
@@ -565,6 +568,7 @@ namespace OpenWifi {
 | 
				
			|||||||
					*CoASocketV6_, Poco::NObserver<RADIUS_Destination, Poco::Net::ReadableNotification>(
 | 
										*CoASocketV6_, Poco::NObserver<RADIUS_Destination, Poco::Net::ReadableNotification>(
 | 
				
			||||||
									   *this, &RADIUS_Destination::OnCoASocketReadable));
 | 
														   *this, &RADIUS_Destination::OnCoASocketReadable));
 | 
				
			||||||
*/
 | 
					*/
 | 
				
			||||||
 | 
									Connected_ = true;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			return true;
 | 
								return true;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
@@ -590,6 +594,8 @@ namespace OpenWifi {
 | 
				
			|||||||
			if (Connected_) {
 | 
								if (Connected_) {
 | 
				
			||||||
				std::lock_guard G(LocalMutex_);
 | 
									std::lock_guard G(LocalMutex_);
 | 
				
			||||||
				if(Type_==GWObjects::RadiusEndpointType::generic) {
 | 
									if(Type_==GWObjects::RadiusEndpointType::generic) {
 | 
				
			||||||
 | 
										poco_information(Logger_, fmt::format("Disconnecting {} generic server. Releasing all UDP resources.", Pool_.name));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
					if(AuthenticationSocketV4_) {
 | 
										if(AuthenticationSocketV4_) {
 | 
				
			||||||
						Reactor_.removeEventHandler(
 | 
											Reactor_.removeEventHandler(
 | 
				
			||||||
							*AuthenticationSocketV4_,
 | 
												*AuthenticationSocketV4_,
 | 
				
			||||||
@@ -617,7 +623,8 @@ namespace OpenWifi {
 | 
				
			|||||||
						CoASocketV4_.reset();
 | 
											CoASocketV4_.reset();
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*					if(AuthenticationSocketV6_) {
 | 
					/*
 | 
				
			||||||
 | 
					 					if(AuthenticationSocketV6_) {
 | 
				
			||||||
						Reactor_.removeEventHandler(
 | 
											Reactor_.removeEventHandler(
 | 
				
			||||||
							*AuthenticationSocketV6_,
 | 
												*AuthenticationSocketV6_,
 | 
				
			||||||
							Poco::NObserver<RADIUS_Destination, Poco::Net::ReadableNotification>(
 | 
												Poco::NObserver<RADIUS_Destination, Poco::Net::ReadableNotification>(
 | 
				
			||||||
@@ -646,7 +653,6 @@ namespace OpenWifi {
 | 
				
			|||||||
*/
 | 
					*/
 | 
				
			||||||
				} else {
 | 
									} else {
 | 
				
			||||||
					if(Socket_!=nullptr) {
 | 
										if(Socket_!=nullptr) {
 | 
				
			||||||
						std::lock_guard G(LocalMutex_);
 | 
					 | 
				
			||||||
						Reactor_.removeEventHandler(
 | 
											Reactor_.removeEventHandler(
 | 
				
			||||||
							*Socket_, Poco::NObserver<RADIUS_Destination, Poco::Net::ReadableNotification>(
 | 
												*Socket_, Poco::NObserver<RADIUS_Destination, Poco::Net::ReadableNotification>(
 | 
				
			||||||
										  *this, &RADIUS_Destination::onData));
 | 
															  *this, &RADIUS_Destination::onData));
 | 
				
			||||||
@@ -660,9 +666,9 @@ namespace OpenWifi {
 | 
				
			|||||||
						Socket_->close();
 | 
											Socket_->close();
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
 | 
									Connected_ = false;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			Connected_ = false;
 | 
								poco_information(Logger_, fmt::format("Disconnecting {}", Pool_.name));
 | 
				
			||||||
			poco_information(Logger_, "Disconnecting.");
 | 
					 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		static void DecodeFile(const std::string &filename, const std::string &s) {
 | 
							static void DecodeFile(const std::string &filename, const std::string &s) {
 | 
				
			||||||
@@ -724,7 +730,8 @@ namespace OpenWifi {
 | 
				
			|||||||
		std::unique_ptr<Poco::Net::DatagramSocket> 		AuthenticationSocketV4_;
 | 
							std::unique_ptr<Poco::Net::DatagramSocket> 		AuthenticationSocketV4_;
 | 
				
			||||||
		std::unique_ptr<Poco::Net::DatagramSocket> 		CoASocketV4_;
 | 
							std::unique_ptr<Poco::Net::DatagramSocket> 		CoASocketV4_;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*		std::unique_ptr<Poco::Net::DatagramSocket> 		CoASocketV6_;
 | 
					/*
 | 
				
			||||||
 | 
					 		std::unique_ptr<Poco::Net::DatagramSocket> 		CoASocketV6_;
 | 
				
			||||||
		std::unique_ptr<Poco::Net::DatagramSocket> 		AccountingSocketV6_;
 | 
							std::unique_ptr<Poco::Net::DatagramSocket> 		AccountingSocketV6_;
 | 
				
			||||||
		std::unique_ptr<Poco::Net::DatagramSocket> 		AuthenticationSocketV6_;
 | 
							std::unique_ptr<Poco::Net::DatagramSocket> 		AuthenticationSocketV6_;
 | 
				
			||||||
*/
 | 
					*/
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -25,9 +25,23 @@ namespace OpenWifi::RESTAPI_RPC {
 | 
				
			|||||||
		if (StorageService()->AddCommand(Cmd.SerialNumber, Cmd, Status)) {
 | 
							if (StorageService()->AddCommand(Cmd.SerialNumber, Cmd, Status)) {
 | 
				
			||||||
			Poco::JSON::Object RetObj;
 | 
								Poco::JSON::Object RetObj;
 | 
				
			||||||
			Cmd.to_json(RetObj);
 | 
								Cmd.to_json(RetObj);
 | 
				
			||||||
			if (Handler != nullptr)
 | 
								if (Handler == nullptr) {
 | 
				
			||||||
				return Handler->ReturnObject(RetObj);
 | 
									// nothing to process/return
 | 
				
			||||||
			return;
 | 
									return;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								Poco::Net::HTTPResponse::HTTPStatus cmd_status = Poco::Net::HTTPResponse::HTTP_OK;
 | 
				
			||||||
 | 
					            if (Cmd.ErrorCode > 0) {
 | 
				
			||||||
 | 
									// command returned error
 | 
				
			||||||
 | 
									cmd_status = Poco::Net::HTTPResponse::HTTP_BAD_REQUEST;
 | 
				
			||||||
 | 
									if (Cmd.Command == uCentralProtocol::CONFIGURE) {
 | 
				
			||||||
 | 
										// special handling for configure command
 | 
				
			||||||
 | 
										if (!Handler->GetBoolParameter("strict", false)) {
 | 
				
			||||||
 | 
											// in non-strict mode return success for failed configure command
 | 
				
			||||||
 | 
											cmd_status = Poco::Net::HTTPResponse::HTTP_OK;
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								return Handler->ReturnObject(RetObj, cmd_status);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		if (Handler != nullptr)
 | 
							if (Handler != nullptr)
 | 
				
			||||||
			return Handler->ReturnStatus(Poco::Net::HTTPResponse::HTTP_INTERNAL_SERVER_ERROR);
 | 
								return Handler->ReturnStatus(Poco::Net::HTTPResponse::HTTP_INTERNAL_SERVER_ERROR);
 | 
				
			||||||
@@ -40,8 +54,8 @@ namespace OpenWifi::RESTAPI_RPC {
 | 
				
			|||||||
						std::chrono::milliseconds WaitTimeInMs, Poco::JSON::Object *ObjectToReturn,
 | 
											std::chrono::milliseconds WaitTimeInMs, Poco::JSON::Object *ObjectToReturn,
 | 
				
			||||||
						RESTAPIHandler *Handler, Poco::Logger &Logger, bool Deferred) {
 | 
											RESTAPIHandler *Handler, Poco::Logger &Logger, bool Deferred) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		Logger.information(fmt::format("{},{}: New {} command. User={} Serial={}. ", Cmd.UUID,
 | 
							Logger.information(fmt::format("{},{}: New {} command. User={} Serial={} Details={}. ", Cmd.UUID,
 | 
				
			||||||
									   RPCID, Cmd.Command, Cmd.SubmittedBy, Cmd.SerialNumber));
 | 
														   RPCID, Cmd.Command, Cmd.SubmittedBy, Cmd.SerialNumber, Cmd.Details));
 | 
				
			||||||
		Cmd.Submitted = Utils::Now();
 | 
							Cmd.Submitted = Utils::Now();
 | 
				
			||||||
		Cmd.Executed = 0;
 | 
							Cmd.Executed = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -167,6 +181,20 @@ namespace OpenWifi::RESTAPI_RPC {
 | 
				
			|||||||
				Cmd.AttachType = "";
 | 
									Cmd.AttachType = "";
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								// If the command fails on the device we should show it as failed and not return 200 OK
 | 
				
			||||||
 | 
								// exception is configure command which only reported failed in strict validation mode
 | 
				
			||||||
 | 
								if (Cmd.ErrorCode &&
 | 
				
			||||||
 | 
									(Cmd.Command != uCentralProtocol::CONFIGURE ||
 | 
				
			||||||
 | 
										(Cmd.Command == uCentralProtocol::CONFIGURE && Handler->GetBoolParameter("strict", false))
 | 
				
			||||||
 | 
									))
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									Logger.information(fmt::format(
 | 
				
			||||||
 | 
									"Command failed with error on device: {}  Reason: {}.",
 | 
				
			||||||
 | 
									Cmd.ErrorCode, Cmd.ErrorText));
 | 
				
			||||||
 | 
									return SetCommandStatus(Cmd, Request, Response, Handler,
 | 
				
			||||||
 | 
													Storage::CommandExecutionType::COMMAND_FAILED, Logger);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if (Cmd.ErrorCode == 0 && Cmd.Command == uCentralProtocol::CONFIGURE) {
 | 
								if (Cmd.ErrorCode == 0 && Cmd.Command == uCentralProtocol::CONFIGURE) {
 | 
				
			||||||
				//	we need to post a kafka event for this.
 | 
									//	we need to post a kafka event for this.
 | 
				
			||||||
				if (Params.has(uCentralProtocol::CONFIG) && Params.isObject(uCentralProtocol::CONFIG)) {
 | 
									if (Params.has(uCentralProtocol::CONFIG) && Params.isObject(uCentralProtocol::CONFIG)) {
 | 
				
			||||||
@@ -175,6 +203,7 @@ namespace OpenWifi::RESTAPI_RPC {
 | 
				
			|||||||
					DeviceConfigurationChangeKafkaEvent KEvent(
 | 
										DeviceConfigurationChangeKafkaEvent KEvent(
 | 
				
			||||||
						Utils::SerialNumberToInt(Cmd.SerialNumber), Utils::Now(),
 | 
											Utils::SerialNumberToInt(Cmd.SerialNumber), Utils::Now(),
 | 
				
			||||||
						Config);
 | 
											Config);
 | 
				
			||||||
 | 
											
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -56,17 +56,27 @@ namespace OpenWifi {
 | 
				
			|||||||
			return BadRequest(RESTAPI::Errors::InvalidJSONDocument);
 | 
								return BadRequest(RESTAPI::Errors::InvalidJSONDocument);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (DefConfig.Models.empty()) {
 | 
							if (DefConfig.models.empty()) {
 | 
				
			||||||
			return BadRequest(RESTAPI::Errors::ModelIDListCannotBeEmpty);
 | 
								return BadRequest(RESTAPI::Errors::ModelIDListCannotBeEmpty);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		std::vector<std::string> Error;
 | 
							DefConfig.platform = DefConfig.platform.empty() ? Platforms::AP : DefConfig.platform;
 | 
				
			||||||
		if (!ValidateUCentralConfiguration(DefConfig.Configuration, Error,
 | 
							if(DefConfig.platform != Platforms::AP && DefConfig.platform != Platforms::SWITCH) {
 | 
				
			||||||
										   GetBoolParameter("strict", false))) {
 | 
								return BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
 | 
				
			||||||
			return BadRequest(RESTAPI::Errors::ConfigBlockInvalid);
 | 
					 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		DefConfig.Created = DefConfig.LastModified = Utils::Now();
 | 
							if(DefConfig.configuration.empty()) {
 | 
				
			||||||
 | 
								return BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							std::string Error;
 | 
				
			||||||
 | 
							if (!ValidateUCentralConfiguration(ConfigurationValidator::GetType(DefConfig.platform),
 | 
				
			||||||
 | 
															   DefConfig.configuration, Error,
 | 
				
			||||||
 | 
															   GetBoolParameter("strict", false))) {
 | 
				
			||||||
 | 
								return BadRequest(RESTAPI::Errors::ConfigBlockInvalid, Error);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							DefConfig.created = DefConfig.lastModified = Utils::Now();
 | 
				
			||||||
		if (StorageService()->CreateDefaultConfiguration(Name, DefConfig)) {
 | 
							if (StorageService()->CreateDefaultConfiguration(Name, DefConfig)) {
 | 
				
			||||||
			return OK();
 | 
								return OK();
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
@@ -88,19 +98,31 @@ namespace OpenWifi {
 | 
				
			|||||||
			return NotFound();
 | 
								return NotFound();
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (!NewConfig.Configuration.empty()) {
 | 
							if(Existing.platform.empty()) {
 | 
				
			||||||
			std::vector<std::string> Error;
 | 
								Existing.platform = Platforms::AP;
 | 
				
			||||||
			if (!ValidateUCentralConfiguration(NewConfig.Configuration, Error,
 | 
					 | 
				
			||||||
											   GetBoolParameter("strict", false))) {
 | 
					 | 
				
			||||||
				return BadRequest(RESTAPI::Errors::ConfigBlockInvalid);
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			Existing.Configuration = NewConfig.Configuration;
 | 
					 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		Existing.LastModified = Utils::Now();
 | 
							if(ParsedBody_->has("platform")) {
 | 
				
			||||||
		AssignIfPresent(Obj, "description", Existing.Description);
 | 
								if(NewConfig.platform.empty() || (NewConfig.platform != Platforms::AP && NewConfig.platform != Platforms::SWITCH)) {
 | 
				
			||||||
 | 
									return BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								Existing.platform = NewConfig.platform;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (!NewConfig.configuration.empty()) {
 | 
				
			||||||
 | 
								std::string Error;
 | 
				
			||||||
 | 
								if (!ValidateUCentralConfiguration(ConfigurationValidator::GetType(Existing.platform),
 | 
				
			||||||
 | 
																   NewConfig.configuration, Error,
 | 
				
			||||||
 | 
																   GetBoolParameter("strict", false))) {
 | 
				
			||||||
 | 
									return BadRequest(RESTAPI::Errors::ConfigBlockInvalid, Error);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								Existing.configuration = NewConfig.configuration;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							Existing.lastModified = Utils::Now();
 | 
				
			||||||
 | 
							AssignIfPresent(Obj, "description", Existing.description);
 | 
				
			||||||
		if (Obj->has("modelIds"))
 | 
							if (Obj->has("modelIds"))
 | 
				
			||||||
			Existing.Models = NewConfig.Models;
 | 
								Existing.models = NewConfig.models;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (StorageService()->UpdateDefaultConfiguration(Name, Existing)) {
 | 
							if (StorageService()->UpdateDefaultConfiguration(Name, Existing)) {
 | 
				
			||||||
			GWObjects::DefaultConfiguration ModifiedConfig;
 | 
								GWObjects::DefaultConfiguration ModifiedConfig;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -166,7 +166,12 @@ namespace OpenWifi {
 | 
				
			|||||||
		{APCommands::Commands::rrm, false, true, &RESTAPI_device_commandHandler::RRM, 60000ms},
 | 
							{APCommands::Commands::rrm, false, true, &RESTAPI_device_commandHandler::RRM, 60000ms},
 | 
				
			||||||
		{APCommands::Commands::certupdate, false, true, &RESTAPI_device_commandHandler::CertUpdate, 60000ms},
 | 
							{APCommands::Commands::certupdate, false, true, &RESTAPI_device_commandHandler::CertUpdate, 60000ms},
 | 
				
			||||||
		{APCommands::Commands::transfer, false, true, &RESTAPI_device_commandHandler::Transfer, 60000ms},
 | 
							{APCommands::Commands::transfer, false, true, &RESTAPI_device_commandHandler::Transfer, 60000ms},
 | 
				
			||||||
		{APCommands::Commands::script, false, true, &RESTAPI_device_commandHandler::Script, 60000ms}
 | 
							{APCommands::Commands::script, false, true, &RESTAPI_device_commandHandler::Script, 60000ms},
 | 
				
			||||||
 | 
							{APCommands::Commands::powercycle, false, true, &RESTAPI_device_commandHandler::PowerCycle, 60000ms},
 | 
				
			||||||
 | 
							{APCommands::Commands::fixedconfig, false, true, &RESTAPI_device_commandHandler::FixedConfig, 120000ms},
 | 
				
			||||||
 | 
							{APCommands::Commands::cablediagnostics, false, true, &RESTAPI_device_commandHandler::CableDiagnostics, 120000ms},
 | 
				
			||||||
 | 
							{APCommands::Commands::reenroll, false, true, &RESTAPI_device_commandHandler::ReEnroll, 120000ms},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	void RESTAPI_device_commandHandler::DoPost() {
 | 
						void RESTAPI_device_commandHandler::DoPost() {
 | 
				
			||||||
@@ -653,13 +658,18 @@ namespace OpenWifi {
 | 
				
			|||||||
				return BadRequest(RESTAPI::Errors::SerialNumberMismatch);
 | 
									return BadRequest(RESTAPI::Errors::SerialNumberMismatch);
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								GWObjects::Device DeviceInfo;
 | 
				
			||||||
 | 
								if (!StorageService()->GetDevice(SerialNumber_, DeviceInfo)) {
 | 
				
			||||||
 | 
									return NotFound();
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
			auto Configuration =
 | 
								auto Configuration =
 | 
				
			||||||
				GetS(RESTAPI::Protocol::CONFIGURATION, Obj, uCentralProtocol::EMPTY_JSON_DOC);
 | 
									GetS(RESTAPI::Protocol::CONFIGURATION, Obj, uCentralProtocol::EMPTY_JSON_DOC);
 | 
				
			||||||
			std::vector<std::string> Error;
 | 
								std::string Error;
 | 
				
			||||||
			if (!ValidateUCentralConfiguration(Configuration, Error,
 | 
								if (!ValidateUCentralConfiguration(ConfigurationValidator::GetType(DeviceInfo.DeviceType),
 | 
				
			||||||
 | 
																   Configuration, Error,
 | 
				
			||||||
											   GetBoolParameter("strict", false))) {
 | 
																   GetBoolParameter("strict", false))) {
 | 
				
			||||||
				CallCanceled("CONFIGURE", CMD_UUID, CMD_RPC, RESTAPI::Errors::ConfigBlockInvalid);
 | 
									CallCanceled("CONFIGURE", CMD_UUID, CMD_RPC, RESTAPI::Errors::ConfigBlockInvalid);
 | 
				
			||||||
				return BadRequest(RESTAPI::Errors::ConfigBlockInvalid);
 | 
									return BadRequest(RESTAPI::Errors::ConfigBlockInvalid, Error);
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			auto When = GetWhen(Obj);
 | 
								auto When = GetWhen(Obj);
 | 
				
			||||||
@@ -685,9 +695,31 @@ namespace OpenWifi {
 | 
				
			|||||||
				Params.stringify(ParamStream);
 | 
									Params.stringify(ParamStream);
 | 
				
			||||||
				Cmd.Details = ParamStream.str();
 | 
									Cmd.Details = ParamStream.str();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									// retrieve capabilities and encode/compress parameters, if required
 | 
				
			||||||
 | 
									Poco::JSON::Object ConfigParams = Params;
 | 
				
			||||||
 | 
									GWObjects::Capabilities Caps;
 | 
				
			||||||
 | 
									if (StorageService()->GetDeviceCapabilities(SerialNumber_, Caps)) {
 | 
				
			||||||
 | 
										Poco::JSON::Object CapsJson;
 | 
				
			||||||
 | 
										Caps.to_json(CapsJson);
 | 
				
			||||||
 | 
										auto DeviceCaps = CapsJson.getObject(uCentralProtocol::CAPABILITIES);
 | 
				
			||||||
 | 
										if (DeviceCaps->has("compress_cmd") && DeviceCaps->get("compress_cmd")) {
 | 
				
			||||||
 | 
											// compressed command capability present and it is set, compress parameters
 | 
				
			||||||
 | 
											Poco::JSON::Object CompressedParams;
 | 
				
			||||||
 | 
											std::string CompressedBase64Data;
 | 
				
			||||||
 | 
											std::uint64_t UncompressedDataLen = ParamStream.str().length();
 | 
				
			||||||
 | 
											if (Utils::CompressAndEncodeBase64(ParamStream.str(), CompressedBase64Data)) {
 | 
				
			||||||
 | 
												// set compressed, base 64 encoded data and length of uncompressed data
 | 
				
			||||||
 | 
												CompressedParams.set(uCentralProtocol::COMPRESS_64, CompressedBase64Data);
 | 
				
			||||||
 | 
												CompressedParams.set(uCentralProtocol::COMPRESS_SZ, UncompressedDataLen);
 | 
				
			||||||
 | 
												ConfigParams = CompressedParams;
 | 
				
			||||||
 | 
											}
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				// AP_WS_Server()->SetPendingUUID(SerialNumber_, NewUUID);
 | 
									// AP_WS_Server()->SetPendingUUID(SerialNumber_, NewUUID);
 | 
				
			||||||
				RESTAPI_RPC::WaitForCommand(CMD_RPC, APCommands::Commands::configure, true,
 | 
									RESTAPI_RPC::WaitForCommand(CMD_RPC, APCommands::Commands::configure, true,
 | 
				
			||||||
												   Cmd, Params, *Request, *Response, timeout,
 | 
																	   Cmd, ConfigParams, *Request, *Response, timeout,
 | 
				
			||||||
												   nullptr, this, Logger_);
 | 
																	   nullptr, this, Logger_);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				if(!Cmd.Executed) {
 | 
									if(!Cmd.Executed) {
 | 
				
			||||||
@@ -1401,9 +1433,9 @@ namespace OpenWifi {
 | 
				
			|||||||
		Cmd.WaitingForFile = 0;
 | 
							Cmd.WaitingForFile = 0;
 | 
				
			||||||
		Cmd.Status= "completed";
 | 
							Cmd.Status= "completed";
 | 
				
			||||||
		if(CommandManager()->FireAndForget(SerialNumber_, uCentralProtocol::RRM, Params)) {
 | 
							if(CommandManager()->FireAndForget(SerialNumber_, uCentralProtocol::RRM, Params)) {
 | 
				
			||||||
 | 
								Cmd.Status= "completed";
 | 
				
			||||||
			StorageService()->AddCommand(SerialNumber_, Cmd,
 | 
								StorageService()->AddCommand(SerialNumber_, Cmd,
 | 
				
			||||||
										 Storage::CommandExecutionType::COMMAND_COMPLETED);
 | 
															 Storage::CommandExecutionType::COMMAND_COMPLETED);
 | 
				
			||||||
			Cmd.Status= "completed";
 | 
					 | 
				
			||||||
			return OK();
 | 
								return OK();
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		Cmd.Status= "failed";	//	should never happen
 | 
							Cmd.Status= "failed";	//	should never happen
 | 
				
			||||||
@@ -1501,4 +1533,164 @@ namespace OpenWifi {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						void RESTAPI_device_commandHandler::PowerCycle(
 | 
				
			||||||
 | 
							const std::string &CMD_UUID, uint64_t CMD_RPC,
 | 
				
			||||||
 | 
							[[maybe_unused]] std::chrono::milliseconds timeout,
 | 
				
			||||||
 | 
							[[maybe_unused]] const GWObjects::DeviceRestrictions &Restrictions) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if(UserInfo_.userinfo.userRole != SecurityObjects::ROOT &&
 | 
				
			||||||
 | 
								UserInfo_.userinfo.userRole != SecurityObjects::ADMIN) {
 | 
				
			||||||
 | 
								CallCanceled("RRM", CMD_UUID, CMD_RPC, RESTAPI::Errors::ACCESS_DENIED);
 | 
				
			||||||
 | 
								return UnAuthorized(RESTAPI::Errors::ACCESS_DENIED);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							poco_debug(Logger_, fmt::format("POWERCYCLE({},{}): TID={} user={} serial={}", CMD_UUID,
 | 
				
			||||||
 | 
															CMD_RPC, TransactionId_, Requester(), SerialNumber_));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if(IsDeviceSimulated(SerialNumber_)) {
 | 
				
			||||||
 | 
								CallCanceled("RRM", CMD_UUID, CMD_RPC, RESTAPI::Errors::SimulatedDeviceNotSupported);
 | 
				
			||||||
 | 
								return BadRequest(RESTAPI::Errors::SimulatedDeviceNotSupported);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							GWObjects::PowerCycleRequest	PR;
 | 
				
			||||||
 | 
							if(!PR.from_json(ParsedBody_)) {
 | 
				
			||||||
 | 
								return BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							GWObjects::CommandDetails Cmd;
 | 
				
			||||||
 | 
							Cmd.SerialNumber = SerialNumber_;
 | 
				
			||||||
 | 
							Cmd.SubmittedBy = Requester();
 | 
				
			||||||
 | 
							Cmd.UUID = CMD_UUID;
 | 
				
			||||||
 | 
							Cmd.Command = uCentralProtocol::POWERCYCLE;
 | 
				
			||||||
 | 
							std::ostringstream os;
 | 
				
			||||||
 | 
							ParsedBody_->stringify(os);
 | 
				
			||||||
 | 
							Cmd.Details = os.str();
 | 
				
			||||||
 | 
							Cmd.RunAt = PR.when;
 | 
				
			||||||
 | 
							Cmd.ErrorCode = 0;
 | 
				
			||||||
 | 
							Cmd.WaitingForFile = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							return RESTAPI_RPC::WaitForCommand(CMD_RPC, APCommands::Commands::powercycle, false, Cmd,
 | 
				
			||||||
 | 
															   *ParsedBody_, *Request, *Response, timeout, nullptr, this,
 | 
				
			||||||
 | 
															   Logger_);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// `fixedconfig` command is used set country propery on AP
 | 
				
			||||||
 | 
						// This handler uses `fixedconfig` command definitions
 | 
				
			||||||
 | 
						void RESTAPI_device_commandHandler::FixedConfig(
 | 
				
			||||||
 | 
							const std::string &CMD_UUID, uint64_t CMD_RPC, std::chrono::milliseconds timeout,
 | 
				
			||||||
 | 
							[[maybe_unused]] const GWObjects::DeviceRestrictions &Restrictions) {
 | 
				
			||||||
 | 
							poco_debug(Logger_, fmt::format("FIXEDCONFIG({},{}): TID={} user={} serial={}", CMD_UUID, CMD_RPC,
 | 
				
			||||||
 | 
															TransactionId_, Requester(), SerialNumber_));
 | 
				
			||||||
 | 
							// do not allow `fixedconfig` command for simulated devices
 | 
				
			||||||
 | 
							if(IsDeviceSimulated(SerialNumber_)) {
 | 
				
			||||||
 | 
								CallCanceled("FIXEDCONFIG", CMD_UUID, CMD_RPC, RESTAPI::Errors::SimulatedDeviceNotSupported);
 | 
				
			||||||
 | 
								return BadRequest(RESTAPI::Errors::SimulatedDeviceNotSupported);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// setup and validate fixedconfig object
 | 
				
			||||||
 | 
							GWObjects::FixedConfig fixed_config;
 | 
				
			||||||
 | 
							if(!fixed_config.from_json(ParsedBody_)) {
 | 
				
			||||||
 | 
								return BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// setup command message
 | 
				
			||||||
 | 
							GWObjects::CommandDetails Cmd;
 | 
				
			||||||
 | 
							Cmd.SerialNumber = SerialNumber_;
 | 
				
			||||||
 | 
							Cmd.SubmittedBy = Requester();
 | 
				
			||||||
 | 
							Cmd.UUID = CMD_UUID;
 | 
				
			||||||
 | 
							Cmd.Command = uCentralProtocol::FIXEDCONFIG;
 | 
				
			||||||
 | 
							std::ostringstream os;
 | 
				
			||||||
 | 
							ParsedBody_->stringify(os);
 | 
				
			||||||
 | 
							Cmd.Details = os.str();
 | 
				
			||||||
 | 
							Cmd.RunAt = 0;
 | 
				
			||||||
 | 
							Cmd.ErrorCode = 0;
 | 
				
			||||||
 | 
							Cmd.WaitingForFile = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// send fixedconfig command to device and return status
 | 
				
			||||||
 | 
							return RESTAPI_RPC::WaitForCommand(CMD_RPC, APCommands::Commands::fixedconfig, false, Cmd,
 | 
				
			||||||
 | 
															   *ParsedBody_, *Request, *Response, timeout, nullptr, this,
 | 
				
			||||||
 | 
															   Logger_);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						void RESTAPI_device_commandHandler::CableDiagnostics(
 | 
				
			||||||
 | 
							const std::string &CMD_UUID, uint64_t CMD_RPC,
 | 
				
			||||||
 | 
							[[maybe_unused]] std::chrono::milliseconds timeout,
 | 
				
			||||||
 | 
							[[maybe_unused]] const GWObjects::DeviceRestrictions &Restrictions) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if(UserInfo_.userinfo.userRole != SecurityObjects::ROOT &&
 | 
				
			||||||
 | 
								UserInfo_.userinfo.userRole != SecurityObjects::ADMIN) {
 | 
				
			||||||
 | 
								CallCanceled("CABLEDIAGNOSTICS", CMD_UUID, CMD_RPC, RESTAPI::Errors::ACCESS_DENIED);
 | 
				
			||||||
 | 
								return UnAuthorized(RESTAPI::Errors::ACCESS_DENIED);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							poco_debug(Logger_, fmt::format("CABLEDIAGNOSTICS({},{}): TID={} user={} serial={}", CMD_UUID,
 | 
				
			||||||
 | 
															CMD_RPC, TransactionId_, Requester(), SerialNumber_));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if(IsDeviceSimulated(SerialNumber_)) {
 | 
				
			||||||
 | 
								CallCanceled("CABLEDIAGNOSTICS", CMD_UUID, CMD_RPC, RESTAPI::Errors::SimulatedDeviceNotSupported);
 | 
				
			||||||
 | 
								return BadRequest(RESTAPI::Errors::SimulatedDeviceNotSupported);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							GWObjects::CableDiagnostics	PR;
 | 
				
			||||||
 | 
							if(!PR.from_json(ParsedBody_)) {
 | 
				
			||||||
 | 
								return BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							GWObjects::CommandDetails Cmd;
 | 
				
			||||||
 | 
							Cmd.SerialNumber = SerialNumber_;
 | 
				
			||||||
 | 
							Cmd.SubmittedBy = Requester();
 | 
				
			||||||
 | 
							Cmd.UUID = CMD_UUID;
 | 
				
			||||||
 | 
							Cmd.Command = uCentralProtocol::CABLEDIAGNOSTICS;
 | 
				
			||||||
 | 
							std::ostringstream os;
 | 
				
			||||||
 | 
							ParsedBody_->stringify(os);
 | 
				
			||||||
 | 
							Cmd.Details = os.str();
 | 
				
			||||||
 | 
							Cmd.RunAt = PR.when;
 | 
				
			||||||
 | 
							Cmd.ErrorCode = 0;
 | 
				
			||||||
 | 
							Cmd.WaitingForFile = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							return RESTAPI_RPC::WaitForCommand(CMD_RPC, APCommands::Commands::cablediagnostics, false, Cmd,
 | 
				
			||||||
 | 
															   *ParsedBody_, *Request, *Response, timeout, nullptr, this,
 | 
				
			||||||
 | 
															   Logger_);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						void RESTAPI_device_commandHandler::ReEnroll(
 | 
				
			||||||
 | 
							const std::string &CMD_UUID, uint64_t CMD_RPC,
 | 
				
			||||||
 | 
							[[maybe_unused]] std::chrono::milliseconds timeout,
 | 
				
			||||||
 | 
							[[maybe_unused]] const GWObjects::DeviceRestrictions &Restrictions) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if(UserInfo_.userinfo.userRole != SecurityObjects::ROOT &&
 | 
				
			||||||
 | 
								UserInfo_.userinfo.userRole != SecurityObjects::ADMIN) {
 | 
				
			||||||
 | 
								CallCanceled("REENROLL", CMD_UUID, CMD_RPC, RESTAPI::Errors::ACCESS_DENIED);
 | 
				
			||||||
 | 
								return UnAuthorized(RESTAPI::Errors::ACCESS_DENIED);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							poco_debug(Logger_, fmt::format("REENROLL({},{}): TID={} user={} serial={}", CMD_UUID,
 | 
				
			||||||
 | 
															CMD_RPC, TransactionId_, Requester(), SerialNumber_));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if(IsDeviceSimulated(SerialNumber_)) {
 | 
				
			||||||
 | 
								CallCanceled("REENROLL", CMD_UUID, CMD_RPC, RESTAPI::Errors::SimulatedDeviceNotSupported);
 | 
				
			||||||
 | 
								return BadRequest(RESTAPI::Errors::SimulatedDeviceNotSupported);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							GWObjects::ReEnroll PR;
 | 
				
			||||||
 | 
							if(!PR.from_json(ParsedBody_)) {
 | 
				
			||||||
 | 
								return BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							GWObjects::CommandDetails Cmd;
 | 
				
			||||||
 | 
							Cmd.SerialNumber = SerialNumber_;
 | 
				
			||||||
 | 
							Cmd.SubmittedBy = Requester();
 | 
				
			||||||
 | 
							Cmd.UUID = CMD_UUID;
 | 
				
			||||||
 | 
							Cmd.Command = uCentralProtocol::REENROLL;
 | 
				
			||||||
 | 
							std::ostringstream os;
 | 
				
			||||||
 | 
							ParsedBody_->stringify(os);
 | 
				
			||||||
 | 
							Cmd.Details = os.str();
 | 
				
			||||||
 | 
							Cmd.RunAt = PR.when;
 | 
				
			||||||
 | 
							Cmd.ErrorCode = 0;
 | 
				
			||||||
 | 
							Cmd.WaitingForFile = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							return RESTAPI_RPC::WaitForCommand(CMD_RPC, APCommands::Commands::reenroll, false, Cmd,
 | 
				
			||||||
 | 
															   *ParsedBody_, *Request, *Response, timeout, nullptr, this,
 | 
				
			||||||
 | 
															   Logger_);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
} // namespace OpenWifi
 | 
					} // namespace OpenWifi
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -68,6 +68,14 @@ namespace OpenWifi {
 | 
				
			|||||||
					const GWObjects::DeviceRestrictions &R);
 | 
										const GWObjects::DeviceRestrictions &R);
 | 
				
			||||||
		void Transfer(const std::string &UUID, uint64_t RPC, std::chrono::milliseconds timeout,
 | 
							void Transfer(const std::string &UUID, uint64_t RPC, std::chrono::milliseconds timeout,
 | 
				
			||||||
					const GWObjects::DeviceRestrictions &R);
 | 
										const GWObjects::DeviceRestrictions &R);
 | 
				
			||||||
 | 
							void PowerCycle(const std::string &UUID, uint64_t RPC, std::chrono::milliseconds timeout,
 | 
				
			||||||
 | 
										  const GWObjects::DeviceRestrictions &R);
 | 
				
			||||||
 | 
							void FixedConfig(const std::string &UUID, uint64_t RPC, std::chrono::milliseconds timeout,
 | 
				
			||||||
 | 
										  const GWObjects::DeviceRestrictions &R);
 | 
				
			||||||
 | 
							void CableDiagnostics(const std::string &UUID, uint64_t RPC, std::chrono::milliseconds timeout,
 | 
				
			||||||
 | 
										  const GWObjects::DeviceRestrictions &R);
 | 
				
			||||||
 | 
							void ReEnroll(const std::string &UUID, uint64_t RPC, std::chrono::milliseconds timeout,
 | 
				
			||||||
 | 
										  const GWObjects::DeviceRestrictions &R);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		static auto PathName() {
 | 
							static auto PathName() {
 | 
				
			||||||
			return std::list<std::string>{"/api/v1/device/{serialNumber}/{command}"};
 | 
								return std::list<std::string>{"/api/v1/device/{serialNumber}/{command}"};
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -17,6 +17,8 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#include "RESTAPI_device_helper.h"
 | 
					#include "RESTAPI_device_helper.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "AP_WS_Server.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace OpenWifi {
 | 
					namespace OpenWifi {
 | 
				
			||||||
	void RESTAPI_device_handler::DoGet() {
 | 
						void RESTAPI_device_handler::DoGet() {
 | 
				
			||||||
		std::string SerialNumber = GetBinding(RESTAPI::Protocol::SERIALNUMBER, "");
 | 
							std::string SerialNumber = GetBinding(RESTAPI::Protocol::SERIALNUMBER, "");
 | 
				
			||||||
@@ -80,6 +82,9 @@ namespace OpenWifi {
 | 
				
			|||||||
			return OK();
 | 
								return OK();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		} else if (StorageService()->DeleteDevice(SerialNumber)) {
 | 
							} else if (StorageService()->DeleteDevice(SerialNumber)) {
 | 
				
			||||||
 | 
								if(AP_WS_Server()->Connected(Utils::SerialNumberToInt(SerialNumber))) {
 | 
				
			||||||
 | 
									AP_WS_Server()->Disconnect(Utils::SerialNumberToInt(SerialNumber));
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
			return OK();
 | 
								return OK();
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -101,9 +106,10 @@ namespace OpenWifi {
 | 
				
			|||||||
			}
 | 
								}
 | 
				
			||||||
			auto Config = Obj->get("configuration").toString();
 | 
								auto Config = Obj->get("configuration").toString();
 | 
				
			||||||
			Poco::JSON::Object Answer;
 | 
								Poco::JSON::Object Answer;
 | 
				
			||||||
			std::vector<std::string> Error;
 | 
								std::string Error;
 | 
				
			||||||
 | 
								auto DeviceType = Poco::toLower(GetParameter("deviceType", Platforms::AP));
 | 
				
			||||||
			auto Res =
 | 
								auto Res =
 | 
				
			||||||
				ValidateUCentralConfiguration(Config, Error, GetBoolParameter("strict", false));
 | 
									ValidateUCentralConfiguration(ConfigurationValidator::GetType(DeviceType),Config, Error, GetBoolParameter("strict", false));
 | 
				
			||||||
			Answer.set("valid", Res);
 | 
								Answer.set("valid", Res);
 | 
				
			||||||
			if (!Error.empty())
 | 
								if (!Error.empty())
 | 
				
			||||||
				Answer.set("error", Error);
 | 
									Answer.set("error", Error);
 | 
				
			||||||
@@ -123,12 +129,13 @@ namespace OpenWifi {
 | 
				
			|||||||
			return BadRequest(RESTAPI::Errors::SerialNumberMismatch);
 | 
								return BadRequest(RESTAPI::Errors::SerialNumberMismatch);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		std::vector<std::string> Error;
 | 
							std::string Error;
 | 
				
			||||||
		if (Device.Configuration.empty() ||
 | 
							if (Device.Configuration.empty() ||
 | 
				
			||||||
			(!Device.Configuration.empty() &&
 | 
								(!Device.Configuration.empty() &&
 | 
				
			||||||
			 !ValidateUCentralConfiguration(Device.Configuration, Error,
 | 
								 !ValidateUCentralConfiguration(ConfigurationValidator::GetType(Device.DeviceType),
 | 
				
			||||||
 | 
																Device.Configuration, Error,
 | 
				
			||||||
											GetBoolParameter("strict", false)))) {
 | 
																GetBoolParameter("strict", false)))) {
 | 
				
			||||||
			return BadRequest(RESTAPI::Errors::ConfigBlockInvalid);
 | 
								return BadRequest(RESTAPI::Errors::ConfigBlockInvalid, Error);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		for (auto &i : Device.Notes) {
 | 
							for (auto &i : Device.Notes) {
 | 
				
			||||||
@@ -169,10 +176,11 @@ namespace OpenWifi {
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (!NewDevice.Configuration.empty()) {
 | 
							if (!NewDevice.Configuration.empty()) {
 | 
				
			||||||
			std::vector<std::string> Error;
 | 
								std::string Error;
 | 
				
			||||||
			if (!ValidateUCentralConfiguration(NewDevice.Configuration, Error,
 | 
								if (!ValidateUCentralConfiguration(ConfigurationValidator::GetType(Existing.DeviceType),
 | 
				
			||||||
 | 
																   NewDevice.Configuration, Error,
 | 
				
			||||||
											   GetBoolParameter("strict", false))) {
 | 
																   GetBoolParameter("strict", false))) {
 | 
				
			||||||
				return BadRequest(RESTAPI::Errors::ConfigBlockInvalid);
 | 
									return BadRequest(RESTAPI::Errors::ConfigBlockInvalid, Error);
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			Config::Config NewConfig(NewDevice.Configuration);
 | 
								Config::Config NewConfig(NewDevice.Configuration);
 | 
				
			||||||
			uint64_t NewConfigUUID = Utils::Now();
 | 
								uint64_t NewConfigUUID = Utils::Now();
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -82,15 +82,24 @@ namespace OpenWifi {
 | 
				
			|||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							auto platform = Poco::toLower(GetParameter("platform", ""));
 | 
				
			||||||
		auto serialOnly = GetBoolParameter(RESTAPI::Protocol::SERIALONLY, false);
 | 
							auto serialOnly = GetBoolParameter(RESTAPI::Protocol::SERIALONLY, false);
 | 
				
			||||||
		auto deviceWithStatus = GetBoolParameter(RESTAPI::Protocol::DEVICEWITHSTATUS, false);
 | 
							auto deviceWithStatus = GetBoolParameter(RESTAPI::Protocol::DEVICEWITHSTATUS, false);
 | 
				
			||||||
		auto completeInfo = GetBoolParameter("completeInfo", false);
 | 
							auto completeInfo = GetBoolParameter("completeInfo", false);
 | 
				
			||||||
 | 
							auto includeProvisioned = GetBoolParameter("includeProvisioned", true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if(!platform.empty() && (platform!=Platforms::AP && platform!=Platforms::SWITCH && platform!="all")) {
 | 
				
			||||||
 | 
								return BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if(platform=="all")
 | 
				
			||||||
 | 
								platform="";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		Poco::JSON::Object RetObj;
 | 
							Poco::JSON::Object RetObj;
 | 
				
			||||||
		if (!QB_.Select.empty()) {
 | 
							if (!QB_.Select.empty()) {
 | 
				
			||||||
			Poco::JSON::Array Objects;
 | 
								Poco::JSON::Array Objects;
 | 
				
			||||||
			for (auto &i : SelectedRecords()) {
 | 
								for (auto &i : SelectedRecords()) {
 | 
				
			||||||
				auto SerialNumber = i;
 | 
									auto &SerialNumber = i;
 | 
				
			||||||
				if (!Utils::ValidSerialNumber(i))
 | 
									if (!Utils::ValidSerialNumber(i))
 | 
				
			||||||
					continue;
 | 
										continue;
 | 
				
			||||||
				GWObjects::Device D;
 | 
									GWObjects::Device D;
 | 
				
			||||||
@@ -116,14 +125,14 @@ namespace OpenWifi {
 | 
				
			|||||||
			else
 | 
								else
 | 
				
			||||||
				RetObj.set(RESTAPI::Protocol::DEVICES, Objects);
 | 
									RetObj.set(RESTAPI::Protocol::DEVICES, Objects);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		} else if (QB_.CountOnly == true) {
 | 
							} else if (QB_.CountOnly) {
 | 
				
			||||||
			uint64_t Count = 0;
 | 
								uint64_t Count = 0;
 | 
				
			||||||
			if (StorageService()->GetDeviceCount(Count)) {
 | 
								if (StorageService()->GetDeviceCount(Count, platform)) {
 | 
				
			||||||
				return ReturnCountOnly(Count);
 | 
									return ReturnCountOnly(Count);
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		} else if (serialOnly) {
 | 
							} else if (serialOnly) {
 | 
				
			||||||
			std::vector<std::string> SerialNumbers;
 | 
								std::vector<std::string> SerialNumbers;
 | 
				
			||||||
			StorageService()->GetDeviceSerialNumbers(QB_.Offset, QB_.Limit, SerialNumbers, OrderBy);
 | 
								StorageService()->GetDeviceSerialNumbers(QB_.Offset, QB_.Limit, SerialNumbers, OrderBy, platform, includeProvisioned);
 | 
				
			||||||
			Poco::JSON::Array Objects;
 | 
								Poco::JSON::Array Objects;
 | 
				
			||||||
			for (const auto &i : SerialNumbers) {
 | 
								for (const auto &i : SerialNumbers) {
 | 
				
			||||||
				Objects.add(i);
 | 
									Objects.add(i);
 | 
				
			||||||
@@ -141,7 +150,7 @@ namespace OpenWifi {
 | 
				
			|||||||
			RetObj.set("serialNumbers", Objects);
 | 
								RetObj.set("serialNumbers", Objects);
 | 
				
			||||||
		} else {
 | 
							} else {
 | 
				
			||||||
			std::vector<GWObjects::Device> Devices;
 | 
								std::vector<GWObjects::Device> Devices;
 | 
				
			||||||
			StorageService()->GetDevices(QB_.Offset, QB_.Limit, Devices, OrderBy);
 | 
								StorageService()->GetDevices(QB_.Offset, QB_.Limit, Devices, OrderBy, platform, includeProvisioned);
 | 
				
			||||||
			Poco::JSON::Array Objects;
 | 
								Poco::JSON::Array Objects;
 | 
				
			||||||
			for (const auto &i : Devices) {
 | 
								for (const auto &i : Devices) {
 | 
				
			||||||
				Poco::JSON::Object Obj;
 | 
									Poco::JSON::Object Obj;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -22,9 +22,15 @@ namespace OpenWifi {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
		std::string FileType;
 | 
							std::string FileType;
 | 
				
			||||||
		std::string FileContent;
 | 
							std::string FileContent;
 | 
				
			||||||
		if (!StorageService()->GetAttachedFileContent(UUID, SerialNumber, FileContent, FileType) || FileContent.empty()) {
 | 
							int WaitingForFile = 0;
 | 
				
			||||||
 | 
							if (!StorageService()->GetAttachedFileContent(UUID, SerialNumber, FileContent, FileType, WaitingForFile) && !WaitingForFile) {
 | 
				
			||||||
			return NotFound();
 | 
								return NotFound();
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
							else if (WaitingForFile) {
 | 
				
			||||||
 | 
								// waiting for file to be uploaded, return Accepted
 | 
				
			||||||
 | 
								return Accepted();
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (FileType == "pcap") {
 | 
							if (FileType == "pcap") {
 | 
				
			||||||
			SendFileContent(FileContent, "application/vnd.tcpdump.pcap", UUID + ".pcap");
 | 
								SendFileContent(FileContent, "application/vnd.tcpdump.pcap", UUID + ".pcap");
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -8,7 +8,7 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#pragma once
 | 
					#pragma once
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "framework/RESTAPI_Handler.h"
 | 
					#include <framework/RESTAPI_Handler.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace OpenWifi {
 | 
					namespace OpenWifi {
 | 
				
			||||||
	class RESTAPI_file : public RESTAPIHandler {
 | 
						class RESTAPI_file : public RESTAPIHandler {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -7,6 +7,7 @@
 | 
				
			|||||||
#include "RESTAPI_ProvObjects.h"
 | 
					#include "RESTAPI_ProvObjects.h"
 | 
				
			||||||
#include "framework/utils.h"
 | 
					#include "framework/utils.h"
 | 
				
			||||||
#include <vector>
 | 
					#include <vector>
 | 
				
			||||||
 | 
					#include "framework/ow_constants.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace OpenWifi {
 | 
					namespace OpenWifi {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -12,6 +12,7 @@
 | 
				
			|||||||
#include "Daemon.h"
 | 
					#include "Daemon.h"
 | 
				
			||||||
#ifdef TIP_GATEWAY_SERVICE
 | 
					#ifdef TIP_GATEWAY_SERVICE
 | 
				
			||||||
#include "AP_WS_Server.h"
 | 
					#include "AP_WS_Server.h"
 | 
				
			||||||
 | 
					#include "StorageService.h"
 | 
				
			||||||
#include "CapabilitiesCache.h"
 | 
					#include "CapabilitiesCache.h"
 | 
				
			||||||
#include "RADIUSSessionTracker.h"
 | 
					#include "RADIUSSessionTracker.h"
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
@@ -29,8 +30,8 @@ namespace OpenWifi::GWObjects {
 | 
				
			|||||||
	void Device::to_json(Poco::JSON::Object &Obj) const {
 | 
						void Device::to_json(Poco::JSON::Object &Obj) const {
 | 
				
			||||||
		field_to_json(Obj, "serialNumber", SerialNumber);
 | 
							field_to_json(Obj, "serialNumber", SerialNumber);
 | 
				
			||||||
#ifdef TIP_GATEWAY_SERVICE
 | 
					#ifdef TIP_GATEWAY_SERVICE
 | 
				
			||||||
		field_to_json(Obj, "deviceType", CapabilitiesCache::instance()->GetPlatform(Compatible));
 | 
							field_to_json(Obj, "deviceType", StorageService()->GetPlatform(SerialNumber));
 | 
				
			||||||
		field_to_json(Obj, "hasRADIUSSessions", RADIUSSessionTracker()->HasSessions(SerialNumber));
 | 
							field_to_json(Obj, "blackListed", StorageService()->IsBlackListed(Utils::MACToInt(SerialNumber)));
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
		field_to_json(Obj, "macAddress", MACAddress);
 | 
							field_to_json(Obj, "macAddress", MACAddress);
 | 
				
			||||||
		field_to_json(Obj, "manufacturer", Manufacturer);
 | 
							field_to_json(Obj, "manufacturer", Manufacturer);
 | 
				
			||||||
@@ -68,9 +69,14 @@ namespace OpenWifi::GWObjects {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#ifdef TIP_GATEWAY_SERVICE
 | 
					#ifdef TIP_GATEWAY_SERVICE
 | 
				
			||||||
		ConnectionState ConState;
 | 
							ConnectionState ConState;
 | 
				
			||||||
 | 
					#ifdef USE_MEDUSA_CLIENT
 | 
				
			||||||
		if (AP_WS_Server()->GetState(SerialNumber, ConState)) {
 | 
					        auto Res = GS()->GetState(SerialNumber);
 | 
				
			||||||
 | 
					        if (Res.has_value()) {
 | 
				
			||||||
 | 
					            Res.value().to_json(SerialNumber,Obj);
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					        if (AP_WS_Server()->GetState(SerialNumber, ConState)) {
 | 
				
			||||||
			ConState.to_json(SerialNumber,Obj);
 | 
								ConState.to_json(SerialNumber,Obj);
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
		} else {
 | 
							} else {
 | 
				
			||||||
			field_to_json(Obj, "ipAddress", "");
 | 
								field_to_json(Obj, "ipAddress", "");
 | 
				
			||||||
			field_to_json(Obj, "txBytes", (uint64_t)0);
 | 
								field_to_json(Obj, "txBytes", (uint64_t)0);
 | 
				
			||||||
@@ -166,14 +172,17 @@ namespace OpenWifi::GWObjects {
 | 
				
			|||||||
		field_to_json(Obj, "recorded", Recorded);
 | 
							field_to_json(Obj, "recorded", Recorded);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	void DefaultConfiguration::to_json(Poco::JSON::Object &Obj) const {
 | 
					    bool HealthCheck::from_json(const Poco::JSON::Object::Ptr &Obj) {
 | 
				
			||||||
		EmbedDocument("configuration", Obj, Configuration);
 | 
					        try {
 | 
				
			||||||
		field_to_json(Obj, "name", Name);
 | 
					            field_from_json(Obj, "UUID", UUID);
 | 
				
			||||||
		field_to_json(Obj, "modelIds", Models);
 | 
					            field_from_json(Obj, "sanity", Sanity);
 | 
				
			||||||
		field_to_json(Obj, "description", Description);
 | 
					            field_from_json(Obj, "recorded", Recorded);
 | 
				
			||||||
		field_to_json(Obj, "created", Created);
 | 
					            return true;
 | 
				
			||||||
		field_to_json(Obj, "lastModified", LastModified);
 | 
					        } catch(...) {
 | 
				
			||||||
	}
 | 
					
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return false;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	void DefaultFirmware::to_json(Poco::JSON::Object &Obj) const {
 | 
						void DefaultFirmware::to_json(Poco::JSON::Object &Obj) const {
 | 
				
			||||||
		field_to_json(Obj, "deviceType", deviceType);
 | 
							field_to_json(Obj, "deviceType", deviceType);
 | 
				
			||||||
@@ -222,12 +231,25 @@ namespace OpenWifi::GWObjects {
 | 
				
			|||||||
		field_to_json(Obj, "deferred", deferred);
 | 
							field_to_json(Obj, "deferred", deferred);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						void DefaultConfiguration::to_json(Poco::JSON::Object &Obj) const {
 | 
				
			||||||
 | 
							EmbedDocument("configuration", Obj, configuration);
 | 
				
			||||||
 | 
							field_to_json(Obj, "name", name);
 | 
				
			||||||
 | 
							field_to_json(Obj, "modelIds", models);
 | 
				
			||||||
 | 
							field_to_json(Obj, "description", description);
 | 
				
			||||||
 | 
							field_to_json(Obj, "created", created);
 | 
				
			||||||
 | 
							field_to_json(Obj, "lastModified", lastModified);
 | 
				
			||||||
 | 
							field_to_json(Obj, "platform", platform);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	bool DefaultConfiguration::from_json(const Poco::JSON::Object::Ptr &Obj) {
 | 
						bool DefaultConfiguration::from_json(const Poco::JSON::Object::Ptr &Obj) {
 | 
				
			||||||
		try {
 | 
							try {
 | 
				
			||||||
			field_from_json(Obj, "name", Name);
 | 
								field_from_json(Obj, "configuration", configuration);
 | 
				
			||||||
			field_from_json(Obj, "configuration", Configuration);
 | 
								field_from_json(Obj, "name", name);
 | 
				
			||||||
			field_from_json(Obj, "modelIds", Models);
 | 
								field_from_json(Obj, "modelIds", models);
 | 
				
			||||||
			field_from_json(Obj, "description", Description);
 | 
								field_from_json(Obj, "description", description);
 | 
				
			||||||
 | 
								field_from_json(Obj, "created", created);
 | 
				
			||||||
 | 
								field_from_json(Obj, "lastModified", lastModified);
 | 
				
			||||||
 | 
								field_from_json(Obj, "platform", platform);
 | 
				
			||||||
			return true;
 | 
								return true;
 | 
				
			||||||
		} catch (const Poco::Exception &E) {
 | 
							} catch (const Poco::Exception &E) {
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
@@ -275,14 +297,13 @@ namespace OpenWifi::GWObjects {
 | 
				
			|||||||
		field_to_json(Obj, "connectionCompletionTime", connectionCompletionTime);
 | 
							field_to_json(Obj, "connectionCompletionTime", connectionCompletionTime);
 | 
				
			||||||
		field_to_json(Obj, "totalConnectionTime", Utils::Now() - started);
 | 
							field_to_json(Obj, "totalConnectionTime", Utils::Now() - started);
 | 
				
			||||||
		field_to_json(Obj, "certificateExpiryDate", certificateExpiryDate);
 | 
							field_to_json(Obj, "certificateExpiryDate", certificateExpiryDate);
 | 
				
			||||||
 | 
							field_to_json(Obj, "certificateIssuerName", certificateIssuerName);
 | 
				
			||||||
		field_to_json(Obj, "connectReason", connectReason);
 | 
							field_to_json(Obj, "connectReason", connectReason);
 | 
				
			||||||
 | 
							field_to_json(Obj, "uptime", uptime);
 | 
				
			||||||
 | 
					        field_to_json(Obj, "compatible", Compatible);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef TIP_GATEWAY_SERVICE
 | 
					#ifdef TIP_GATEWAY_SERVICE
 | 
				
			||||||
		hasRADIUSSessions = RADIUSSessionTracker()->HasSessions(SerialNumber);
 | 
							hasRADIUSSessions = RADIUSSessionTracker()->HasSessions(SerialNumber);
 | 
				
			||||||
		AP_WS_Server()->ExtendedAttributes(SerialNumber, hasGPS, sanity,
 | 
					 | 
				
			||||||
										   memoryUsed,
 | 
					 | 
				
			||||||
										   load,
 | 
					 | 
				
			||||||
										   temperature);
 | 
					 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
		field_to_json(Obj, "hasRADIUSSessions", hasRADIUSSessions );
 | 
							field_to_json(Obj, "hasRADIUSSessions", hasRADIUSSessions );
 | 
				
			||||||
		field_to_json(Obj, "hasGPS", hasGPS);
 | 
							field_to_json(Obj, "hasGPS", hasGPS);
 | 
				
			||||||
@@ -314,6 +335,46 @@ namespace OpenWifi::GWObjects {
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    bool ConnectionState::from_json(const Poco::JSON::Object::Ptr &Obj) {
 | 
				
			||||||
 | 
					        try {
 | 
				
			||||||
 | 
					            field_from_json(Obj, "compatible", Compatible);
 | 
				
			||||||
 | 
					            field_from_json(Obj, "ipAddress", Address);
 | 
				
			||||||
 | 
					            field_from_json(Obj, "txBytes", TX);
 | 
				
			||||||
 | 
					            field_from_json(Obj, "rxBytes", RX);
 | 
				
			||||||
 | 
					            field_from_json(Obj, "messageCount", MessageCount);
 | 
				
			||||||
 | 
					            field_from_json(Obj, "UUID", UUID);
 | 
				
			||||||
 | 
					            field_from_json(Obj, "connected", Connected);
 | 
				
			||||||
 | 
					            field_from_json(Obj, "firmware", Firmware);
 | 
				
			||||||
 | 
					            field_from_json(Obj, "lastContact", LastContact);
 | 
				
			||||||
 | 
					            field_from_json(Obj, "associations_2G", Associations_2G);
 | 
				
			||||||
 | 
					            field_from_json(Obj, "associations_5G", Associations_5G);
 | 
				
			||||||
 | 
					            field_from_json(Obj, "associations_6G", Associations_6G);
 | 
				
			||||||
 | 
					            field_from_json(Obj, "webSocketClients", webSocketClients);
 | 
				
			||||||
 | 
					            field_from_json(Obj, "websocketPackets", websocketPackets);
 | 
				
			||||||
 | 
					            field_from_json(Obj, "kafkaClients", kafkaClients);
 | 
				
			||||||
 | 
					            field_from_json(Obj, "kafkaPackets", kafkaPackets);
 | 
				
			||||||
 | 
					            field_from_json(Obj, "locale", locale);
 | 
				
			||||||
 | 
					            field_from_json(Obj, "started", started);
 | 
				
			||||||
 | 
					            field_from_json(Obj, "sessionId", sessionId);
 | 
				
			||||||
 | 
					            field_from_json(Obj, "connectionCompletionTime", connectionCompletionTime);
 | 
				
			||||||
 | 
					            field_from_json(Obj, "totalConnectionTime", totalConnectionTime);
 | 
				
			||||||
 | 
					            field_from_json(Obj, "certificateExpiryDate", certificateExpiryDate);
 | 
				
			||||||
 | 
								field_from_json(Obj, "certificateIssuerName", certificateIssuerName);
 | 
				
			||||||
 | 
					            field_from_json(Obj, "connectReason", connectReason);
 | 
				
			||||||
 | 
					            field_from_json(Obj, "uptime", uptime);
 | 
				
			||||||
 | 
					            field_from_json(Obj, "hasRADIUSSessions", hasRADIUSSessions );
 | 
				
			||||||
 | 
					            field_from_json(Obj, "hasGPS", hasGPS);
 | 
				
			||||||
 | 
					            field_from_json(Obj, "sanity", sanity);
 | 
				
			||||||
 | 
					            field_from_json(Obj, "memoryUsed", memoryUsed);
 | 
				
			||||||
 | 
					            field_from_json(Obj, "sanity", sanity);
 | 
				
			||||||
 | 
					            field_from_json(Obj, "load", load);
 | 
				
			||||||
 | 
					            field_from_json(Obj, "temperature", temperature);
 | 
				
			||||||
 | 
					            return true;
 | 
				
			||||||
 | 
					        } catch(const Poco::Exception &E) {
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return false;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	void DeviceConnectionStatistics::to_json(Poco::JSON::Object &Obj) const {
 | 
						void DeviceConnectionStatistics::to_json(Poco::JSON::Object &Obj) const {
 | 
				
			||||||
		field_to_json(Obj, "averageConnectionTime", averageConnectionTime);
 | 
							field_to_json(Obj, "averageConnectionTime", averageConnectionTime);
 | 
				
			||||||
		field_to_json(Obj, "connectedDevices", connectedDevices);
 | 
							field_to_json(Obj, "connectedDevices", connectedDevices);
 | 
				
			||||||
@@ -711,7 +772,7 @@ namespace OpenWifi::GWObjects {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	bool DeviceCertificateUpdateRequest::from_json(const Poco::JSON::Object::Ptr &Obj) {
 | 
						bool DeviceCertificateUpdateRequest::from_json(const Poco::JSON::Object::Ptr &Obj) {
 | 
				
			||||||
		try {
 | 
							try {
 | 
				
			||||||
			field_from_json(Obj, "serialNumber", serialNumber);
 | 
								field_from_json(Obj, "serial", serialNumber);
 | 
				
			||||||
			field_from_json(Obj, "encodedCertificate", encodedCertificate);
 | 
								field_from_json(Obj, "encodedCertificate", encodedCertificate);
 | 
				
			||||||
			return true;
 | 
								return true;
 | 
				
			||||||
		} catch (const Poco::Exception &E) {
 | 
							} catch (const Poco::Exception &E) {
 | 
				
			||||||
@@ -719,4 +780,55 @@ namespace OpenWifi::GWObjects {
 | 
				
			|||||||
		return false;
 | 
							return false;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						bool PowerCyclePort::from_json(const Poco::JSON::Object::Ptr &Obj) {
 | 
				
			||||||
 | 
							try {
 | 
				
			||||||
 | 
								field_from_json(Obj, "name", name);
 | 
				
			||||||
 | 
								field_from_json(Obj, "cycle", cycle);
 | 
				
			||||||
 | 
								return true;
 | 
				
			||||||
 | 
							} catch (const Poco::Exception &E) {
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return false;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						bool PowerCycleRequest::from_json(const Poco::JSON::Object::Ptr &Obj) {
 | 
				
			||||||
 | 
							try {
 | 
				
			||||||
 | 
								field_from_json(Obj, "serial", serialNumber);
 | 
				
			||||||
 | 
								field_from_json(Obj, "when", when);
 | 
				
			||||||
 | 
								field_from_json(Obj, "ports", ports);
 | 
				
			||||||
 | 
								return true;
 | 
				
			||||||
 | 
							} catch (const Poco::Exception &E) {
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return false;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						bool FixedConfig::from_json(const Poco::JSON::Object::Ptr &Obj) {
 | 
				
			||||||
 | 
							try {
 | 
				
			||||||
 | 
								field_from_json(Obj, "serial", serialNumber);
 | 
				
			||||||
 | 
								field_from_json(Obj, "country", country);
 | 
				
			||||||
 | 
								return true;
 | 
				
			||||||
 | 
							} catch (const Poco::Exception &E) {
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return false;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						bool CableDiagnostics::from_json(const Poco::JSON::Object::Ptr &Obj) {
 | 
				
			||||||
 | 
							try {
 | 
				
			||||||
 | 
								field_from_json(Obj, "serial", serialNumber);
 | 
				
			||||||
 | 
								field_from_json(Obj, "when", when);
 | 
				
			||||||
 | 
								field_from_json(Obj, "ports", ports);
 | 
				
			||||||
 | 
								return true;
 | 
				
			||||||
 | 
							} catch (const Poco::Exception &E) {
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return false;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						bool ReEnroll::from_json(const Poco::JSON::Object::Ptr &Obj) {
 | 
				
			||||||
 | 
							try {
 | 
				
			||||||
 | 
								field_from_json(Obj, "serial", serialNumber);
 | 
				
			||||||
 | 
								field_from_json(Obj, "when", when);
 | 
				
			||||||
 | 
								return true;
 | 
				
			||||||
 | 
							} catch (const Poco::Exception &E) {
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return false;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
} // namespace OpenWifi::GWObjects
 | 
					} // namespace OpenWifi::GWObjects
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -42,6 +42,7 @@ namespace OpenWifi::GWObjects {
 | 
				
			|||||||
		uint64_t sessionId = 0;
 | 
							uint64_t sessionId = 0;
 | 
				
			||||||
		double connectionCompletionTime = 0.0;
 | 
							double connectionCompletionTime = 0.0;
 | 
				
			||||||
		std::uint64_t certificateExpiryDate = 0;
 | 
							std::uint64_t certificateExpiryDate = 0;
 | 
				
			||||||
 | 
							std::string certificateIssuerName;
 | 
				
			||||||
		std::uint64_t hasRADIUSSessions = 0;
 | 
							std::uint64_t hasRADIUSSessions = 0;
 | 
				
			||||||
		bool hasGPS = false;
 | 
							bool hasGPS = false;
 | 
				
			||||||
		std::uint64_t sanity=0;
 | 
							std::uint64_t sanity=0;
 | 
				
			||||||
@@ -49,8 +50,11 @@ namespace OpenWifi::GWObjects {
 | 
				
			|||||||
		std::double_t load=0.0;
 | 
							std::double_t load=0.0;
 | 
				
			||||||
		std::double_t temperature=0.0;
 | 
							std::double_t temperature=0.0;
 | 
				
			||||||
		std::string 	connectReason;
 | 
							std::string 	connectReason;
 | 
				
			||||||
 | 
							std::uint64_t 	uptime=0;
 | 
				
			||||||
 | 
					        std::uint64_t 	totalConnectionTime=0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		void to_json(const std::string &SerialNumber, Poco::JSON::Object &Obj) ;
 | 
							void to_json(const std::string &SerialNumber, Poco::JSON::Object &Obj) ;
 | 
				
			||||||
 | 
					        bool from_json(const Poco::JSON::Object::Ptr &Obj);
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	struct DeviceRestrictionsKeyInfo {
 | 
						struct DeviceRestrictionsKeyInfo {
 | 
				
			||||||
@@ -112,6 +116,7 @@ namespace OpenWifi::GWObjects {
 | 
				
			|||||||
		std::uint64_t 	lastRecordedContact=0;
 | 
							std::uint64_t 	lastRecordedContact=0;
 | 
				
			||||||
		std::uint64_t 	certificateExpiryDate = 0;
 | 
							std::uint64_t 	certificateExpiryDate = 0;
 | 
				
			||||||
		std::string 	connectReason;
 | 
							std::string 	connectReason;
 | 
				
			||||||
 | 
							bool			blackListed=false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		void to_json(Poco::JSON::Object &Obj) const;
 | 
							void to_json(Poco::JSON::Object &Obj) const;
 | 
				
			||||||
		void to_json_with_status(Poco::JSON::Object &Obj) const;
 | 
							void to_json_with_status(Poco::JSON::Object &Obj) const;
 | 
				
			||||||
@@ -137,13 +142,15 @@ namespace OpenWifi::GWObjects {
 | 
				
			|||||||
	};
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	struct HealthCheck {
 | 
						struct HealthCheck {
 | 
				
			||||||
		std::string SerialNumber;
 | 
					        std::string SerialNumber;
 | 
				
			||||||
		uint64_t UUID = 0;
 | 
					        uint64_t UUID = 0;
 | 
				
			||||||
		std::string Data;
 | 
					        std::string Data;
 | 
				
			||||||
		uint64_t Recorded = 0;
 | 
					        uint64_t Recorded = 0;
 | 
				
			||||||
		uint64_t Sanity = 0;
 | 
					        uint64_t Sanity = 0;
 | 
				
			||||||
		void to_json(Poco::JSON::Object &Obj) const;
 | 
					
 | 
				
			||||||
	};
 | 
					        void to_json(Poco::JSON::Object &Obj) const;
 | 
				
			||||||
 | 
					        bool from_json(const Poco::JSON::Object::Ptr &Obj);
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	struct Capabilities {
 | 
						struct Capabilities {
 | 
				
			||||||
		std::string Capabilities;
 | 
							std::string Capabilities;
 | 
				
			||||||
@@ -174,12 +181,13 @@ namespace OpenWifi::GWObjects {
 | 
				
			|||||||
	};
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	struct DefaultConfiguration {
 | 
						struct DefaultConfiguration {
 | 
				
			||||||
		std::string Name;
 | 
							std::string name;
 | 
				
			||||||
		std::string Configuration;
 | 
							std::string configuration;
 | 
				
			||||||
		Types::StringVec Models;
 | 
							Types::StringVec models;
 | 
				
			||||||
		std::string Description;
 | 
							std::string description;
 | 
				
			||||||
		uint64_t Created;
 | 
							uint64_t created;
 | 
				
			||||||
		uint64_t LastModified;
 | 
							uint64_t lastModified;
 | 
				
			||||||
 | 
							std::string platform;
 | 
				
			||||||
		void to_json(Poco::JSON::Object &Obj) const;
 | 
							void to_json(Poco::JSON::Object &Obj) const;
 | 
				
			||||||
		bool from_json(const Poco::JSON::Object::Ptr &Obj);
 | 
							bool from_json(const Poco::JSON::Object::Ptr &Obj);
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
@@ -513,4 +521,37 @@ namespace OpenWifi::GWObjects {
 | 
				
			|||||||
		bool from_json(const Poco::JSON::Object::Ptr &Obj);
 | 
							bool from_json(const Poco::JSON::Object::Ptr &Obj);
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						struct PowerCyclePort {
 | 
				
			||||||
 | 
							std::string 	name;
 | 
				
			||||||
 | 
							std::uint64_t 	cycle=10000;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							bool from_json(const Poco::JSON::Object::Ptr &Obj);
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						struct PowerCycleRequest {
 | 
				
			||||||
 | 
							std::string 	serialNumber;
 | 
				
			||||||
 | 
							std::uint64_t 	when;
 | 
				
			||||||
 | 
							std::vector<PowerCyclePort> ports;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							bool from_json(const Poco::JSON::Object::Ptr &Obj);
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
						struct FixedConfig {
 | 
				
			||||||
 | 
							std::string 	serialNumber;
 | 
				
			||||||
 | 
							std::string 	country;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							bool from_json(const Poco::JSON::Object::Ptr &Obj);
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
						struct CableDiagnostics {
 | 
				
			||||||
 | 
							std::string 	serialNumber;
 | 
				
			||||||
 | 
							std::uint64_t 	when;
 | 
				
			||||||
 | 
							std::vector<std::string> ports;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							bool from_json(const Poco::JSON::Object::Ptr &Obj);
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
						struct ReEnroll {
 | 
				
			||||||
 | 
							std::string 	serialNumber;
 | 
				
			||||||
 | 
							std::uint64_t 	when;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							bool from_json(const Poco::JSON::Object::Ptr &Obj);
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
} // namespace OpenWifi::GWObjects
 | 
					} // namespace OpenWifi::GWObjects
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -587,6 +587,9 @@ namespace OpenWifi::ProvObjects {
 | 
				
			|||||||
		field_to_json(Obj, "locale", locale);
 | 
							field_to_json(Obj, "locale", locale);
 | 
				
			||||||
		field_to_json(Obj, "realMacAddress", realMacAddress);
 | 
							field_to_json(Obj, "realMacAddress", realMacAddress);
 | 
				
			||||||
		field_to_json(Obj, "doNotAllowOverrides", doNotAllowOverrides);
 | 
							field_to_json(Obj, "doNotAllowOverrides", doNotAllowOverrides);
 | 
				
			||||||
 | 
					        field_to_json(Obj, "imported", imported);
 | 
				
			||||||
 | 
					        field_to_json(Obj, "connected", connected);
 | 
				
			||||||
 | 
					        field_to_json(Obj, "platform", platform);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	bool InventoryTag::from_json(const Poco::JSON::Object::Ptr &Obj) {
 | 
						bool InventoryTag::from_json(const Poco::JSON::Object::Ptr &Obj) {
 | 
				
			||||||
@@ -609,6 +612,9 @@ namespace OpenWifi::ProvObjects {
 | 
				
			|||||||
			field_from_json(Obj, "locale", locale);
 | 
								field_from_json(Obj, "locale", locale);
 | 
				
			||||||
			field_from_json(Obj, "realMacAddress", realMacAddress);
 | 
								field_from_json(Obj, "realMacAddress", realMacAddress);
 | 
				
			||||||
			field_from_json(Obj, "doNotAllowOverrides", doNotAllowOverrides);
 | 
								field_from_json(Obj, "doNotAllowOverrides", doNotAllowOverrides);
 | 
				
			||||||
 | 
					            field_from_json(Obj, "imported", imported);
 | 
				
			||||||
 | 
					            field_from_json(Obj, "connected", connected);
 | 
				
			||||||
 | 
					            field_from_json(Obj, "platform", platform);
 | 
				
			||||||
			return true;
 | 
								return true;
 | 
				
			||||||
		} catch (...) {
 | 
							} catch (...) {
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -490,9 +490,11 @@ namespace OpenWifi::ProvObjects {
 | 
				
			|||||||
        std::string locale;
 | 
					        std::string locale;
 | 
				
			||||||
        std::string realMacAddress;
 | 
					        std::string realMacAddress;
 | 
				
			||||||
        bool doNotAllowOverrides = false;
 | 
					        bool doNotAllowOverrides = false;
 | 
				
			||||||
 | 
					        std::uint64_t imported=0;
 | 
				
			||||||
 | 
					        std::uint64_t connected=0;
 | 
				
			||||||
 | 
					        std::string platform{Platforms::AP};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        void to_json(Poco::JSON::Object &Obj) const;
 | 
					        void to_json(Poco::JSON::Object &Obj) const;
 | 
				
			||||||
 | 
					 | 
				
			||||||
        bool from_json(const Poco::JSON::Object::Ptr &Obj);
 | 
					        bool from_json(const Poco::JSON::Object::Ptr &Obj);
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -24,7 +24,7 @@ namespace OpenWifi::StateUtils {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	bool ComputeAssociations(const Poco::JSON::Object::Ptr RawObject, uint64_t &Radios_2G,
 | 
						bool ComputeAssociations(const Poco::JSON::Object::Ptr RawObject, uint64_t &Radios_2G,
 | 
				
			||||||
							 uint64_t &Radios_5G, uint64_t &Radios_6G) {
 | 
												 uint64_t &Radios_5G, uint64_t &Radios_6G, uint64_t &UpTime	) {
 | 
				
			||||||
		Radios_2G = 0;
 | 
							Radios_2G = 0;
 | 
				
			||||||
		Radios_5G = 0;
 | 
							Radios_5G = 0;
 | 
				
			||||||
		Radios_6G = 0;
 | 
							Radios_6G = 0;
 | 
				
			||||||
@@ -90,9 +90,15 @@ namespace OpenWifi::StateUtils {
 | 
				
			|||||||
					}
 | 
										}
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			//			std::cout << Radios_2G << " " << Radios_5G << " " << Radios_6G << std::endl;
 | 
					 | 
				
			||||||
			return true;
 | 
								return true;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if(RawObject->has("unit") && !RawObject->isNull("unit") && RawObject->isObject("unit")) {
 | 
				
			||||||
 | 
								auto unit = RawObject->getObject("unit");
 | 
				
			||||||
 | 
								if(unit->has("uptime")) {
 | 
				
			||||||
 | 
									UpTime = unit->get("uptime");
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
		return false;
 | 
							return false;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
} // namespace OpenWifi::StateUtils
 | 
					} // namespace OpenWifi::StateUtils
 | 
				
			||||||
@@ -8,5 +8,5 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
namespace OpenWifi::StateUtils {
 | 
					namespace OpenWifi::StateUtils {
 | 
				
			||||||
	bool ComputeAssociations(const Poco::JSON::Object::Ptr RawObject, uint64_t &Radios_2G,
 | 
						bool ComputeAssociations(const Poco::JSON::Object::Ptr RawObject, uint64_t &Radios_2G,
 | 
				
			||||||
							 uint64_t &Radios_5G, uint64_t &Radio_6G);
 | 
												 uint64_t &Radios_5G, uint64_t &Radio_6G, uint64_t &UpTime);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -22,6 +22,8 @@ namespace OpenWifi {
 | 
				
			|||||||
		ScriptDB_->Create();
 | 
							ScriptDB_->Create();
 | 
				
			||||||
		ScriptDB_->Initialize();
 | 
							ScriptDB_->Initialize();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							FixDeviceTypeBug();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		return 0;
 | 
							return 0;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -143,26 +143,31 @@ namespace OpenWifi {
 | 
				
			|||||||
								 bool simulated);
 | 
													 bool simulated);
 | 
				
			||||||
		bool CreateDevice(Poco::Data::Session &Sess, GWObjects::Device &DeviceDetails);
 | 
							bool CreateDevice(Poco::Data::Session &Sess, GWObjects::Device &DeviceDetails);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		bool GetDevice(LockedDbSession &Session, std::string &SerialNumber, GWObjects::Device &);
 | 
							bool GetDevice(LockedDbSession &Session, const std::string &SerialNumber, GWObjects::Device &);
 | 
				
			||||||
		bool GetDevice(Poco::Data::Session &Session, std::string &SerialNumber, GWObjects::Device &DeviceDetails);
 | 
							bool GetDevice(Poco::Data::Session &Session, const std::string &SerialNumber, GWObjects::Device &DeviceDetails);
 | 
				
			||||||
		bool GetDevice(std::string &SerialNumber, GWObjects::Device &);
 | 
							bool GetDevice(const 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 = "",
 | 
				
			||||||
 | 
											const std::string &platform = "",
 | 
				
			||||||
 | 
											bool includeProvisioned = true);
 | 
				
			||||||
		//		bool GetDevices(uint64_t From, uint64_t HowMany, const std::string & Select,
 | 
							//		bool GetDevices(uint64_t From, uint64_t HowMany, const std::string & Select,
 | 
				
			||||||
		// std::vector<GWObjects::Device> &Devices, const std::string & orderBy="");
 | 
							// std::vector<GWObjects::Device> &Devices, const std::string & orderBy="");
 | 
				
			||||||
		bool DeleteDevice(std::string &SerialNumber);
 | 
							bool DeleteDevice(std::string &SerialNumber);
 | 
				
			||||||
		bool DeleteDevices(std::string &SerialPattern, bool SimulatedOnly);
 | 
							bool DeleteDevices(std::string &SerialPattern, bool SimulatedOnly);
 | 
				
			||||||
		bool DeleteDevices(std::uint64_t OlderContact, bool SimulatedOnly);
 | 
							bool DeleteDevices(std::uint64_t OlderContact, bool SimulatedOnly);
 | 
				
			||||||
 | 
							std::string GetPlatform(const std::string &SerialNumber);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		bool UpdateDevice(GWObjects::Device &);
 | 
							bool UpdateDevice(GWObjects::Device &);
 | 
				
			||||||
		bool UpdateDevice(LockedDbSession &Session, GWObjects::Device &);
 | 
							bool UpdateDevice(LockedDbSession &Session, GWObjects::Device &);
 | 
				
			||||||
		bool UpdateDevice(Poco::Data::Session &Sess, GWObjects::Device &NewDeviceDetails);
 | 
							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, const std::string &platform = "");
 | 
				
			||||||
		bool GetDeviceSerialNumbers(uint64_t From, uint64_t HowMany,
 | 
							bool GetDeviceSerialNumbers(uint64_t From, uint64_t HowMany,
 | 
				
			||||||
									std::vector<std::string> &SerialNumbers,
 | 
														std::vector<std::string> &SerialNumbers,
 | 
				
			||||||
									const std::string &orderBy = "");
 | 
														const std::string &orderBy = "",
 | 
				
			||||||
 | 
														const std::string &platform = "",
 | 
				
			||||||
 | 
														bool includeProvisioned = true);									
 | 
				
			||||||
		bool GetDeviceFWUpdatePolicy(std::string &SerialNumber, std::string &Policy);
 | 
							bool GetDeviceFWUpdatePolicy(std::string &SerialNumber, std::string &Policy);
 | 
				
			||||||
		bool SetDevicePassword(LockedDbSession &Session, std::string &SerialNumber, std::string &Password);
 | 
							bool SetDevicePassword(LockedDbSession &Session, std::string &SerialNumber, std::string &Password);
 | 
				
			||||||
		bool UpdateSerialNumberCache();
 | 
							bool UpdateSerialNumberCache();
 | 
				
			||||||
@@ -198,6 +203,7 @@ namespace OpenWifi {
 | 
				
			|||||||
		bool GetDefaultConfigurations(uint64_t From, uint64_t HowMany,
 | 
							bool GetDefaultConfigurations(uint64_t From, uint64_t HowMany,
 | 
				
			||||||
									  std::vector<GWObjects::DefaultConfiguration> &Devices);
 | 
														  std::vector<GWObjects::DefaultConfiguration> &Devices);
 | 
				
			||||||
		bool FindDefaultConfigurationForModel(const std::string &Model,
 | 
							bool FindDefaultConfigurationForModel(const std::string &Model,
 | 
				
			||||||
 | 
																  const std::string &Platform,
 | 
				
			||||||
											  GWObjects::DefaultConfiguration &DefConfig);
 | 
																  GWObjects::DefaultConfiguration &DefConfig);
 | 
				
			||||||
		uint64_t GetDefaultConfigurationsCount();
 | 
							uint64_t GetDefaultConfigurationsCount();
 | 
				
			||||||
		bool DefaultConfigurationAlreadyExists(std::string &Name);
 | 
							bool DefaultConfigurationAlreadyExists(std::string &Name);
 | 
				
			||||||
@@ -237,7 +243,7 @@ namespace OpenWifi {
 | 
				
			|||||||
									 const std::string &Type);
 | 
														 const std::string &Type);
 | 
				
			||||||
		bool CancelWaitFile(std::string &UUID, std::string &ErrorText);
 | 
							bool CancelWaitFile(std::string &UUID, std::string &ErrorText);
 | 
				
			||||||
		bool GetAttachedFileContent(std::string &UUID, const std::string &SerialNumber,
 | 
							bool GetAttachedFileContent(std::string &UUID, const std::string &SerialNumber,
 | 
				
			||||||
									std::string &FileContent, std::string &Type);
 | 
														std::string &FileContent, std::string &Type, int& WaitingForFile);
 | 
				
			||||||
		bool RemoveAttachedFile(std::string &UUID);
 | 
							bool RemoveAttachedFile(std::string &UUID);
 | 
				
			||||||
		bool SetCommandResult(std::string &UUID, std::string &Result);
 | 
							bool SetCommandResult(std::string &UUID, std::string &Result);
 | 
				
			||||||
		bool GetNewestCommands(std::string &SerialNumber, uint64_t HowMany,
 | 
							bool GetNewestCommands(std::string &SerialNumber, uint64_t HowMany,
 | 
				
			||||||
@@ -291,6 +297,8 @@ namespace OpenWifi {
 | 
				
			|||||||
		bool AnalyzeCommands(Types::CountedMap &R);
 | 
							bool AnalyzeCommands(Types::CountedMap &R);
 | 
				
			||||||
		bool AnalyzeDevices(GWObjects::Dashboard &D);
 | 
							bool AnalyzeDevices(GWObjects::Dashboard &D);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							void FixDeviceTypeBug();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		int Start() override;
 | 
							int Start() override;
 | 
				
			||||||
		void Stop() override;
 | 
							void Stop() override;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -111,7 +111,6 @@ namespace OpenWifi {
 | 
				
			|||||||
					}
 | 
										}
 | 
				
			||||||
				} break;
 | 
									} break;
 | 
				
			||||||
				case TelemetryNotification::NotificationType::unregister: {
 | 
									case TelemetryNotification::NotificationType::unregister: {
 | 
				
			||||||
					std::lock_guard G(Mutex_);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
					auto client = Clients_.find(Notification->Data_);
 | 
										auto client = Clients_.find(Notification->Data_);
 | 
				
			||||||
					if (client != Clients_.end()) {
 | 
										if (client != Clients_.end()) {
 | 
				
			||||||
 
 | 
				
			|||||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@@ -5,7 +5,7 @@
 | 
				
			|||||||
#pragma once
 | 
					#pragma once
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "framework/SubSystemServer.h"
 | 
					#include "framework/SubSystemServer.h"
 | 
				
			||||||
 | 
					#include "framework/ow_constants.h"
 | 
				
			||||||
#include <valijson/adapters/poco_json_adapter.hpp>
 | 
					#include <valijson/adapters/poco_json_adapter.hpp>
 | 
				
			||||||
#include <valijson/constraints/constraint.hpp>
 | 
					#include <valijson/constraints/constraint.hpp>
 | 
				
			||||||
#include <valijson/constraints/constraint_visitor.hpp>
 | 
					#include <valijson/constraints/constraint_visitor.hpp>
 | 
				
			||||||
@@ -17,33 +17,42 @@
 | 
				
			|||||||
namespace OpenWifi {
 | 
					namespace OpenWifi {
 | 
				
			||||||
	class ConfigurationValidator : public SubSystemServer {
 | 
						class ConfigurationValidator : public SubSystemServer {
 | 
				
			||||||
	  public:
 | 
						  public:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							enum class ConfigurationType { AP = 0 , SWITCH = 1};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		static auto instance() {
 | 
							static auto instance() {
 | 
				
			||||||
			static auto instance_ = new ConfigurationValidator;
 | 
								static auto instance_ = new ConfigurationValidator;
 | 
				
			||||||
			return instance_;
 | 
								return instance_;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		bool Validate(const std::string &C, std::vector<std::string> &Errors, bool Strict);
 | 
							bool Validate(ConfigurationType Type, const std::string &C, std::string &Errors, bool Strict);
 | 
				
			||||||
		int Start() override;
 | 
							int Start() override;
 | 
				
			||||||
		void Stop() override;
 | 
							void Stop() override;
 | 
				
			||||||
		void reinitialize(Poco::Util::Application &self) override;
 | 
							void reinitialize(Poco::Util::Application &self) override;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							inline static ConfigurationType GetType(const std::string &type) {
 | 
				
			||||||
 | 
					                       std::string Type = Poco::toLower(type);
 | 
				
			||||||
 | 
								if (Type == Platforms::AP)
 | 
				
			||||||
 | 
									return ConfigurationType::AP;
 | 
				
			||||||
 | 
								if (Type == Platforms::SWITCH)
 | 
				
			||||||
 | 
									return ConfigurationType::SWITCH;
 | 
				
			||||||
 | 
								return ConfigurationType::AP;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	  private:
 | 
						  private:
 | 
				
			||||||
		bool Initialized_ = false;
 | 
							bool Initialized_ = false;
 | 
				
			||||||
		bool Working_ = false;
 | 
							bool Working_ = false;
 | 
				
			||||||
		void Init();
 | 
							void Init();
 | 
				
			||||||
		std::unique_ptr<valijson::Schema> RootSchema_;
 | 
							std::array<valijson::Schema,2> 			RootSchema_;
 | 
				
			||||||
		std::unique_ptr<valijson::SchemaParser> SchemaParser_;
 | 
							bool SetSchema(ConfigurationType Type, const std::string &SchemaStr);
 | 
				
			||||||
		std::unique_ptr<valijson::adapters::PocoJsonAdapter> PocoJsonAdapter_;
 | 
					 | 
				
			||||||
		Poco::JSON::Object::Ptr SchemaDocPtr_;
 | 
					 | 
				
			||||||
		bool SetSchema(const std::string &SchemaStr);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		ConfigurationValidator()
 | 
							ConfigurationValidator()
 | 
				
			||||||
			: SubSystemServer("ConfigValidator", "CFG-VALIDATOR", "config.validator") {}
 | 
								: SubSystemServer("ConfigValidator", "CFG-VALIDATOR", "config.validator") {}
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	inline auto ConfigurationValidator() { return ConfigurationValidator::instance(); }
 | 
						inline auto ConfigurationValidator() { return ConfigurationValidator::instance(); }
 | 
				
			||||||
	inline bool ValidateUCentralConfiguration(const std::string &C, std::vector<std::string> &Error,
 | 
						inline bool ValidateUCentralConfiguration(ConfigurationValidator::ConfigurationType Type, const std::string &C, std::string &Errors,
 | 
				
			||||||
											  bool strict) {
 | 
																  bool strict) {
 | 
				
			||||||
		return ConfigurationValidator::instance()->Validate(C, Error, strict);
 | 
							return ConfigurationValidator::instance()->Validate(Type, C, Errors, strict);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
} // namespace OpenWifi
 | 
					} // namespace OpenWifi
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -16,9 +16,9 @@ namespace OpenWifi {
 | 
				
			|||||||
		KafkaManager()->PostMessage(KafkaTopics::SERVICE_EVENTS, MicroServicePrivateEndPoint(), Msg,
 | 
							KafkaManager()->PostMessage(KafkaTopics::SERVICE_EVENTS, MicroServicePrivateEndPoint(), Msg,
 | 
				
			||||||
									false);
 | 
														false);
 | 
				
			||||||
		while (Running_) {
 | 
							while (Running_) {
 | 
				
			||||||
			Poco::Thread::trySleep((unsigned long)MicroServiceDaemonBusTimer());
 | 
								if(!Poco::Thread::trySleep((unsigned long)MicroServiceDaemonBusTimer())) {
 | 
				
			||||||
			if (!Running_)
 | 
					                break;
 | 
				
			||||||
				break;
 | 
					            }
 | 
				
			||||||
			Msg = (MicroServiceMakeSystemEventMessage(KafkaTopics::ServiceEvents::EVENT_KEEP_ALIVE));
 | 
								Msg = (MicroServiceMakeSystemEventMessage(KafkaTopics::ServiceEvents::EVENT_KEEP_ALIVE));
 | 
				
			||||||
			KafkaManager()->PostMessage(KafkaTopics::SERVICE_EVENTS, MicroServicePrivateEndPoint(),
 | 
								KafkaManager()->PostMessage(KafkaTopics::SERVICE_EVENTS, MicroServicePrivateEndPoint(),
 | 
				
			||||||
										Msg, false);
 | 
															Msg, false);
 | 
				
			||||||
@@ -29,7 +29,7 @@ namespace OpenWifi {
 | 
				
			|||||||
	};
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	void EventBusManager::Start() {
 | 
						void EventBusManager::Start() {
 | 
				
			||||||
		poco_information(Logger(), "Starting...");
 | 
							poco_information(Logger_, "Starting...");
 | 
				
			||||||
		if (KafkaManager()->Enabled()) {
 | 
							if (KafkaManager()->Enabled()) {
 | 
				
			||||||
			Thread_.start(*this);
 | 
								Thread_.start(*this);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
@@ -37,11 +37,11 @@ namespace OpenWifi {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	void EventBusManager::Stop() {
 | 
						void EventBusManager::Stop() {
 | 
				
			||||||
		if (KafkaManager()->Enabled()) {
 | 
							if (KafkaManager()->Enabled()) {
 | 
				
			||||||
			poco_information(Logger(), "Stopping...");
 | 
								poco_information(Logger_, "Stopping...");
 | 
				
			||||||
			Running_ = false;
 | 
								Running_ = false;
 | 
				
			||||||
			Thread_.wakeUp();
 | 
								Thread_.wakeUp();
 | 
				
			||||||
			Thread_.join();
 | 
								Thread_.join();
 | 
				
			||||||
			poco_information(Logger(), "Stopped...");
 | 
								poco_information(Logger_, "Stopped...");
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -22,7 +22,6 @@ namespace OpenWifi {
 | 
				
			|||||||
			return instance_;
 | 
								return instance_;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		explicit EventBusManager(Poco::Logger &L);
 | 
					 | 
				
			||||||
		void run() final;
 | 
							void run() final;
 | 
				
			||||||
		void Start();
 | 
							void Start();
 | 
				
			||||||
		void Stop();
 | 
							void Stop();
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -79,8 +79,10 @@ namespace OpenWifi {
 | 
				
			|||||||
		Utils::SetThreadName("Kafka:Prod");
 | 
							Utils::SetThreadName("Kafka:Prod");
 | 
				
			||||||
		cppkafka::Configuration Config(
 | 
							cppkafka::Configuration Config(
 | 
				
			||||||
			{{"client.id", MicroServiceConfigGetString("openwifi.kafka.client.id", "")},
 | 
								{{"client.id", MicroServiceConfigGetString("openwifi.kafka.client.id", "")},
 | 
				
			||||||
			 {"metadata.broker.list",
 | 
								 {"metadata.broker.list",MicroServiceConfigGetString("openwifi.kafka.brokerlist", "")} // ,
 | 
				
			||||||
			  MicroServiceConfigGetString("openwifi.kafka.brokerlist", "")}});
 | 
								 // {"send.buffer.bytes", KafkaManager()->KafkaManagerMaximumPayloadSize() }
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					 		);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		AddKafkaSecurity(Config);
 | 
							AddKafkaSecurity(Config);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -105,6 +107,19 @@ namespace OpenWifi {
 | 
				
			|||||||
					NewMessage.partition(0);
 | 
										NewMessage.partition(0);
 | 
				
			||||||
					NewMessage.payload(Msg->Payload());
 | 
										NewMessage.payload(Msg->Payload());
 | 
				
			||||||
					Producer.produce(NewMessage);
 | 
										Producer.produce(NewMessage);
 | 
				
			||||||
 | 
										if (Queue_.size() < 100) {
 | 
				
			||||||
 | 
											// use flush when internal queue is lightly loaded, i.e. flush after each
 | 
				
			||||||
 | 
											// message
 | 
				
			||||||
 | 
											Producer.flush();
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
										else {
 | 
				
			||||||
 | 
											// use poll when internal queue is loaded to allow messages to be sent in
 | 
				
			||||||
 | 
											// batches
 | 
				
			||||||
 | 
											Producer.poll((std::chrono::milliseconds) 0);
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									if (Queue_.size() == 0) {
 | 
				
			||||||
 | 
										// message queue is empty, flush all previously sent messages
 | 
				
			||||||
					Producer.flush();
 | 
										Producer.flush();
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			} catch (const cppkafka::HandleException &E) {
 | 
								} catch (const cppkafka::HandleException &E) {
 | 
				
			||||||
@@ -117,6 +132,7 @@ namespace OpenWifi {
 | 
				
			|||||||
			}
 | 
								}
 | 
				
			||||||
			Note = Queue_.waitDequeueNotification();
 | 
								Note = Queue_.waitDequeueNotification();
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
							Producer.flush();
 | 
				
			||||||
		poco_information(Logger_, "Stopped...");
 | 
							poco_information(Logger_, "Stopped...");
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -275,6 +291,7 @@ namespace OpenWifi {
 | 
				
			|||||||
	int KafkaManager::Start() {
 | 
						int KafkaManager::Start() {
 | 
				
			||||||
		if (!KafkaEnabled_)
 | 
							if (!KafkaEnabled_)
 | 
				
			||||||
			return 0;
 | 
								return 0;
 | 
				
			||||||
 | 
							MaxPayloadSize_ = MicroServiceConfigGetInt("openwifi.kafka.max.payload", 250000);
 | 
				
			||||||
		ConsumerThr_.Start();
 | 
							ConsumerThr_.Start();
 | 
				
			||||||
		ProducerThr_.Start();
 | 
							ProducerThr_.Start();
 | 
				
			||||||
		return 0;
 | 
							return 0;
 | 
				
			||||||
@@ -321,4 +338,4 @@ namespace OpenWifi {
 | 
				
			|||||||
											   partitions.front().get_partition()));
 | 
																   partitions.front().get_partition()));
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
} // namespace OpenWifi
 | 
					} // namespace OpenWifi
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -94,11 +94,14 @@ namespace OpenWifi {
 | 
				
			|||||||
			return ConsumerThr_.UnregisterTopicWatcher(Topic,Id);
 | 
								return ConsumerThr_.UnregisterTopicWatcher(Topic,Id);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							std::uint64_t KafkaManagerMaximumPayloadSize() const { return MaxPayloadSize_; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	  private:
 | 
						  private:
 | 
				
			||||||
		bool KafkaEnabled_ = false;
 | 
							bool KafkaEnabled_ = false;
 | 
				
			||||||
		std::string SystemInfoWrapper_;
 | 
							std::string SystemInfoWrapper_;
 | 
				
			||||||
		KafkaProducer ProducerThr_;
 | 
							KafkaProducer ProducerThr_;
 | 
				
			||||||
		KafkaConsumer ConsumerThr_;
 | 
							KafkaConsumer ConsumerThr_;
 | 
				
			||||||
 | 
							std::uint64_t MaxPayloadSize_ = 250000;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		void PartitionAssignment(const cppkafka::TopicPartitionList &partitions);
 | 
							void PartitionAssignment(const cppkafka::TopicPartitionList &partitions);
 | 
				
			||||||
		void PartitionRevocation(const cppkafka::TopicPartitionList &partitions);
 | 
							void PartitionRevocation(const cppkafka::TopicPartitionList &partitions);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,4 +1,5 @@
 | 
				
			|||||||
//
 | 
					//
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
// Created by stephane bourque on 2022-10-26.
 | 
					// Created by stephane bourque on 2022-10-26.
 | 
				
			||||||
//
 | 
					//
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -29,11 +30,13 @@
 | 
				
			|||||||
#include "framework/WebSocketLogger.h"
 | 
					#include "framework/WebSocketLogger.h"
 | 
				
			||||||
#include "framework/utils.h"
 | 
					#include "framework/utils.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef  USE_MEDUSA_CLIENT
 | 
				
			||||||
 | 
					#include <medusa/MedusaClient.h>
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace OpenWifi {
 | 
					namespace OpenWifi {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	void MicroService::Exit(int Reason) { std::exit(Reason); }
 | 
						static std::string MakeServiceListString(const Types::MicroServiceMetaMap &Services) {
 | 
				
			||||||
 | 
					 | 
				
			||||||
    static std::string MakeServiceListString(const Types::MicroServiceMetaMap &Services) {
 | 
					 | 
				
			||||||
        std::string SvcList;
 | 
					        std::string SvcList;
 | 
				
			||||||
        for (const auto &Svc : Services) {
 | 
					        for (const auto &Svc : Services) {
 | 
				
			||||||
            if (SvcList.empty())
 | 
					            if (SvcList.empty())
 | 
				
			||||||
@@ -204,25 +207,29 @@ namespace OpenWifi {
 | 
				
			|||||||
			Res.push_back(ServiceRec);
 | 
								Res.push_back(ServiceRec);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		return Res;
 | 
							return Res;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	void MicroService::LoadConfigurationFile() {
 | 
						void MicroService::LoadConfigurationFile() {
 | 
				
			||||||
		std::string Location = Poco::Environment::get(DAEMON_CONFIG_ENV_VAR, ".");
 | 
					        if(ConfigContent_.empty()) {
 | 
				
			||||||
		ConfigFileName_ =
 | 
					            std::string Location = Poco::Environment::get(DAEMON_CONFIG_ENV_VAR, ".");
 | 
				
			||||||
			ConfigFileName_.empty() ? Location + "/" + DAEMON_PROPERTIES_FILENAME : ConfigFileName_;
 | 
					            ConfigFileName_ =
 | 
				
			||||||
		Poco::Path ConfigFile(ConfigFileName_);
 | 
					                ConfigFileName_.empty() ? Location + "/" + DAEMON_PROPERTIES_FILENAME : ConfigFileName_;
 | 
				
			||||||
 | 
					            Poco::Path ConfigFile(ConfigFileName_);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (!ConfigFile.isFile()) {
 | 
					            if (!ConfigFile.isFile()) {
 | 
				
			||||||
			std::cerr << DAEMON_APP_NAME << ": Configuration " << ConfigFile.toString()
 | 
					                std::cerr << DAEMON_APP_NAME << ": Configuration " << ConfigFile.toString()
 | 
				
			||||||
					  << " does not seem to exist. Please set " + DAEMON_CONFIG_ENV_VAR +
 | 
					                          << " does not seem to exist. Please set " + DAEMON_CONFIG_ENV_VAR +
 | 
				
			||||||
							 " env variable the path of the " + DAEMON_PROPERTIES_FILENAME +
 | 
					                                 " env variable the path of the " + DAEMON_PROPERTIES_FILENAME +
 | 
				
			||||||
							 " file."
 | 
					                                 " file."
 | 
				
			||||||
					  << std::endl;
 | 
					                          << std::endl;
 | 
				
			||||||
			std::exit(Poco::Util::Application::EXIT_CONFIG);
 | 
					                std::exit(Poco::Util::Application::EXIT_CONFIG);
 | 
				
			||||||
		}
 | 
					            }
 | 
				
			||||||
 | 
					            PropConfigurationFile_ = new Poco::Util::PropertyFileConfiguration(ConfigFile.toString());
 | 
				
			||||||
		// 	    loadConfiguration(ConfigFile.toString());
 | 
					        } else {
 | 
				
			||||||
		PropConfigurationFile_ = new Poco::Util::PropertyFileConfiguration(ConfigFile.toString());
 | 
					            std::istringstream is(ConfigContent_);
 | 
				
			||||||
 | 
					            PropConfigurationFile_ = new Poco::Util::PropertyFileConfiguration(is);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
		configPtr()->addWriteable(PropConfigurationFile_, PRIO_DEFAULT);
 | 
							configPtr()->addWriteable(PropConfigurationFile_, PRIO_DEFAULT);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -425,49 +432,69 @@ namespace OpenWifi {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	void DaemonPostInitialization(Poco::Util::Application &self);
 | 
						void DaemonPostInitialization(Poco::Util::Application &self);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	void MicroService::initialize(Poco::Util::Application &self) {
 | 
					    void MicroService::StartEverything(Poco::Util::Application &self) {
 | 
				
			||||||
		// add the default services
 | 
					        LoadConfigurationFile();
 | 
				
			||||||
		LoadConfigurationFile();
 | 
					        InitializeLoggingSystem();
 | 
				
			||||||
		InitializeLoggingSystem();
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		SubSystems_.push_back(KafkaManager());
 | 
					        static bool InitializedBaseService=false;
 | 
				
			||||||
		SubSystems_.push_back(ALBHealthCheckServer());
 | 
					        if(!InitializedBaseService) {
 | 
				
			||||||
		SubSystems_.push_back(RESTAPI_ExtServer());
 | 
					            InitializedBaseService = true;
 | 
				
			||||||
		SubSystems_.push_back(RESTAPI_IntServer());
 | 
					            SubSystems_.push_back(KafkaManager());
 | 
				
			||||||
 | 
					            SubSystems_.push_back(ALBHealthCheckServer());
 | 
				
			||||||
 | 
					            SubSystems_.push_back(RESTAPI_ExtServer());
 | 
				
			||||||
 | 
					            SubSystems_.push_back(RESTAPI_IntServer());
 | 
				
			||||||
#ifndef TIP_SECURITY_SERVICE
 | 
					#ifndef TIP_SECURITY_SERVICE
 | 
				
			||||||
		SubSystems_.push_back(AuthClient());
 | 
					            SubSystems_.push_back(AuthClient());
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
		Poco::Net::initializeSSL();
 | 
					 | 
				
			||||||
		Poco::Net::HTTPStreamFactory::registerFactory();
 | 
					 | 
				
			||||||
		Poco::Net::HTTPSStreamFactory::registerFactory();
 | 
					 | 
				
			||||||
		Poco::Net::FTPStreamFactory::registerFactory();
 | 
					 | 
				
			||||||
		Poco::Net::FTPSStreamFactory::registerFactory();
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		Poco::File DataDir(ConfigPath("openwifi.system.data"));
 | 
					            Poco::Net::initializeSSL();
 | 
				
			||||||
		DataDir_ = DataDir.path();
 | 
					            Poco::Net::HTTPStreamFactory::registerFactory();
 | 
				
			||||||
		if (!DataDir.exists()) {
 | 
					            Poco::Net::HTTPSStreamFactory::registerFactory();
 | 
				
			||||||
			try {
 | 
					            Poco::Net::FTPStreamFactory::registerFactory();
 | 
				
			||||||
				DataDir.createDirectory();
 | 
					            Poco::Net::FTPSStreamFactory::registerFactory();
 | 
				
			||||||
			} catch (const Poco::Exception &E) {
 | 
					        }
 | 
				
			||||||
				Logger_.log(E);
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		WWWAssetsDir_ = ConfigPath("openwifi.restapi.wwwassets", "");
 | 
					 | 
				
			||||||
		if (WWWAssetsDir_.empty())
 | 
					 | 
				
			||||||
			WWWAssetsDir_ = DataDir_;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		LoadMyConfig();
 | 
					        Poco::File DataDir(ConfigPath("openwifi.system.data"));
 | 
				
			||||||
 | 
					        DataDir_ = DataDir.path();
 | 
				
			||||||
 | 
					        if (!DataDir.exists()) {
 | 
				
			||||||
 | 
					            try {
 | 
				
			||||||
 | 
					                DataDir.createDirectory();
 | 
				
			||||||
 | 
					            } catch (const Poco::Exception &E) {
 | 
				
			||||||
 | 
					                Logger_.log(E);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        WWWAssetsDir_ = ConfigPath("openwifi.restapi.wwwassets", "");
 | 
				
			||||||
 | 
					        if (WWWAssetsDir_.empty())
 | 
				
			||||||
 | 
					            WWWAssetsDir_ = DataDir_;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		AllowExternalMicroServices_ = ConfigGetBool("allowexternalmicroservices", true);
 | 
					        LoadMyConfig();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		InitializeSubSystemServers();
 | 
					        AllowExternalMicroServices_ = ConfigGetBool("allowexternalmicroservices", true);
 | 
				
			||||||
		ServerApplication::initialize(self);
 | 
					 | 
				
			||||||
		DaemonPostInitialization(self);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		Types::TopicNotifyFunction F = [this](const std::string &Key, const std::string &Payload) {
 | 
					        InitializeSubSystemServers();
 | 
				
			||||||
			this->BusMessageReceived(Key, Payload);
 | 
					        ServerApplication::initialize(self);
 | 
				
			||||||
		};
 | 
					        DaemonPostInitialization(self);
 | 
				
			||||||
		KafkaManager()->RegisterTopicWatcher(KafkaTopics::SERVICE_EVENTS, F);
 | 
					
 | 
				
			||||||
 | 
					        Types::TopicNotifyFunction F = [this](const std::string &Key, const std::string &Payload) {
 | 
				
			||||||
 | 
					            this->BusMessageReceived(Key, Payload);
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					        KafkaManager()->RegisterTopicWatcher(KafkaTopics::SERVICE_EVENTS, F);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void MicroService::StopEverything([[maybe_unused]] Poco::Util::Application &self) {
 | 
				
			||||||
 | 
					        LoadConfigurationFile();
 | 
				
			||||||
 | 
					        InitializeLoggingSystem();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Types::TopicNotifyFunction F = [this](const std::string &Key, const std::string &Payload) {
 | 
				
			||||||
 | 
					            this->BusMessageReceived(Key, Payload);
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					        KafkaManager()->RegisterTopicWatcher(KafkaTopics::SERVICE_EVENTS, F);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void MicroService::initialize([[maybe_unused]] Poco::Util::Application &self) {
 | 
				
			||||||
 | 
					#ifndef USE_MEDUSA_CLIENT
 | 
				
			||||||
 | 
					        StartEverything(self);
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	void MicroService::uninitialize() {
 | 
						void MicroService::uninitialize() {
 | 
				
			||||||
@@ -753,6 +780,8 @@ namespace OpenWifi {
 | 
				
			|||||||
		MicroServiceErrorHandler ErrorHandler(*this);
 | 
							MicroServiceErrorHandler ErrorHandler(*this);
 | 
				
			||||||
		Poco::ErrorHandler::set(&ErrorHandler);
 | 
							Poco::ErrorHandler::set(&ErrorHandler);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Args_ = args;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (!HelpRequested_) {
 | 
							if (!HelpRequested_) {
 | 
				
			||||||
			SavePID();
 | 
								SavePID();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -768,11 +797,18 @@ namespace OpenWifi {
 | 
				
			|||||||
				poco_information(logger, "Starting as a daemon.");
 | 
									poco_information(logger, "Starting as a daemon.");
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef USE_MEDUSA_CLIENT
 | 
				
			||||||
 | 
					            MedusaClient::instance()->SetSubSystems(SubSystems_);
 | 
				
			||||||
 | 
					            MedusaClient::instance()->Start();
 | 
				
			||||||
 | 
								waitForTerminationRequest();
 | 
				
			||||||
 | 
					            MedusaClient::instance()->Stop();
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
			poco_information(logger, fmt::format("System ID set to {}", ID_));
 | 
								poco_information(logger, fmt::format("System ID set to {}", ID_));
 | 
				
			||||||
			StartSubSystemServers();
 | 
								StartSubSystemServers();
 | 
				
			||||||
			waitForTerminationRequest();
 | 
								waitForTerminationRequest();
 | 
				
			||||||
			StopSubSystemServers();
 | 
								StopSubSystemServers();
 | 
				
			||||||
			logger.notice(fmt::format("Stopped {}...", DAEMON_APP_NAME));
 | 
								logger.notice(fmt::format("Stopped {}...", DAEMON_APP_NAME));
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		return Application::EXIT_OK;
 | 
							return Application::EXIT_OK;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -55,9 +55,6 @@ namespace OpenWifi {
 | 
				
			|||||||
#include "nlohmann/json.hpp"
 | 
					#include "nlohmann/json.hpp"
 | 
				
			||||||
#include "ow_version.h"
 | 
					#include "ow_version.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define _OWDEBUG_ std::cout << __FILE__ << ":" << __LINE__ << std::endl;
 | 
					 | 
				
			||||||
// #define _OWDEBUG_ Logger().debug(Poco::format("%s: %lu",__FILE__,__LINE__));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
namespace OpenWifi {
 | 
					namespace OpenWifi {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	class MicroService : public Poco::Util::ServerApplication {
 | 
						class MicroService : public Poco::Util::ServerApplication {
 | 
				
			||||||
@@ -70,7 +67,6 @@ namespace OpenWifi {
 | 
				
			|||||||
			  SubSystems_(std::move(Subsystems)), Logger_(Poco::Logger::get("FRAMEWORK")) {
 | 
								  SubSystems_(std::move(Subsystems)), Logger_(Poco::Logger::get("FRAMEWORK")) {
 | 
				
			||||||
			instance_ = this;
 | 
								instance_ = this;
 | 
				
			||||||
			RandomEngine_.seed(std::chrono::steady_clock::now().time_since_epoch().count());
 | 
								RandomEngine_.seed(std::chrono::steady_clock::now().time_since_epoch().count());
 | 
				
			||||||
			// Logger_ = Poco::Logger::root().get("BASE-SVC");
 | 
					 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		inline static const char *ExtraConfigurationFilename = "/configuration_override.json";
 | 
							inline static const char *ExtraConfigurationFilename = "/configuration_override.json";
 | 
				
			||||||
@@ -92,7 +88,7 @@ namespace OpenWifi {
 | 
				
			|||||||
		inline uint64_t DaemonBusTimer() const { return DAEMON_BUS_TIMER; };
 | 
							inline uint64_t DaemonBusTimer() const { return DAEMON_BUS_TIMER; };
 | 
				
			||||||
		[[nodiscard]] const std::string &AppName() { return DAEMON_APP_NAME; }
 | 
							[[nodiscard]] const std::string &AppName() { return DAEMON_APP_NAME; }
 | 
				
			||||||
		static inline uint64_t GetPID() { return Poco::Process::id(); };
 | 
							static inline uint64_t GetPID() { return Poco::Process::id(); };
 | 
				
			||||||
		[[nodiscard]] inline const std::string GetPublicAPIEndPoint() {
 | 
							[[nodiscard]] inline std::string GetPublicAPIEndPoint() const {
 | 
				
			||||||
			return MyPublicEndPoint_ + "/api/v1";
 | 
								return MyPublicEndPoint_ + "/api/v1";
 | 
				
			||||||
		};
 | 
							};
 | 
				
			||||||
		[[nodiscard]] inline const std::string &GetUIURI() const { return UIURI_; };
 | 
							[[nodiscard]] inline const std::string &GetUIURI() const { return UIURI_; };
 | 
				
			||||||
@@ -107,7 +103,8 @@ namespace OpenWifi {
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
		static MicroService &instance() { return *instance_; }
 | 
							static MicroService &instance() { return *instance_; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		inline void Exit(int Reason);
 | 
							inline void Exit(int Reason) { std::exit(Reason); }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		void BusMessageReceived(const std::string &Key, const std::string &Payload);
 | 
							void BusMessageReceived(const std::string &Key, const std::string &Payload);
 | 
				
			||||||
		Types::MicroServiceMetaVec GetServices(const std::string &Type);
 | 
							Types::MicroServiceMetaVec GetServices(const std::string &Type);
 | 
				
			||||||
		Types::MicroServiceMetaVec GetServices();
 | 
							Types::MicroServiceMetaVec GetServices();
 | 
				
			||||||
@@ -115,7 +112,9 @@ namespace OpenWifi {
 | 
				
			|||||||
		void Reload();
 | 
							void Reload();
 | 
				
			||||||
		void LoadMyConfig();
 | 
							void LoadMyConfig();
 | 
				
			||||||
		void initialize(Poco::Util::Application &self) override;
 | 
							void initialize(Poco::Util::Application &self) override;
 | 
				
			||||||
		void uninitialize() override;
 | 
					        void StartEverything(Poco::Util::Application &self);
 | 
				
			||||||
 | 
					        void StopEverything(Poco::Util::Application &self);
 | 
				
			||||||
 | 
					        void uninitialize() override;
 | 
				
			||||||
		void reinitialize(Poco::Util::Application &self) override;
 | 
							void reinitialize(Poco::Util::Application &self) override;
 | 
				
			||||||
		void defineOptions(Poco::Util::OptionSet &options) override;
 | 
							void defineOptions(Poco::Util::OptionSet &options) override;
 | 
				
			||||||
		void handleHelp(const std::string &name, const std::string &value);
 | 
							void handleHelp(const std::string &name, const std::string &value);
 | 
				
			||||||
@@ -132,7 +131,7 @@ namespace OpenWifi {
 | 
				
			|||||||
		void Reload(const std::string &Sub);
 | 
							void Reload(const std::string &Sub);
 | 
				
			||||||
		Types::StringVec GetSubSystems() const;
 | 
							Types::StringVec GetSubSystems() const;
 | 
				
			||||||
		Types::StringPairVec GetLogLevels();
 | 
							Types::StringPairVec GetLogLevels();
 | 
				
			||||||
		const Types::StringVec &GetLogLevelNames();
 | 
							static const Types::StringVec &GetLogLevelNames();
 | 
				
			||||||
		uint64_t ConfigGetInt(const std::string &Key, uint64_t Default);
 | 
							uint64_t ConfigGetInt(const std::string &Key, uint64_t Default);
 | 
				
			||||||
		uint64_t ConfigGetInt(const std::string &Key);
 | 
							uint64_t ConfigGetInt(const std::string &Key);
 | 
				
			||||||
		uint64_t ConfigGetBool(const std::string &Key, bool Default);
 | 
							uint64_t ConfigGetBool(const std::string &Key, bool Default);
 | 
				
			||||||
@@ -166,12 +165,25 @@ namespace OpenWifi {
 | 
				
			|||||||
								const std::string &FormatterPattern,
 | 
													const std::string &FormatterPattern,
 | 
				
			||||||
								const std::string &root_env_var);
 | 
													const std::string &root_env_var);
 | 
				
			||||||
		inline bool AllowExternalMicroServices() const { return AllowExternalMicroServices_; }
 | 
							inline bool AllowExternalMicroServices() const { return AllowExternalMicroServices_; }
 | 
				
			||||||
 | 
					        const ArgVec &Args() const { return Args_; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        inline void SetConfigContent(const std::string &Content) { ConfigContent_ = Content; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        inline std::optional<OpenWifi::Types::MicroServiceMeta> GetPrivateEndPointServiceKey( const std::string & ServicePrivateEndPoint ) {
 | 
				
			||||||
 | 
					            std::lock_guard   G(InfraMutex_);
 | 
				
			||||||
 | 
					            auto K = Services_.find(ServicePrivateEndPoint);
 | 
				
			||||||
 | 
					            if(K==end(Services_)) {
 | 
				
			||||||
 | 
					                return std::nullopt;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            return K->second;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	  private:
 | 
						  private:
 | 
				
			||||||
		static MicroService *instance_;
 | 
							static MicroService *instance_;
 | 
				
			||||||
		bool HelpRequested_ = false;
 | 
							bool HelpRequested_ = false;
 | 
				
			||||||
		std::string LogDir_;
 | 
							std::string LogDir_;
 | 
				
			||||||
		std::string ConfigFileName_;
 | 
							std::string ConfigFileName_;
 | 
				
			||||||
 | 
					        std::string ConfigContent_;
 | 
				
			||||||
		uint64_t ID_ = 1;
 | 
							uint64_t ID_ = 1;
 | 
				
			||||||
		Poco::SharedPtr<Poco::Crypto::RSAKey> AppKey_;
 | 
							Poco::SharedPtr<Poco::Crypto::RSAKey> AppKey_;
 | 
				
			||||||
		bool DebugMode_ = false;
 | 
							bool DebugMode_ = false;
 | 
				
			||||||
@@ -201,6 +213,7 @@ 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};
 | 
				
			||||||
 | 
					        ArgVec Args_;
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	inline MicroService *MicroService::instance_ = nullptr;
 | 
						inline MicroService *MicroService::instance_ = nullptr;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -133,4 +133,8 @@ namespace OpenWifi {
 | 
				
			|||||||
		return MicroService::instance().Hash();
 | 
							return MicroService::instance().Hash();
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    std::optional<OpenWifi::Types::MicroServiceMeta> MicroServicePrivateAccessKey(const std::string &servicePrivateEndPoint) {
 | 
				
			||||||
 | 
					        return MicroService::instance().GetPrivateEndPointServiceKey(servicePrivateEndPoint);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
} // namespace OpenWifi
 | 
					} // namespace OpenWifi
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -23,7 +23,9 @@ namespace OpenWifi {
 | 
				
			|||||||
	std::string MicroServiceConfigGetString(const std::string &Key,
 | 
						std::string MicroServiceConfigGetString(const std::string &Key,
 | 
				
			||||||
											const std::string &DefaultValue);
 | 
																const std::string &DefaultValue);
 | 
				
			||||||
	std::string MicroServiceAccessKey();
 | 
						std::string MicroServiceAccessKey();
 | 
				
			||||||
	bool MicroServiceConfigGetBool(const std::string &Key, bool DefaultValue);
 | 
					    std::optional<OpenWifi::Types::MicroServiceMeta> MicroServicePrivateAccessKey(const std::string &servicePrivateEndPoint);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    bool MicroServiceConfigGetBool(const std::string &Key, bool DefaultValue);
 | 
				
			||||||
	std::uint64_t MicroServiceConfigGetInt(const std::string &Key, std::uint64_t DefaultValue);
 | 
						std::uint64_t MicroServiceConfigGetInt(const std::string &Key, std::uint64_t DefaultValue);
 | 
				
			||||||
	std::string MicroServicePrivateEndPoint();
 | 
						std::string MicroServicePrivateEndPoint();
 | 
				
			||||||
	std::uint64_t MicroServiceID();
 | 
						std::uint64_t MicroServiceID();
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -431,6 +431,11 @@ namespace OpenWifi {
 | 
				
			|||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							inline void Accepted() {
 | 
				
			||||||
 | 
								PrepareResponse(Poco::Net::HTTPResponse::HTTP_ACCEPTED);
 | 
				
			||||||
 | 
								Response->send();
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		inline void SendCompressedTarFile(const std::string &FileName, const std::string &Content) {
 | 
							inline void SendCompressedTarFile(const std::string &FileName, const std::string &Content) {
 | 
				
			||||||
			Response->setStatus(Poco::Net::HTTPResponse::HTTPStatus::HTTP_OK);
 | 
								Response->setStatus(Poco::Net::HTTPResponse::HTTPStatus::HTTP_OK);
 | 
				
			||||||
			SetCommonHeaders();
 | 
								SetCommonHeaders();
 | 
				
			||||||
@@ -552,8 +557,8 @@ namespace OpenWifi {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
		inline bool IsAuthorized(bool &Expired, bool &Contacted, bool SubOnly = false);
 | 
							inline bool IsAuthorized(bool &Expired, bool &Contacted, bool SubOnly = false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		inline void ReturnObject(Poco::JSON::Object &Object) {
 | 
							inline void ReturnObject(Poco::JSON::Object &Object, Poco::Net::HTTPResponse::HTTPStatus Status = Poco::Net::HTTPResponse::HTTP_OK) {
 | 
				
			||||||
			PrepareResponse();
 | 
								PrepareResponse(Status);
 | 
				
			||||||
			if (Request != nullptr) {
 | 
								if (Request != nullptr) {
 | 
				
			||||||
				//   can we compress ???
 | 
									//   can we compress ???
 | 
				
			||||||
				auto AcceptedEncoding = Request->find("Accept-Encoding");
 | 
									auto AcceptedEncoding = Request->find("Accept-Encoding");
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -68,6 +68,16 @@ namespace OpenWifi {
 | 
				
			|||||||
				Context->addCertificateAuthority(Issuing);
 | 
									Context->addCertificateAuthority(Issuing);
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if (!client_cas_.empty()) {
 | 
				
			||||||
 | 
									// add certificates specified in clientcas
 | 
				
			||||||
 | 
									std::vector<Poco::Crypto::X509Certificate> Certs =
 | 
				
			||||||
 | 
										Poco::Net::X509Certificate::readPEM(client_cas_);
 | 
				
			||||||
 | 
									for (const auto &cert : Certs) {
 | 
				
			||||||
 | 
										Context->addChainCertificate(cert);
 | 
				
			||||||
 | 
										Context->addCertificateAuthority(cert);
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			Poco::Crypto::RSAKey Key("", key_file_, key_file_password_);
 | 
								Poco::Crypto::RSAKey Key("", key_file_, key_file_password_);
 | 
				
			||||||
			Context->usePrivateKey(Key);
 | 
								Context->usePrivateKey(Key);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -45,6 +45,7 @@ namespace OpenWifi {
 | 
				
			|||||||
		[[nodiscard]] inline auto KeyFile() const { return key_file_; };
 | 
							[[nodiscard]] inline auto KeyFile() const { return key_file_; };
 | 
				
			||||||
		[[nodiscard]] inline auto CertFile() const { return cert_file_; };
 | 
							[[nodiscard]] inline auto CertFile() const { return cert_file_; };
 | 
				
			||||||
		[[nodiscard]] inline auto RootCA() const { return root_ca_; };
 | 
							[[nodiscard]] inline auto RootCA() const { return root_ca_; };
 | 
				
			||||||
 | 
							[[nodiscard]] inline auto ClientCas() const { return client_cas_; };
 | 
				
			||||||
		[[nodiscard]] inline auto KeyFilePassword() const { return key_file_password_; };
 | 
							[[nodiscard]] inline auto KeyFilePassword() const { return key_file_password_; };
 | 
				
			||||||
		[[nodiscard]] inline auto IssuerCertFile() const { return issuer_cert_file_; };
 | 
							[[nodiscard]] inline auto IssuerCertFile() const { return issuer_cert_file_; };
 | 
				
			||||||
		[[nodiscard]] inline auto Name() const { return name_; };
 | 
							[[nodiscard]] inline auto Name() const { return name_; };
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -58,11 +58,9 @@ namespace OpenWifi {
 | 
				
			|||||||
	void UI_WebSocketClientServer::run() {
 | 
						void UI_WebSocketClientServer::run() {
 | 
				
			||||||
		Running_ = true;
 | 
							Running_ = true;
 | 
				
			||||||
		while (Running_) {
 | 
							while (Running_) {
 | 
				
			||||||
			Poco::Thread::trySleep(2000);
 | 
								if(!Poco::Thread::trySleep(2000)) {
 | 
				
			||||||
 | 
					                break;
 | 
				
			||||||
			if (!Running_)
 | 
					            }
 | 
				
			||||||
				break;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			std::lock_guard G(LocalMutex_);
 | 
								std::lock_guard G(LocalMutex_);
 | 
				
			||||||
			for (const auto i : ToBeRemoved_) {
 | 
								for (const auto i : ToBeRemoved_) {
 | 
				
			||||||
				// std::cout << "Erasing old WS UI connection..." << std::endl;
 | 
									// std::cout << "Erasing old WS UI connection..." << std::endl;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -7,57 +7,59 @@
 | 
				
			|||||||
#include <vector>
 | 
					#include <vector>
 | 
				
			||||||
#include <string>
 | 
					#include <string>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "ow_constants.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace OpenWifi {
 | 
					namespace OpenWifi {
 | 
				
			||||||
	inline  const std::vector<std::pair<std::string, std::string>> DefaultDeviceTypeList{
 | 
						inline  const std::vector<std::pair<std::string, std::string>> DefaultDeviceTypeList{
 | 
				
			||||||
		{"actiontec_web7200", "AP"},
 | 
							{"actiontec_web7200", Platforms::AP},
 | 
				
			||||||
		{"cig_wf186w", "AP"},
 | 
							{"cig_wf186w", Platforms::AP},
 | 
				
			||||||
		{"cig_wf188n", "AP"},
 | 
							{"cig_wf188n", Platforms::AP},
 | 
				
			||||||
		{"cig_wf194c4", "AP"},
 | 
							{"cig_wf194c4", Platforms::AP},
 | 
				
			||||||
		{"cig_wf196", "AP"},
 | 
							{"cig_wf196", Platforms::AP},
 | 
				
			||||||
		{"cig_wf196-ca", "AP"},
 | 
							{"cig_wf196-ca", Platforms::AP},
 | 
				
			||||||
		{"cig_wf196-ca-ath12", "AP"},
 | 
							{"cig_wf196-ca-ath12", Platforms::AP},
 | 
				
			||||||
		{"cig_wf196-us", "AP"},
 | 
							{"cig_wf196-us", Platforms::AP},
 | 
				
			||||||
		{"cig_wf610d", "AP"},
 | 
							{"cig_wf610d", Platforms::AP},
 | 
				
			||||||
		{"cig_wf660a", "AP"},
 | 
							{"cig_wf660a", Platforms::AP},
 | 
				
			||||||
		{"cig_wf808", "AP"},
 | 
							{"cig_wf808", Platforms::AP},
 | 
				
			||||||
		{"cybertan_eww622-a1", "AP"},
 | 
							{"cybertan_eww622-a1", Platforms::AP},
 | 
				
			||||||
		{"edgecore_eap101", "AP"},
 | 
							{"edgecore_eap101", Platforms::AP},
 | 
				
			||||||
		{"edgecore_eap101-ath12", "AP"},
 | 
							{"edgecore_eap101-ath12", Platforms::AP},
 | 
				
			||||||
		{"edgecore_eap102", "AP"},
 | 
							{"edgecore_eap102", Platforms::AP},
 | 
				
			||||||
		{"edgecore_eap104", "AP"},
 | 
							{"edgecore_eap104", Platforms::AP},
 | 
				
			||||||
		{"edgecore_eap104-ath12", "AP"},
 | 
							{"edgecore_eap104-ath12", Platforms::AP},
 | 
				
			||||||
		{"edgecore_ecs4100-12ph", "AP"},
 | 
							{"edgecore_ecs4100-12ph", Platforms::AP},
 | 
				
			||||||
		{"edgecore_ecw5211", "AP"},
 | 
							{"edgecore_ecw5211", Platforms::AP},
 | 
				
			||||||
		{"edgecore_ecw5410", "AP"},
 | 
							{"edgecore_ecw5410", Platforms::AP},
 | 
				
			||||||
		{"edgecore_oap100", "AP"},
 | 
							{"edgecore_oap100", Platforms::AP},
 | 
				
			||||||
		{"edgecore_spw2ac1200", "SWITCH"},
 | 
							{"edgecore_spw2ac1200", Platforms::SWITCH},
 | 
				
			||||||
		{"edgecore_spw2ac1200-lan-poe", "SWITCH"},
 | 
							{"edgecore_spw2ac1200-lan-poe", Platforms::SWITCH},
 | 
				
			||||||
		{"edgecore_ssw2ac2600", "SWITCH"},
 | 
							{"edgecore_ssw2ac2600", Platforms::SWITCH},
 | 
				
			||||||
		{"hfcl_ion4", "AP"},
 | 
							{"hfcl_ion4", Platforms::AP},
 | 
				
			||||||
		{"hfcl_ion4x", "AP"},
 | 
							{"hfcl_ion4x", Platforms::AP},
 | 
				
			||||||
		{"hfcl_ion4x_2", "AP"},
 | 
							{"hfcl_ion4x_2", Platforms::AP},
 | 
				
			||||||
		{"hfcl_ion4xe", "AP"},
 | 
							{"hfcl_ion4xe", Platforms::AP},
 | 
				
			||||||
		{"hfcl_ion4xi", "AP"},
 | 
							{"hfcl_ion4xi", Platforms::AP},
 | 
				
			||||||
		{"indio_um-305ac", "AP"},
 | 
							{"indio_um-305ac", Platforms::AP},
 | 
				
			||||||
		{"indio_um-305ax", "AP"},
 | 
							{"indio_um-305ax", Platforms::AP},
 | 
				
			||||||
		{"indio_um-310ax-v1", "AP"},
 | 
							{"indio_um-310ax-v1", Platforms::AP},
 | 
				
			||||||
		{"indio_um-325ac", "AP"},
 | 
							{"indio_um-325ac", Platforms::AP},
 | 
				
			||||||
		{"indio_um-510ac-v3", "AP"},
 | 
							{"indio_um-510ac-v3", Platforms::AP},
 | 
				
			||||||
		{"indio_um-510axm-v1", "AP"},
 | 
							{"indio_um-510axm-v1", Platforms::AP},
 | 
				
			||||||
		{"indio_um-510axp-v1", "AP"},
 | 
							{"indio_um-510axp-v1", Platforms::AP},
 | 
				
			||||||
		{"indio_um-550ac", "AP"},
 | 
							{"indio_um-550ac", Platforms::AP},
 | 
				
			||||||
		{"linksys_e8450-ubi", "AP"},
 | 
							{"linksys_e8450-ubi", Platforms::AP},
 | 
				
			||||||
		{"linksys_ea6350-v4", "AP"},
 | 
							{"linksys_ea6350-v4", Platforms::AP},
 | 
				
			||||||
		{"linksys_ea8300", "AP"},
 | 
							{"linksys_ea8300", Platforms::AP},
 | 
				
			||||||
		{"liteon_wpx8324", "AP"},
 | 
							{"liteon_wpx8324", Platforms::AP},
 | 
				
			||||||
		{"meshpp_s618_cp01", "AP"},
 | 
							{"meshpp_s618_cp01", Platforms::AP},
 | 
				
			||||||
		{"meshpp_s618_cp03", "AP"},
 | 
							{"meshpp_s618_cp03", Platforms::AP},
 | 
				
			||||||
		{"udaya_a5-id2", "AP"},
 | 
							{"udaya_a5-id2", Platforms::AP},
 | 
				
			||||||
		{"wallys_dr40x9", "AP"},
 | 
							{"wallys_dr40x9", Platforms::AP},
 | 
				
			||||||
		{"wallys_dr6018", "AP"},
 | 
							{"wallys_dr6018", Platforms::AP},
 | 
				
			||||||
		{"wallys_dr6018_v4", "AP"},
 | 
							{"wallys_dr6018_v4", Platforms::AP},
 | 
				
			||||||
		{"x64_vm", "AP"},
 | 
							{"x64_vm", Platforms::AP},
 | 
				
			||||||
		{"yuncore_ax840", "AP"},
 | 
							{"yuncore_ax840", Platforms::AP},
 | 
				
			||||||
		{"yuncore_fap640", "AP"},
 | 
							{"yuncore_fap640", Platforms::AP},
 | 
				
			||||||
		{"yuncore_fap650", "AP"}};
 | 
							{"yuncore_fap650", Platforms::AP}};
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -565,6 +565,7 @@ namespace OpenWifi::RESTAPI::Protocol {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	static const char *TRANSFER = "transfer";
 | 
						static const char *TRANSFER = "transfer";
 | 
				
			||||||
	static const char *CERTUPDATE = "certupdate";
 | 
						static const char *CERTUPDATE = "certupdate";
 | 
				
			||||||
 | 
						static const char *POWERCYCLE = "powercycle";
 | 
				
			||||||
	static const char *RRM = "rrm";
 | 
						static const char *RRM = "rrm";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	static const char *REQUIREMENTS = "requirements";
 | 
						static const char *REQUIREMENTS = "requirements";
 | 
				
			||||||
@@ -579,6 +580,10 @@ namespace OpenWifi::RESTAPI::Protocol {
 | 
				
			|||||||
	static const char *INTERVAL = "interval";
 | 
						static const char *INTERVAL = "interval";
 | 
				
			||||||
	static const char *UI = "UI";
 | 
						static const char *UI = "UI";
 | 
				
			||||||
	static const char *BANDWIDTH = "bandwidth";
 | 
						static const char *BANDWIDTH = "bandwidth";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						static const char *FIXEDCONFIG = "fixedconfig";
 | 
				
			||||||
 | 
						static const char *CABLEDIAGNOSTICS = "cable-diagnostics";
 | 
				
			||||||
 | 
						static const char *REENROLL = "reenroll";
 | 
				
			||||||
} // namespace OpenWifi::RESTAPI::Protocol
 | 
					} // namespace OpenWifi::RESTAPI::Protocol
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace OpenWifi::uCentralProtocol {
 | 
					namespace OpenWifi::uCentralProtocol {
 | 
				
			||||||
@@ -607,6 +612,7 @@ namespace OpenWifi::uCentralProtocol {
 | 
				
			|||||||
	static const char *CFGPENDING = "cfgpending";
 | 
						static const char *CFGPENDING = "cfgpending";
 | 
				
			||||||
	static const char *RECOVERY = "recovery";
 | 
						static const char *RECOVERY = "recovery";
 | 
				
			||||||
	static const char *COMPRESS_64 = "compress_64";
 | 
						static const char *COMPRESS_64 = "compress_64";
 | 
				
			||||||
 | 
						static const char *COMPRESS_SZ = "compress_sz";
 | 
				
			||||||
	static const char *CAPABILITIES = "capabilities";
 | 
						static const char *CAPABILITIES = "capabilities";
 | 
				
			||||||
	static const char *REQUEST_UUID = "request_uuid";
 | 
						static const char *REQUEST_UUID = "request_uuid";
 | 
				
			||||||
	static const char *SANITY = "sanity";
 | 
						static const char *SANITY = "sanity";
 | 
				
			||||||
@@ -687,9 +693,15 @@ namespace OpenWifi::uCentralProtocol {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	static const char *TRANSFER = "transfer";
 | 
						static const char *TRANSFER = "transfer";
 | 
				
			||||||
	static const char *CERTUPDATE = "certupdate";
 | 
						static const char *CERTUPDATE = "certupdate";
 | 
				
			||||||
 | 
						static const char *POWERCYCLE = "powercycle";
 | 
				
			||||||
	static const char *RRM = "rrm";
 | 
						static const char *RRM = "rrm";
 | 
				
			||||||
	static const char *ACTIONS = "actions";
 | 
						static const char *ACTIONS = "actions";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						static const char *FIXEDCONFIG = "fixedconfig";
 | 
				
			||||||
 | 
						static const char *CABLEDIAGNOSTICS = "cable-diagnostics";
 | 
				
			||||||
 | 
						static const char *REENROLL = "reenroll";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
} // namespace OpenWifi::uCentralProtocol
 | 
					} // namespace OpenWifi::uCentralProtocol
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace OpenWifi::uCentralProtocol::Events {
 | 
					namespace OpenWifi::uCentralProtocol::Events {
 | 
				
			||||||
@@ -785,6 +797,10 @@ namespace OpenWifi::APCommands {
 | 
				
			|||||||
		rrm,
 | 
							rrm,
 | 
				
			||||||
		certupdate,
 | 
							certupdate,
 | 
				
			||||||
		transfer,
 | 
							transfer,
 | 
				
			||||||
 | 
							powercycle,
 | 
				
			||||||
 | 
							fixedconfig,
 | 
				
			||||||
 | 
							cablediagnostics,
 | 
				
			||||||
 | 
							reenroll,
 | 
				
			||||||
		unknown
 | 
							unknown
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -799,7 +815,9 @@ namespace OpenWifi::APCommands {
 | 
				
			|||||||
		RESTAPI::Protocol::EVENTQUEUE,	 RESTAPI::Protocol::TELEMETRY,
 | 
							RESTAPI::Protocol::EVENTQUEUE,	 RESTAPI::Protocol::TELEMETRY,
 | 
				
			||||||
		RESTAPI::Protocol::PING,		 RESTAPI::Protocol::SCRIPT,
 | 
							RESTAPI::Protocol::PING,		 RESTAPI::Protocol::SCRIPT,
 | 
				
			||||||
		RESTAPI::Protocol::RRM,		 	 RESTAPI::Protocol::CERTUPDATE,
 | 
							RESTAPI::Protocol::RRM,		 	 RESTAPI::Protocol::CERTUPDATE,
 | 
				
			||||||
		RESTAPI::Protocol::TRANSFER
 | 
							RESTAPI::Protocol::TRANSFER,	 RESTAPI::Protocol::POWERCYCLE,
 | 
				
			||||||
 | 
							RESTAPI::Protocol::FIXEDCONFIG,  RESTAPI::Protocol::CABLEDIAGNOSTICS,
 | 
				
			||||||
 | 
							RESTAPI::Protocol::REENROLL
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	inline const char *to_string(Commands Cmd) { return uCentralAPCommands[(uint8_t)Cmd]; }
 | 
						inline const char *to_string(Commands Cmd) { return uCentralAPCommands[(uint8_t)Cmd]; }
 | 
				
			||||||
@@ -828,6 +846,11 @@ namespace OpenWifi::Provisioning::DeviceClass {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
} // namespace OpenWifi::Provisioning::DeviceClass
 | 
					} // namespace OpenWifi::Provisioning::DeviceClass
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace OpenWifi::Platforms {
 | 
				
			||||||
 | 
						static const std::string AP = "ap";
 | 
				
			||||||
 | 
						static const std::string SWITCH = "switch";
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#if defined(__GNUC__)
 | 
					#if defined(__GNUC__)
 | 
				
			||||||
#pragma GCC diagnostic pop
 | 
					#pragma GCC diagnostic pop
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -590,6 +590,26 @@ namespace OpenWifi::Utils {
 | 
				
			|||||||
		return false;
 | 
							return false;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						//
 | 
				
			||||||
 | 
						// Compress given data using utility function and encode it in base64 format.
 | 
				
			||||||
 | 
						//
 | 
				
			||||||
 | 
						bool CompressAndEncodeBase64(const std::string& UnCompressedData, std::string& CompressedBase64Data) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							unsigned long CompressedDataSize = UnCompressedData.size();
 | 
				
			||||||
 | 
							std::vector<Bytef> CompressedData(CompressedDataSize);
 | 
				
			||||||
 | 
							auto status = compress(&CompressedData[0], &CompressedDataSize,
 | 
				
			||||||
 | 
													(Bytef*) UnCompressedData.c_str(), UnCompressedData.size());
 | 
				
			||||||
 | 
							if (status == Z_OK) {
 | 
				
			||||||
 | 
								CompressedBase64Data = OpenWifi::Utils::base64encode(&CompressedData[0], CompressedDataSize);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							else {
 | 
				
			||||||
 | 
								// failed to compress data
 | 
				
			||||||
 | 
								return false;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							return true;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	bool IsAlphaNumeric(const std::string &s) {
 | 
						bool IsAlphaNumeric(const std::string &s) {
 | 
				
			||||||
		return std::all_of(s.begin(), s.end(), [](char c) -> bool { return isalnum(c); });
 | 
							return std::all_of(s.begin(), s.end(), [](char c) -> bool { return isalnum(c); });
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -151,6 +151,8 @@ namespace OpenWifi::Utils {
 | 
				
			|||||||
	bool ExtractBase64CompressedData(const std::string &CompressedData,
 | 
						bool ExtractBase64CompressedData(const std::string &CompressedData,
 | 
				
			||||||
									 std::string &UnCompressedData, uint64_t compress_sz);
 | 
														 std::string &UnCompressedData, uint64_t compress_sz);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						bool CompressAndEncodeBase64(const std::string& UnCompressedData, std::string& CompressedData);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	inline bool match(const char* first, const char* second)
 | 
						inline bool match(const char* first, const char* second)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		// If we reach at the end of both strings, we are done
 | 
							// If we reach at the end of both strings, we are done
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -14,6 +14,7 @@
 | 
				
			|||||||
#include "nlohmann/json.hpp"
 | 
					#include "nlohmann/json.hpp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "Poco/NObserver.h"
 | 
					#include "Poco/NObserver.h"
 | 
				
			||||||
 | 
					#include <Poco/Net/Context.h>
 | 
				
			||||||
#include "Poco/Net/SocketNotification.h"
 | 
					#include "Poco/Net/SocketNotification.h"
 | 
				
			||||||
#include "Poco/Net/NetException.h"
 | 
					#include "Poco/Net/NetException.h"
 | 
				
			||||||
#include "Poco/Net/WebSocketImpl.h"
 | 
					#include "Poco/Net/WebSocketImpl.h"
 | 
				
			||||||
@@ -71,6 +72,7 @@ namespace OpenWifi {
 | 
				
			|||||||
				const auto &RootCas =
 | 
									const auto &RootCas =
 | 
				
			||||||
					MicroServiceConfigPath("ucentral.websocket.host.0.rootca", "");
 | 
										MicroServiceConfigPath("ucentral.websocket.host.0.rootca", "");
 | 
				
			||||||
				const auto &Cas = MicroServiceConfigPath("ucentral.websocket.host.0.cas", "");
 | 
									const auto &Cas = MicroServiceConfigPath("ucentral.websocket.host.0.cas", "");
 | 
				
			||||||
 | 
									const auto &ClientCasFile = MicroServiceConfigPath("ucentral.websocket.host.0.clientcas", "");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				Poco::Net::Context::Params P;
 | 
									Poco::Net::Context::Params P;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -86,6 +88,7 @@ namespace OpenWifi {
 | 
				
			|||||||
				Poco::Crypto::X509Certificate Cert(CertFileName);
 | 
									Poco::Crypto::X509Certificate Cert(CertFileName);
 | 
				
			||||||
				Poco::Crypto::X509Certificate Root(RootCaFileName);
 | 
									Poco::Crypto::X509Certificate Root(RootCaFileName);
 | 
				
			||||||
				Poco::Crypto::X509Certificate Issuing(IssuerFileName);
 | 
									Poco::Crypto::X509Certificate Issuing(IssuerFileName);
 | 
				
			||||||
 | 
					                std::vector<Poco::Crypto::X509Certificate> ClientCasCerts;
 | 
				
			||||||
				Poco::Crypto::RSAKey Key("", KeyFileName, KeyPassword);
 | 
									Poco::Crypto::RSAKey Key("", KeyFileName, KeyPassword);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				DeviceSecureContext->useCertificate(Cert);
 | 
									DeviceSecureContext->useCertificate(Cert);
 | 
				
			||||||
@@ -93,7 +96,11 @@ namespace OpenWifi {
 | 
				
			|||||||
				DeviceSecureContext->addCertificateAuthority(Root);
 | 
									DeviceSecureContext->addCertificateAuthority(Root);
 | 
				
			||||||
				DeviceSecureContext->addChainCertificate(Issuing);
 | 
									DeviceSecureContext->addChainCertificate(Issuing);
 | 
				
			||||||
				DeviceSecureContext->addCertificateAuthority(Issuing);
 | 
									DeviceSecureContext->addCertificateAuthority(Issuing);
 | 
				
			||||||
				DeviceSecureContext->addCertificateAuthority(Root);
 | 
					                ClientCasCerts = Poco::Net::X509Certificate::readPEM(ClientCasFile);
 | 
				
			||||||
 | 
					                for (const auto &cert : ClientCasCerts) {
 | 
				
			||||||
 | 
					                    DeviceSecureContext->addChainCertificate(cert);
 | 
				
			||||||
 | 
					                    DeviceSecureContext->addCertificateAuthority(cert);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
				DeviceSecureContext->enableSessionCache(true);
 | 
									DeviceSecureContext->enableSessionCache(true);
 | 
				
			||||||
				DeviceSecureContext->setSessionCacheSize(0);
 | 
									DeviceSecureContext->setSessionCacheSize(0);
 | 
				
			||||||
				DeviceSecureContext->setSessionTimeout(120);
 | 
									DeviceSecureContext->setSessionTimeout(120);
 | 
				
			||||||
@@ -1117,4 +1124,4 @@ namespace OpenWifi {
 | 
				
			|||||||
	RTTYS_EndPoint::~RTTYS_EndPoint() {
 | 
						RTTYS_EndPoint::~RTTYS_EndPoint() {
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
} // namespace OpenWifi
 | 
					} // namespace OpenWifi
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -644,21 +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);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
			std::string StatementStr;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			//	Get the existing command
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			StatementStr =
 | 
					 | 
				
			||||||
				"UPDATE CommandList SET WaitingForFile=?, AttachDate=?, AttachSize=? WHERE UUID=?";
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			Statement << ConvertParams(StatementStr), Poco::Data::Keywords::use(WaitForFile),
 | 
					 | 
				
			||||||
				Poco::Data::Keywords::use(Now), Poco::Data::Keywords::use(Size),
 | 
					 | 
				
			||||||
				Poco::Data::Keywords::use(UUID);
 | 
					 | 
				
			||||||
			Statement.execute();
 | 
					 | 
				
			||||||
			Sess.commit();
 | 
					 | 
				
			||||||
			if (Size < FileUploader()->MaxSize()) {
 | 
								if (Size < FileUploader()->MaxSize()) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				Poco::Data::BLOB TheBlob;
 | 
									Poco::Data::BLOB TheBlob;
 | 
				
			||||||
@@ -680,7 +666,20 @@ namespace OpenWifi {
 | 
				
			|||||||
			} else {
 | 
								} else {
 | 
				
			||||||
				poco_warning(Logger(), fmt::format("File {} is too large.", UUID));
 | 
									poco_warning(Logger(), fmt::format("File {} is too large.", UUID));
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								// update CommandList here to ensure that file us uploaded
 | 
				
			||||||
 | 
					                        Sess.begin();
 | 
				
			||||||
 | 
					                        Poco::Data::Statement Statement(Sess);
 | 
				
			||||||
 | 
								std::string StatementStr;
 | 
				
			||||||
 | 
								StatementStr =
 | 
				
			||||||
 | 
									"UPDATE CommandList SET WaitingForFile=?, AttachDate=?, AttachSize=? WHERE UUID=?";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								Statement << ConvertParams(StatementStr), Poco::Data::Keywords::use(WaitForFile),
 | 
				
			||||||
 | 
									Poco::Data::Keywords::use(Now), Poco::Data::Keywords::use(Size),
 | 
				
			||||||
 | 
									Poco::Data::Keywords::use(UUID);
 | 
				
			||||||
 | 
								Statement.execute();
 | 
				
			||||||
			Sess.commit();
 | 
								Sess.commit();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			return true;
 | 
								return true;
 | 
				
			||||||
		} catch (const Poco::Exception &E) {
 | 
							} catch (const Poco::Exception &E) {
 | 
				
			||||||
			Logger().log(E);
 | 
								Logger().log(E);
 | 
				
			||||||
@@ -689,7 +688,7 @@ namespace OpenWifi {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	bool Storage::GetAttachedFileContent(std::string &UUID, const std::string &SerialNumber,
 | 
						bool Storage::GetAttachedFileContent(std::string &UUID, const std::string &SerialNumber,
 | 
				
			||||||
										 std::string &FileContent, std::string &Type) {
 | 
															 std::string &FileContent, std::string &Type, int &WaitingForFile) {
 | 
				
			||||||
		try {
 | 
							try {
 | 
				
			||||||
			Poco::Data::BLOB L;
 | 
								Poco::Data::BLOB L;
 | 
				
			||||||
			/*
 | 
								/*
 | 
				
			||||||
@@ -702,10 +701,10 @@ namespace OpenWifi {
 | 
				
			|||||||
			Poco::Data::Statement Select1(Sess);
 | 
								Poco::Data::Statement Select1(Sess);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			std::string TmpSerialNumber;
 | 
								std::string TmpSerialNumber;
 | 
				
			||||||
			std::string st1{"SELECT SerialNumber, Command FROM CommandList WHERE UUID=?"};
 | 
								std::string st1{"SELECT SerialNumber, Command , WaitingForFile FROM CommandList WHERE UUID=?"};
 | 
				
			||||||
			std::string Command;
 | 
								std::string Command;
 | 
				
			||||||
			Select1 << ConvertParams(st1), Poco::Data::Keywords::into(TmpSerialNumber),
 | 
								Select1 << ConvertParams(st1), Poco::Data::Keywords::into(TmpSerialNumber),
 | 
				
			||||||
				Poco::Data::Keywords::into(Command), Poco::Data::Keywords::use(UUID);
 | 
									Poco::Data::Keywords::into(Command), Poco::Data::Keywords::into(WaitingForFile), Poco::Data::Keywords::use(UUID);
 | 
				
			||||||
			Select1.execute();
 | 
								Select1.execute();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if (TmpSerialNumber != SerialNumber) {
 | 
								if (TmpSerialNumber != SerialNumber) {
 | 
				
			||||||
@@ -825,4 +824,4 @@ namespace OpenWifi {
 | 
				
			|||||||
		return false;
 | 
							return false;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
} // namespace OpenWifi
 | 
					} // namespace OpenWifi
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -19,37 +19,39 @@ namespace OpenWifi {
 | 
				
			|||||||
																   "Models TEXT, "
 | 
																					   "Models TEXT, "
 | 
				
			||||||
																   "Description TEXT, "
 | 
																					   "Description TEXT, "
 | 
				
			||||||
																   "Created BIGINT , "
 | 
																					   "Created BIGINT , "
 | 
				
			||||||
																   "LastModified BIGINT)"};
 | 
																					   "LastModified BIGINT, Platform TEXT )"};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	const static std::string DB_DefConfig_SelectFields{"Name, "
 | 
						const static std::string DB_DefConfig_SelectFields{"Name, "
 | 
				
			||||||
													   "Configuration, "
 | 
																		   "Configuration, "
 | 
				
			||||||
													   "Models, "
 | 
																		   "Models, "
 | 
				
			||||||
													   "Description, "
 | 
																		   "Description, "
 | 
				
			||||||
													   "Created, "
 | 
																		   "Created, "
 | 
				
			||||||
													   "LastModified "};
 | 
																		   "LastModified, Platform "};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	const static std::string DB_DefConfig_InsertValues{"?,?,?,?,?,?"};
 | 
						const static std::string DB_DefConfig_InsertValues{"?,?,?,?,?,?,?"};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	typedef Poco::Tuple<std::string, std::string, std::string, std::string, uint64_t, uint64_t>
 | 
						typedef Poco::Tuple<std::string, std::string, std::string, std::string, uint64_t, uint64_t, std::string>
 | 
				
			||||||
		DefConfigRecordTuple;
 | 
							DefConfigRecordTuple;
 | 
				
			||||||
	typedef std::vector<DefConfigRecordTuple> DefConfigRecordList;
 | 
						typedef std::vector<DefConfigRecordTuple> DefConfigRecordList;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	void Convert(const DefConfigRecordTuple &R, GWObjects::DefaultConfiguration &T) {
 | 
						void Convert(const DefConfigRecordTuple &R, GWObjects::DefaultConfiguration &T) {
 | 
				
			||||||
		T.Name = R.get<0>();
 | 
							T.name = R.get<0>();
 | 
				
			||||||
		T.Configuration = R.get<1>();
 | 
							T.configuration = R.get<1>();
 | 
				
			||||||
		T.Models = RESTAPI_utils::to_object_array(R.get<2>());
 | 
							T.models = RESTAPI_utils::to_object_array(R.get<2>());
 | 
				
			||||||
		T.Description = R.get<3>();
 | 
							T.description = R.get<3>();
 | 
				
			||||||
		T.Created = R.get<4>();
 | 
							T.created = R.get<4>();
 | 
				
			||||||
		T.LastModified = R.get<5>();
 | 
							T.lastModified = R.get<5>();
 | 
				
			||||||
 | 
							T.platform = R.get<6>();
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	void Convert(const GWObjects::DefaultConfiguration &R, DefConfigRecordTuple &T) {
 | 
						void Convert(const GWObjects::DefaultConfiguration &R, DefConfigRecordTuple &T) {
 | 
				
			||||||
		T.set<0>(R.Name);
 | 
							T.set<0>(R.name);
 | 
				
			||||||
		T.set<1>(R.Configuration);
 | 
							T.set<1>(R.configuration);
 | 
				
			||||||
		T.set<2>(RESTAPI_utils::to_string(R.Models));
 | 
							T.set<2>(RESTAPI_utils::to_string(R.models));
 | 
				
			||||||
		T.set<3>(R.Description);
 | 
							T.set<3>(R.description);
 | 
				
			||||||
		T.set<4>(R.Created);
 | 
							T.set<4>(R.created);
 | 
				
			||||||
		T.set<5>(R.LastModified);
 | 
							T.set<5>(R.lastModified);
 | 
				
			||||||
 | 
							T.set<6>(R.platform);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	bool Storage::CreateDefaultConfiguration(std::string &Name,
 | 
						bool Storage::CreateDefaultConfiguration(std::string &Name,
 | 
				
			||||||
@@ -69,7 +71,7 @@ namespace OpenWifi {
 | 
				
			|||||||
			if (!TmpName.empty())
 | 
								if (!TmpName.empty())
 | 
				
			||||||
				return false;
 | 
									return false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			Config::Config Cfg(DefConfig.Configuration);
 | 
								Config::Config Cfg(DefConfig.configuration);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if (Cfg.Valid()) {
 | 
								if (Cfg.Valid()) {
 | 
				
			||||||
				Sess.begin();
 | 
									Sess.begin();
 | 
				
			||||||
@@ -124,10 +126,10 @@ namespace OpenWifi {
 | 
				
			|||||||
			Poco::Data::Session Sess = Pool_->get();
 | 
								Poco::Data::Session Sess = Pool_->get();
 | 
				
			||||||
			Sess.begin();
 | 
								Sess.begin();
 | 
				
			||||||
			Poco::Data::Statement Update(Sess);
 | 
								Poco::Data::Statement Update(Sess);
 | 
				
			||||||
			DefConfig.LastModified = Now;
 | 
								DefConfig.lastModified = Now;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			std::string St{"UPDATE DefaultConfigs SET Name=?, Configuration=?,  Models=?,  "
 | 
								std::string St{"UPDATE DefaultConfigs SET Name=?, Configuration=?,  Models=?,  "
 | 
				
			||||||
						   "Description=?,  Created=? , LastModified=?  WHERE Name=?"};
 | 
											   "Description=?,  Created=? , LastModified=? , Platform=?  WHERE Name=?"};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			DefConfigRecordTuple R;
 | 
								DefConfigRecordTuple R;
 | 
				
			||||||
			Convert(DefConfig, R);
 | 
								Convert(DefConfig, R);
 | 
				
			||||||
@@ -219,31 +221,30 @@ namespace OpenWifi {
 | 
				
			|||||||
		return false;
 | 
							return false;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	bool Storage::FindDefaultConfigurationForModel(const std::string &Model,
 | 
						bool Storage::FindDefaultConfigurationForModel(const std::string &DeviceModel, const std::string &Platform,
 | 
				
			||||||
												   GWObjects::DefaultConfiguration &DefConfig) {
 | 
																	   GWObjects::DefaultConfiguration &Config) {
 | 
				
			||||||
		try {
 | 
							try {
 | 
				
			||||||
			DefConfigRecordList Records;
 | 
								DefConfigRecordList DefConfigs;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			Poco::Data::Session Sess = Pool_->get();
 | 
								Poco::Data::Session Sess = Pool_->get();
 | 
				
			||||||
			Poco::Data::Statement Select(Sess);
 | 
								Poco::Data::Statement Select(Sess);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			Select << "SELECT " + DB_DefConfig_SelectFields + " FROM DefaultConfigs",
 | 
								Select << "SELECT " + DB_DefConfig_SelectFields + " FROM DefaultConfigs",
 | 
				
			||||||
				Poco::Data::Keywords::into(Records);
 | 
									Poco::Data::Keywords::into(DefConfigs);
 | 
				
			||||||
			Select.execute();
 | 
								Select.execute();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			for (const auto &i : Records) {
 | 
								for (const auto &DefConfig : DefConfigs) {
 | 
				
			||||||
				GWObjects::DefaultConfiguration Config;
 | 
									GWObjects::DefaultConfiguration C;
 | 
				
			||||||
				Convert(i, Config);
 | 
									Convert(DefConfig, C);
 | 
				
			||||||
				for (const auto &j : Config.Models) {
 | 
									for (const auto &Model : C.models) {
 | 
				
			||||||
					if (j == "*" || j == Model) {
 | 
										if ((Model == "*" || Model == DeviceModel) && (Config.platform == Platform)){
 | 
				
			||||||
						DefConfig = Config;
 | 
											Config = C;
 | 
				
			||||||
						return true;
 | 
											return true;
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			Logger().information(
 | 
								Logger().information(
 | 
				
			||||||
				fmt::format("AUTO-PROVISIONING: no default configuration for model:{}", Model));
 | 
									fmt::format("AUTO-PROVISIONING: no default configuration for model:{}", DeviceModel));
 | 
				
			||||||
			return false;
 | 
					 | 
				
			||||||
		} 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__),
 | 
				
			||||||
											   E.displayText()));
 | 
																   E.displayText()));
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -172,14 +172,18 @@ namespace OpenWifi {
 | 
				
			|||||||
		R.set<30>(D.connectReason);
 | 
							R.set<30>(D.connectReason);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	bool Storage::GetDeviceCount(uint64_t &Count) {
 | 
						bool Storage::GetDeviceCount(uint64_t &Count, const std::string &platform) {
 | 
				
			||||||
		try {
 | 
							try {
 | 
				
			||||||
			Poco::Data::Session Sess = Pool_->get();
 | 
								Poco::Data::Session Sess = Pool_->get();
 | 
				
			||||||
			Poco::Data::Statement Select(Sess);
 | 
								Poco::Data::Statement Select(Sess);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			std::string st{"SELECT COUNT(*) FROM Devices"};
 | 
								if(!platform.empty()) {
 | 
				
			||||||
 | 
									std::string st{"SELECT COUNT(*) FROM Devices WHERE DeviceType='" + platform + "'"};
 | 
				
			||||||
			Select << st, Poco::Data::Keywords::into(Count);
 | 
									Select << st, Poco::Data::Keywords::into(Count);
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
									std::string st{"SELECT COUNT(*) FROM Devices"};
 | 
				
			||||||
 | 
									Select << st, Poco::Data::Keywords::into(Count);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
			Select.execute();
 | 
								Select.execute();
 | 
				
			||||||
			return true;
 | 
								return true;
 | 
				
			||||||
		} catch (const Poco::Exception &E) {
 | 
							} catch (const Poco::Exception &E) {
 | 
				
			||||||
@@ -190,16 +194,37 @@ namespace OpenWifi {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	bool Storage::GetDeviceSerialNumbers(uint64_t From, uint64_t HowMany,
 | 
						bool Storage::GetDeviceSerialNumbers(uint64_t From, uint64_t HowMany,
 | 
				
			||||||
										 std::vector<std::string> &SerialNumbers,
 | 
															 std::vector<std::string> &SerialNumbers,
 | 
				
			||||||
										 const std::string &orderBy) {
 | 
															 const std::string &orderBy,
 | 
				
			||||||
 | 
															 const std::string &platform, bool includeProvisioned) {
 | 
				
			||||||
		try {
 | 
							try {
 | 
				
			||||||
			Poco::Data::Session Sess = Pool_->get();
 | 
								Poco::Data::Session Sess = Pool_->get();
 | 
				
			||||||
			Poco::Data::Statement Select(Sess);
 | 
								Poco::Data::Statement Select(Sess);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			std::string st;
 | 
								std::string st;
 | 
				
			||||||
 | 
								std::string whereClause = "";
 | 
				
			||||||
 | 
								if(!platform.empty()) {
 | 
				
			||||||
 | 
									if (includeProvisioned == false) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
										whereClause = fmt::format("WHERE entity='' and venue='' and DeviceType='" + platform + "'");
 | 
				
			||||||
 | 
									} else {
 | 
				
			||||||
 | 
										whereClause = fmt::format("WHERE DeviceType='" + platform + "'");
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									//st = "SELECT SerialNumber From Devices WHERE DeviceType='" + platform + "' ";
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
									if (includeProvisioned == false) {
 | 
				
			||||||
 | 
										whereClause = fmt::format("WHERE entity='' and venue=''");
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									//st = "SELECT SerialNumber From Devices ";
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								
 | 
				
			||||||
 | 
								st = fmt::format("SELECT SerialNumber From Devices {}", whereClause);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if (orderBy.empty())
 | 
								if (orderBy.empty())
 | 
				
			||||||
				st = "SELECT SerialNumber From Devices ORDER BY SerialNumber ASC ";
 | 
									st += " ORDER BY SerialNumber ASC ";
 | 
				
			||||||
			else
 | 
								else
 | 
				
			||||||
				st = "SELECT SerialNumber From Devices " + orderBy;
 | 
									st += orderBy;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			Select << st + ComputeRange(From, HowMany), Poco::Data::Keywords::into(SerialNumbers);
 | 
								Select << st + ComputeRange(From, HowMany), Poco::Data::Keywords::into(SerialNumbers);
 | 
				
			||||||
			Select.execute();
 | 
								Select.execute();
 | 
				
			||||||
@@ -265,7 +290,7 @@ namespace OpenWifi {
 | 
				
			|||||||
			D.pendingUUID = 0;
 | 
								D.pendingUUID = 0;
 | 
				
			||||||
			D.LastConfigurationChange = Utils::Now();
 | 
								D.LastConfigurationChange = Utils::Now();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			ConfigurationCache().Add(Utils::SerialNumberToInt(SerialNumber), D.UUID);
 | 
								SetCurrentConfigurationID(Utils::SerialNumberToInt(SerialNumber), D.UUID);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			Poco::Data::Session Sess = Pool_->get();
 | 
								Poco::Data::Session Sess = Pool_->get();
 | 
				
			||||||
			Sess.begin();
 | 
								Sess.begin();
 | 
				
			||||||
@@ -298,19 +323,30 @@ namespace OpenWifi {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	bool Storage::CompleteDeviceConfigurationChange(Poco::Data::Session & Session, std::string & SerialNumber) {
 | 
						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))
 | 
				
			||||||
				return false;
 | 
									return false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if(D.pendingConfiguration.empty())
 | 
								if(!D.pendingConfiguration.empty()) {
 | 
				
			||||||
				return true;
 | 
									D.Configuration = D.pendingConfiguration;
 | 
				
			||||||
			D.Configuration = D.pendingConfiguration;
 | 
									D.pendingConfiguration.clear();
 | 
				
			||||||
			D.pendingConfiguration.clear();
 | 
								}
 | 
				
			||||||
			D.UUID = D.pendingUUID;
 | 
								if(D.pendingUUID!=0) {
 | 
				
			||||||
			D.pendingUUID = 0;
 | 
									D.UUID = D.pendingUUID;
 | 
				
			||||||
			D.LastConfigurationChange = Utils::Now();
 | 
									D.pendingUUID = 0;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			ConfigurationCache().Add(Utils::SerialNumberToInt(SerialNumber), D.UUID);
 | 
								//	if this is a broken device, fix it...
 | 
				
			||||||
 | 
								if(D.UUID==0) {
 | 
				
			||||||
 | 
									Config::Config Cfg(D.Configuration);
 | 
				
			||||||
 | 
									if(Cfg.Valid()) {
 | 
				
			||||||
 | 
										D.UUID = Cfg.UUID();
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								D.LastConfigurationChange = Utils::Now();
 | 
				
			||||||
 | 
								SetCurrentConfigurationID(Utils::SerialNumberToInt(SerialNumber), D.UUID);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			Session.begin();
 | 
								Session.begin();
 | 
				
			||||||
			Poco::Data::Statement Update(Session);
 | 
								Poco::Data::Statement Update(Session);
 | 
				
			||||||
@@ -525,7 +561,7 @@ namespace OpenWifi {
 | 
				
			|||||||
		} catch (const Poco::Exception &E) {
 | 
							} catch (const Poco::Exception &E) {
 | 
				
			||||||
			Logger().log(E);
 | 
								Logger().log(E);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		return true;
 | 
							return false;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	bool Storage::CreateDefaultDevice(Poco::Data::Session &Session, std::string &SerialNumber, const Config::Capabilities &Caps,
 | 
						bool Storage::CreateDefaultDevice(Poco::Data::Session &Session, std::string &SerialNumber, const Config::Capabilities &Caps,
 | 
				
			||||||
@@ -557,21 +593,31 @@ namespace OpenWifi {
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (!Found && AP_WS_Server()->UseDefaults() &&
 | 
							if (!Found && AP_WS_Server()->UseDefaults() &&
 | 
				
			||||||
			FindDefaultConfigurationForModel(Caps.Compatible(), DefConfig)) {
 | 
								FindDefaultConfigurationForModel(Caps.Compatible(), Caps.Platform(), DefConfig)) {
 | 
				
			||||||
			Config::Config NewConfig(DefConfig.Configuration);
 | 
								Config::Config NewConfig(DefConfig.configuration);
 | 
				
			||||||
			NewConfig.SetUUID(Now);
 | 
								NewConfig.SetUUID(Now);
 | 
				
			||||||
			D.Configuration = NewConfig.get();
 | 
								D.Configuration = NewConfig.get();
 | 
				
			||||||
		} else if (!Found) {
 | 
							} else if (!Found) {
 | 
				
			||||||
			Config::Config NewConfig;
 | 
								if(Caps.Platform()==Platforms::AP) {
 | 
				
			||||||
			NewConfig.SetUUID(Now);
 | 
									Config::Config NewConfig;
 | 
				
			||||||
			D.Configuration = NewConfig.get();
 | 
									NewConfig.SetUUID(Now);
 | 
				
			||||||
 | 
									D.Configuration = NewConfig.get();
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
									Poco::JSON::Object Obj;
 | 
				
			||||||
 | 
									Obj.set("uuid", Now);
 | 
				
			||||||
 | 
									std::ostringstream os;
 | 
				
			||||||
 | 
									Obj.stringify(os);
 | 
				
			||||||
 | 
									D.Configuration = os.str();
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		//	We need to insert the country code according to the IP in the radios section...
 | 
							//	We need to insert the country code according to the IP in the radios section...
 | 
				
			||||||
		D.locale = InsertRadiosCountyRegulation(D.Configuration, IPAddress);
 | 
							D.locale = InsertRadiosCountyRegulation(D.Configuration, IPAddress);
 | 
				
			||||||
		D.SerialNumber = Poco::toLower(SerialNumber);
 | 
							D.SerialNumber = Poco::toLower(SerialNumber);
 | 
				
			||||||
		D.Compatible = Caps.Compatible();
 | 
							D.Compatible = Caps.Compatible();
 | 
				
			||||||
		D.DeviceType = Daemon()->IdentifyDevice(D.Compatible);
 | 
							if(D.Compatible.empty())
 | 
				
			||||||
 | 
								D.Compatible = Caps.Model();
 | 
				
			||||||
 | 
							D.DeviceType = Poco::toLower(Caps.Platform());
 | 
				
			||||||
		D.MACAddress = Utils::SerialToMAC(SerialNumber);
 | 
							D.MACAddress = Utils::SerialToMAC(SerialNumber);
 | 
				
			||||||
		D.Manufacturer = Caps.Model();
 | 
							D.Manufacturer = Caps.Model();
 | 
				
			||||||
		D.Firmware = Firmware;
 | 
							D.Firmware = Firmware;
 | 
				
			||||||
@@ -620,6 +666,22 @@ namespace OpenWifi {
 | 
				
			|||||||
		return false;
 | 
							return false;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						std::string Storage::GetPlatform(const std::string &SerialNumber) {
 | 
				
			||||||
 | 
							try {
 | 
				
			||||||
 | 
								Poco::Data::Session Sess = Pool_->get();
 | 
				
			||||||
 | 
								Poco::Data::Statement Select(Sess);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								std::string St = fmt::format("SELECT DeviceType FROM Devices WHERE SerialNumber='{}'", SerialNumber);
 | 
				
			||||||
 | 
								std::string Platform;
 | 
				
			||||||
 | 
								Select << ConvertParams(St), Poco::Data::Keywords::into(Platform);
 | 
				
			||||||
 | 
								Select.execute();
 | 
				
			||||||
 | 
								return Platform;
 | 
				
			||||||
 | 
							} catch (const Poco::Exception &E) {
 | 
				
			||||||
 | 
								Logger().log(E);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return "";
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	bool Storage::DeleteDevice(std::string &SerialNumber) {
 | 
						bool Storage::DeleteDevice(std::string &SerialNumber) {
 | 
				
			||||||
		try {
 | 
							try {
 | 
				
			||||||
			std::vector<std::string> TableNames{"Devices",		"Statistics",	"CommandList",
 | 
								std::vector<std::string> TableNames{"Devices",		"Statistics",	"CommandList",
 | 
				
			||||||
@@ -708,17 +770,14 @@ namespace OpenWifi {
 | 
				
			|||||||
		return false;
 | 
							return false;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	bool Storage::GetDevice(Poco::Data::Session &Session, std::string &SerialNumber, GWObjects::Device &DeviceDetails) {
 | 
						bool Storage::GetDevice(Poco::Data::Session &Session, const std::string &SerialNumber, GWObjects::Device &DeviceDetails) {
 | 
				
			||||||
		try {
 | 
							try {
 | 
				
			||||||
			Poco::Data::Statement Select(Session);
 | 
								Poco::Data::Statement Select(Session);
 | 
				
			||||||
			std::string St{"SELECT " + DB_DeviceSelectFields +
 | 
								std::string St = fmt::format("SELECT {} FROM Devices WHERE SerialNumber='{}'", DB_DeviceSelectFields, SerialNumber);
 | 
				
			||||||
						   " FROM Devices WHERE SerialNumber=?"};
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
			DeviceRecordTuple R;
 | 
								DeviceRecordTuple R;
 | 
				
			||||||
			Select << ConvertParams(St), Poco::Data::Keywords::into(R),
 | 
								Select << St, Poco::Data::Keywords::into(R);
 | 
				
			||||||
				Poco::Data::Keywords::use(SerialNumber);
 | 
					 | 
				
			||||||
			Select.execute();
 | 
								Select.execute();
 | 
				
			||||||
 | 
					 | 
				
			||||||
			if (Select.rowsExtracted() == 0)
 | 
								if (Select.rowsExtracted() == 0)
 | 
				
			||||||
				return false;
 | 
									return false;
 | 
				
			||||||
			ConvertDeviceRecord(R, DeviceDetails);
 | 
								ConvertDeviceRecord(R, DeviceDetails);
 | 
				
			||||||
@@ -729,7 +788,7 @@ namespace OpenWifi {
 | 
				
			|||||||
		return false;
 | 
							return false;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	bool Storage::GetDevice(std::string &SerialNumber, GWObjects::Device &DeviceDetails) {
 | 
						bool Storage::GetDevice(const std::string &SerialNumber, GWObjects::Device &DeviceDetails) {
 | 
				
			||||||
		try {
 | 
							try {
 | 
				
			||||||
			auto Sess = Pool_->get();
 | 
								auto Sess = Pool_->get();
 | 
				
			||||||
			return GetDevice(Sess, SerialNumber, DeviceDetails);
 | 
								return GetDevice(Sess, SerialNumber, DeviceDetails);
 | 
				
			||||||
@@ -739,7 +798,7 @@ namespace OpenWifi {
 | 
				
			|||||||
		return false;
 | 
							return false;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	bool Storage::GetDevice(LockedDbSession &Session, std::string &SerialNumber, GWObjects::Device &DeviceDetails) {
 | 
						bool Storage::GetDevice(LockedDbSession &Session, const std::string &SerialNumber, GWObjects::Device &DeviceDetails) {
 | 
				
			||||||
		try {
 | 
							try {
 | 
				
			||||||
			std::lock_guard		Lock(Session.Mutex());
 | 
								std::lock_guard		Lock(Session.Mutex());
 | 
				
			||||||
			return GetDevice(Session.Session(), SerialNumber, DeviceDetails);
 | 
								return GetDevice(Session.Session(), SerialNumber, DeviceDetails);
 | 
				
			||||||
@@ -817,18 +876,38 @@ namespace OpenWifi {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	bool Storage::GetDevices(uint64_t From, uint64_t HowMany,
 | 
						bool Storage::GetDevices(uint64_t From, uint64_t HowMany,
 | 
				
			||||||
							 std::vector<GWObjects::Device> &Devices, const std::string &orderBy) {
 | 
												 std::vector<GWObjects::Device> &Devices, const std::string &orderBy, const std::string &platform,
 | 
				
			||||||
 | 
												 bool includeProvisioned) {
 | 
				
			||||||
		DeviceRecordList Records;
 | 
							DeviceRecordList Records;
 | 
				
			||||||
		try {
 | 
							try {
 | 
				
			||||||
			Poco::Data::Session Sess = Pool_->get();
 | 
								Poco::Data::Session Sess = Pool_->get();
 | 
				
			||||||
			Poco::Data::Statement Select(Sess);
 | 
								Poco::Data::Statement Select(Sess);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			// std::string st{"SELECT " + DB_DeviceSelectFields + " FROM Devices " + orderBy.empty()
 | 
								std::string st;
 | 
				
			||||||
			// ? " ORDER BY SerialNumber ASC " + ComputeRange(From, HowMany)};
 | 
								std::string whereClause = "";
 | 
				
			||||||
			std::string st = fmt::format("SELECT {} FROM Devices {} {}", DB_DeviceSelectFields,
 | 
								if(platform.empty()) {
 | 
				
			||||||
										 orderBy.empty() ? " ORDER BY SerialNumber ASC " : orderBy,
 | 
					 | 
				
			||||||
										 ComputeRange(From, HowMany));
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									if (includeProvisioned == false) {
 | 
				
			||||||
 | 
										whereClause = fmt::format("WHERE entity='' and venue=''");
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									if (includeProvisioned == false) {
 | 
				
			||||||
 | 
										whereClause = fmt::format("WHERE DeviceType='{}' and entity='' and venue=''",platform);
 | 
				
			||||||
 | 
									} else {
 | 
				
			||||||
 | 
										whereClause = fmt::format("WHERE DeviceType='{}'", platform);				
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
							
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								st =
 | 
				
			||||||
 | 
									fmt::format("SELECT {} FROM Devices {} {} {}", DB_DeviceSelectFields, whereClause,
 | 
				
			||||||
 | 
												orderBy.empty() ? " ORDER BY SerialNumber ASC " : orderBy,
 | 
				
			||||||
 | 
												ComputeRange(From, HowMany));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								//Logger().information(fmt::format(" GetDevices st is {} ", st));
 | 
				
			||||||
 | 
								
 | 
				
			||||||
			Select << ConvertParams(st), Poco::Data::Keywords::into(Records);
 | 
								Select << ConvertParams(st), Poco::Data::Keywords::into(Records);
 | 
				
			||||||
			Select.execute();
 | 
								Select.execute();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -1056,9 +1135,9 @@ namespace OpenWifi {
 | 
				
			|||||||
							}
 | 
												}
 | 
				
			||||||
						}
 | 
											}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
						uint64_t Associations_2G, Associations_5G, Associations_6G;
 | 
											uint64_t Associations_2G, Associations_5G, Associations_6G, uptime;
 | 
				
			||||||
						StateUtils::ComputeAssociations(RawObject, Associations_2G, Associations_5G,
 | 
											StateUtils::ComputeAssociations(RawObject, Associations_2G, Associations_5G,
 | 
				
			||||||
														Associations_6G);
 | 
																			Associations_6G, uptime);
 | 
				
			||||||
						UpdateCountedMap(Dashboard.associations, "2G", Associations_2G);
 | 
											UpdateCountedMap(Dashboard.associations, "2G", Associations_2G);
 | 
				
			||||||
						UpdateCountedMap(Dashboard.associations, "5G", Associations_5G);
 | 
											UpdateCountedMap(Dashboard.associations, "5G", Associations_5G);
 | 
				
			||||||
						UpdateCountedMap(Dashboard.associations, "6G", Associations_6G);
 | 
											UpdateCountedMap(Dashboard.associations, "6G", Associations_6G);
 | 
				
			||||||
@@ -1082,4 +1161,25 @@ namespace OpenWifi {
 | 
				
			|||||||
			FieldList.push_back(field);
 | 
								FieldList.push_back(field);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						void Storage::FixDeviceTypeBug() {
 | 
				
			||||||
 | 
							try {
 | 
				
			||||||
 | 
								std::vector<std::string> ScriptLines{
 | 
				
			||||||
 | 
									"update devices set devicetype='ap' where devicetype='AP';",
 | 
				
			||||||
 | 
									"update devices set devicetype='switch' where devicetype='SWITCH';",
 | 
				
			||||||
 | 
									"update devices set devicetype='ap' where devicetype!='ap' and devicetype!='switch';"
 | 
				
			||||||
 | 
								};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								for (const auto &ScriptLine : ScriptLines) {
 | 
				
			||||||
 | 
									try {
 | 
				
			||||||
 | 
										Poco::Data::Session Sess = Pool_->get();
 | 
				
			||||||
 | 
										Poco::Data::Statement SqlStatement(Sess);
 | 
				
			||||||
 | 
										SqlStatement << ScriptLine, Poco::Data::Keywords::now;
 | 
				
			||||||
 | 
									} catch (...) {
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							} catch (const Poco::Exception &E) {
 | 
				
			||||||
 | 
								Logger().log(E);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
} // namespace OpenWifi
 | 
					} // namespace OpenWifi
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -275,9 +275,21 @@ namespace OpenWifi {
 | 
				
			|||||||
						"Models TEXT, "
 | 
											"Models TEXT, "
 | 
				
			||||||
						"Description TEXT, "
 | 
											"Description TEXT, "
 | 
				
			||||||
						"Created BIGINT , "
 | 
											"Created BIGINT , "
 | 
				
			||||||
						"LastModified BIGINT)",
 | 
											"LastModified BIGINT, Platform TEXT)",
 | 
				
			||||||
					Poco::Data::Keywords::now;
 | 
										Poco::Data::Keywords::now;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								std::vector<std::string> Script{
 | 
				
			||||||
 | 
									"alter table DefaultConfigs add column Platform text"
 | 
				
			||||||
 | 
								};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								for (const auto &i : Script) {
 | 
				
			||||||
 | 
									try {
 | 
				
			||||||
 | 
										Sess << i, Poco::Data::Keywords::now;
 | 
				
			||||||
 | 
									} catch (...) {
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			return 0;
 | 
								return 0;
 | 
				
			||||||
		} catch (const Poco::Exception &E) {
 | 
							} catch (const Poco::Exception &E) {
 | 
				
			||||||
			Logger().log(E);
 | 
								Logger().log(E);
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user