mirror of
https://github.com/Telecominfraproject/wlan-cloud-ucentralgw.git
synced 2025-11-01 19:28:01 +00:00
Compare commits
321 Commits
v3.0.0-RC3
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
691d3399f8 | ||
|
|
6542726ac3 | ||
|
|
4bc753f8b5 | ||
|
|
e3a513fa6a | ||
|
|
b151239a5c | ||
|
|
862dab38d1 | ||
|
|
ee2e9a19c0 | ||
|
|
8b28fa0435 | ||
|
|
aeef70a121 | ||
|
|
42c421ec12 | ||
|
|
98bfb4b24d | ||
|
|
6b64089f55 | ||
|
|
1f6e42b57c | ||
|
|
f857d61377 | ||
|
|
66d580d047 | ||
|
|
567c671c22 | ||
|
|
9e3735ced8 | ||
|
|
18b169e517 | ||
|
|
cab0d8aee6 | ||
|
|
680b6a16e3 | ||
|
|
218694872f | ||
|
|
6ae1eeb2ea | ||
|
|
f537e701a0 | ||
|
|
d4dfb7b620 | ||
|
|
446cbf270f | ||
|
|
06ffee27b1 | ||
|
|
fa3c325bfa | ||
|
|
182a442582 | ||
|
|
3b7a24ea30 | ||
|
|
1c5909613f | ||
|
|
8e5e51a52a | ||
|
|
b4699e9178 | ||
|
|
438309714f | ||
|
|
a9130eeb75 | ||
|
|
33068fca9e | ||
|
|
d329151f6c | ||
|
|
ec846006bb | ||
|
|
bd48079a8d | ||
|
|
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 | ||
|
|
915a2c936d | ||
|
|
e1bf6a9ab7 | ||
|
|
58fc925a2f | ||
|
|
3dda87b41f | ||
|
|
a5fe59086a | ||
|
|
c66b936c1e | ||
|
|
0e763cf034 | ||
|
|
eb441d71aa | ||
|
|
082153a229 | ||
|
|
25a03ca801 | ||
|
|
0d549137de | ||
|
|
40e814cab8 | ||
|
|
e40d53f3e5 | ||
|
|
607507ce9a | ||
|
|
b3ec5b1e81 | ||
|
|
c52d3c92f6 | ||
|
|
d1216a8ac4 | ||
|
|
c27f0390f8 | ||
|
|
052d379e2b | ||
|
|
4eda1b813f | ||
|
|
5364adf509 | ||
|
|
3b5580a525 | ||
|
|
644918fa14 | ||
|
|
8cdd398a6e | ||
|
|
9f7f4683df | ||
|
|
1c6e35fa8b | ||
|
|
af17823df0 | ||
|
|
0cff2163bb | ||
|
|
0a5fe39bde | ||
|
|
c42feca957 | ||
|
|
d3c5b17733 | ||
|
|
30bc8e8283 | ||
|
|
336c94a25a | ||
|
|
84f42e5a7d | ||
|
|
17752fdefe | ||
|
|
ef300b0349 | ||
|
|
9c4ecb6165 | ||
|
|
efd099b6fa | ||
|
|
15805dcaf6 | ||
|
|
e5ed1750cc | ||
|
|
87d74568f2 | ||
|
|
0cca3caa9b | ||
|
|
1d22e1153f | ||
|
|
f3ccc49647 | ||
|
|
46fb410108 | ||
|
|
fc680a6bc4 | ||
|
|
246f9c8aad | ||
|
|
3f06f00a88 | ||
|
|
0288d905b7 | ||
|
|
135b63c021 | ||
|
|
12e07fa65f | ||
|
|
567c2d1514 | ||
|
|
b9bd768ca6 | ||
|
|
f2dec010ee | ||
|
|
329d8d4441 | ||
|
|
d4dbbeb54b | ||
|
|
b1c6884d49 | ||
|
|
3ffa35bb14 | ||
|
|
bd06722948 | ||
|
|
8c70ec5280 | ||
|
|
6c13d845f1 | ||
|
|
77cc0b250b | ||
|
|
a3c424d8fe | ||
|
|
3f834a967b | ||
|
|
4120aefcd4 | ||
|
|
909ee66ef0 | ||
|
|
c3ad34d84b | ||
|
|
fbb9f40529 | ||
|
|
5f6300bb17 | ||
|
|
0bcfb26579 | ||
|
|
5b199bc4f5 | ||
|
|
4c6fb85542 | ||
|
|
63993789ca | ||
|
|
cc9d4c5f68 | ||
|
|
50fa1de62c | ||
|
|
14ef6608d6 | ||
|
|
8e48d30d6a | ||
|
|
46c6321674 | ||
|
|
77f67fe545 | ||
|
|
ceda1fc8f6 | ||
|
|
5b1a4fb9c0 | ||
|
|
2ddc0d3117 | ||
|
|
2cfc6c30e9 | ||
|
|
0318b475f5 | ||
|
|
c5c2dc1a1e | ||
|
|
7b899adb88 | ||
|
|
aa472ed79e | ||
|
|
1778912264 | ||
|
|
142bc4f271 | ||
|
|
a01d006d4e | ||
|
|
135a195081 | ||
|
|
ef7cb883fb | ||
|
|
2e361a41d7 | ||
|
|
84281ec58e | ||
|
|
3560871f44 | ||
|
|
b072f1e2ab | ||
|
|
72173ed4b5 | ||
|
|
ff53d4ba2e | ||
|
|
81721b4a61 | ||
|
|
3619be1832 | ||
|
|
a8fc823b94 | ||
|
|
a8a33013be | ||
|
|
9560f908a6 | ||
|
|
8400b8cfcb | ||
|
|
82897f5b76 | ||
|
|
4b472fd112 | ||
|
|
ecb6312f0f | ||
|
|
0aba846277 | ||
|
|
5be884ef98 | ||
|
|
10c890a196 | ||
|
|
0974abd510 | ||
|
|
8dbbfc3298 | ||
|
|
c981ae14ee | ||
|
|
97547068d7 | ||
|
|
16cc443786 |
2
.github/workflows/ci.yml
vendored
2
.github/workflows/ci.yml
vendored
@@ -21,7 +21,7 @@ defaults:
|
||||
|
||||
jobs:
|
||||
docker:
|
||||
runs-on: ubuntu-20.04
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
DOCKER_REGISTRY_URL: tip-tip-wlan-cloud-ucentral.jfrog.io
|
||||
DOCKER_REGISTRY_USERNAME: ucentral
|
||||
|
||||
2
.github/workflows/release.yml
vendored
2
.github/workflows/release.yml
vendored
@@ -11,7 +11,7 @@ defaults:
|
||||
|
||||
jobs:
|
||||
helm-package:
|
||||
runs-on: ubuntu-20.04
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
HELM_REPO_URL: https://tip.jfrog.io/artifactory/tip-wlan-cloud-ucentral-helm/
|
||||
HELM_REPO_USERNAME: ucentral
|
||||
|
||||
4
.gitignore
vendored
4
.gitignore
vendored
@@ -21,10 +21,12 @@ _deps
|
||||
/docker-compose/.env
|
||||
/docker-compose/.env_*
|
||||
/cmake-build/
|
||||
/uploads/
|
||||
test_scripts/curl/token.json
|
||||
.vscode/c_cpp_properties.json
|
||||
test_scripts/curl/result.json
|
||||
*.swp
|
||||
helm/charts/*
|
||||
!helm/charts/.gitkeep
|
||||
/portal-test/
|
||||
/src/ow_version.h
|
||||
.vscode/*
|
||||
|
||||
2
.idea/.gitignore
generated
vendored
2
.idea/.gitignore
generated
vendored
@@ -6,3 +6,5 @@
|
||||
/dataSources.local.xml
|
||||
# Editor-based HTTP Client requests
|
||||
/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"?>
|
||||
<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="CidrRootsConfiguration">
|
||||
<excludeRoots>
|
||||
|
||||
62
BUILDING.md
62
BUILDING.md
@@ -1,5 +1,5 @@
|
||||
# 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
|
||||
- boost
|
||||
- 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
|
||||
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.
|
||||
|
||||
## Ubuntu
|
||||
These instructions have proven to work on Ubuntu 20.4.
|
||||
```bash
|
||||
sudo apt install git cmake g++ libssl-dev libmariadb-dev
|
||||
sudo apt install libpq-dev libaprutil1-dev apache2-dev libboost-all-dev
|
||||
sudo apt install librdkafka-dev // default-libmysqlclient-dev
|
||||
sudo apt install nlohmann-json-dev
|
||||
sudo apt install git cmake g++ libssl-dev libmariadb-dev \
|
||||
libpq-dev libaprutil1-dev apache2-dev libboost-all-dev \
|
||||
librdkafka-dev // default-libmysqlclient-dev \
|
||||
nlohmann-json-dev
|
||||
|
||||
cd ~
|
||||
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
|
||||
mkdir cmake-build
|
||||
cd cmake-build
|
||||
cmake ..
|
||||
cmake --build . --config Release
|
||||
sudo cmake --build . --target install
|
||||
cd ../..
|
||||
|
||||
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
|
||||
mkdir cmake-build
|
||||
cd cmake-build
|
||||
cmake ..
|
||||
cmake --build . --config Release
|
||||
sudo cmake --build . --target install
|
||||
cd ../..
|
||||
|
||||
cd ~
|
||||
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
|
||||
mkdir cmake-build
|
||||
cd cmake-build
|
||||
cmake ..
|
||||
cmake --build . --config Release
|
||||
sudo cmake --build . --target install
|
||||
cd ../..
|
||||
|
||||
git clone https://github.com/fmtlib/fmt --branch 9.0.0 /fmtlib
|
||||
cd fmtlib
|
||||
@@ -57,56 +57,59 @@ cd cmake-build
|
||||
cmake ..
|
||||
make
|
||||
make install
|
||||
cd ../..
|
||||
|
||||
cd ~
|
||||
git clone https://github.com/Telecominfraproject/wlan-cloud-ucentralgw
|
||||
cd wlan-cloud-ucentralgw
|
||||
mkdir cmake-build
|
||||
cd cmake-build
|
||||
cmake ..
|
||||
make -j 8
|
||||
cd ../..
|
||||
```
|
||||
|
||||
## Fedora
|
||||
The following instructions have proven to work on Fedora 33
|
||||
```bash
|
||||
sudo yum install cmake g++ openssl-devel mysql-devel mysql apr-util-devel boost boost-devel
|
||||
sudo yum install yaml-cpp-devel lua-devel
|
||||
sudo yum install cmake g++ openssl-devel mysql-devel mysql apr-util-devel boost boost-devel \
|
||||
yaml-cpp-devel lua-devel
|
||||
sudo dnf install postgresql.x86_64 librdkafka-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
|
||||
mkdir cmake-build
|
||||
cd cmake-build
|
||||
cmake ..
|
||||
cmake --build . --config Release
|
||||
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
|
||||
mkdir cmake-build
|
||||
cd cmake-build
|
||||
cmake ..
|
||||
cmake --build . --config Release
|
||||
sudo cmake --build . --target install
|
||||
cd ../..
|
||||
|
||||
cd ~
|
||||
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
|
||||
mkdir cmake-build
|
||||
cd cmake-build
|
||||
cmake ..
|
||||
cmake --build . --config Release
|
||||
sudo cmake --build . --target install
|
||||
cd ../..
|
||||
|
||||
cd ~
|
||||
git clone https://github.com/Telecominfraproject/wlan-cloud-ucentralgw
|
||||
cd wlan-cloud-ucentralgw
|
||||
mkdir cmake-build
|
||||
cd cmake-build
|
||||
cmake ..
|
||||
make
|
||||
cd ../..
|
||||
```
|
||||
|
||||
## macOS Build
|
||||
@@ -125,7 +128,7 @@ brew install openssl \
|
||||
nlohmann-json \
|
||||
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
|
||||
mkdir cmake-build
|
||||
push cmake-build
|
||||
@@ -135,7 +138,7 @@ sudo cmake --build . --target install
|
||||
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
|
||||
mkdir cmake-build
|
||||
pushd cmake-build
|
||||
@@ -145,10 +148,10 @@ sudo cmake --build . --target install
|
||||
popd
|
||||
popd
|
||||
|
||||
git clone https://github.com/AriliaWireless/valijson --branch tip-v1
|
||||
cd valijson
|
||||
git clone https://github.com/Telecominfraproject/wlan-cloud-lib-valijson --branch tip-v1 valijson
|
||||
pushd valijson
|
||||
mkdir cmake-build
|
||||
cd cmake-build
|
||||
pushd cmake-build
|
||||
cmake ..
|
||||
cmake --build . --config Release
|
||||
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.
|
||||
|
||||
```bash
|
||||
sudo apt install git cmake g++ libssl-dev libaprutil1-dev apache2-dev libboost-all-dev libyaml-cpp-dev
|
||||
git clone https://github.com/stephb9959/poco
|
||||
sudo apt install git cmake g++ libssl-dev libaprutil1-dev apache2-dev \
|
||||
libboost-all-dev libyaml-cpp-dev
|
||||
|
||||
git clone https://github.com/Telecominfraproject/wlan-cloud-lib-poco --branch poco-tip-v1 poco
|
||||
cd poco
|
||||
mkdir cmake-build
|
||||
cd cmake-build
|
||||
cmake ..
|
||||
cmake --build . --config Release
|
||||
sudo cmake --build . --target install
|
||||
cd ../..
|
||||
|
||||
cd ~
|
||||
git clone https://github.com/Telecominfraproject/wlan-cloud-ucentralgw
|
||||
cd wlan-cloud-ucentralgw
|
||||
mkdir cmake-build
|
||||
cd cmake-build
|
||||
cmake -DSMALL_BUILD=1 ..
|
||||
make
|
||||
cd ../..
|
||||
```
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
cmake_minimum_required(VERSION 3.13)
|
||||
project(owgw VERSION 3.0.0)
|
||||
project(owgw VERSION 4.1.1)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
set(CMAKE_CXX_STANDARD 20)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED True)
|
||||
|
||||
if(UNIX AND APPLE)
|
||||
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_regulatory.cpp src/RESTAPI/RESTAPI_regulatory.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_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
|
||||
@@ -175,7 +177,7 @@ add_executable( owgw
|
||||
src/SDKcalls.cpp
|
||||
src/SDKcalls.h
|
||||
src/StateUtils.cpp src/StateUtils.h
|
||||
src/AP_WS_ReactorPool.h
|
||||
src/AP_WS_Reactor_Pool.h
|
||||
src/AP_WS_Connection.h
|
||||
src/AP_WS_Connection.cpp
|
||||
src/TelemetryClient.h src/TelemetryClient.cpp
|
||||
@@ -211,7 +213,8 @@ add_executable( owgw
|
||||
src/RegulatoryInfo.cpp src/RegulatoryInfo.h
|
||||
src/RADIUSSessionTracker.cpp src/RADIUSSessionTracker.h
|
||||
src/libs/Scheduler.h src/libs/InterruptableSleep.h src/libs/ctpl_stl.h src/libs/Cron.h
|
||||
src/GenericScheduler.cpp src/GenericScheduler.h src/framework/default_device_types.h src/AP_WS_Process_rebootLog.cpp src/AP_WS_ConfigAutoUpgrader.cpp src/AP_WS_ConfigAutoUpgrader.h src/RESTAPI/RESTAPI_default_firmwares.cpp src/RESTAPI/RESTAPI_default_firmwares.h src/RESTAPI/RESTAPI_default_firmware.cpp src/RESTAPI/RESTAPI_default_firmware.h src/storage/storage_def_firmware.cpp src/firmware_revision_cache.h src/sdks/sdk_fms.h)
|
||||
src/GenericScheduler.cpp src/GenericScheduler.h src/framework/default_device_types.h src/AP_WS_Process_rebootLog.cpp src/AP_WS_ConfigAutoUpgrader.cpp src/AP_WS_ConfigAutoUpgrader.h src/RESTAPI/RESTAPI_default_firmwares.cpp src/RESTAPI/RESTAPI_default_firmwares.h src/RESTAPI/RESTAPI_default_firmware.cpp src/RESTAPI/RESTAPI_default_firmware.h src/storage/storage_def_firmware.cpp src/firmware_revision_cache.h src/sdks/sdk_fms.h
|
||||
src/AP_WS_LookForUpgrade.cpp)
|
||||
|
||||
if(NOT SMALL_BUILD)
|
||||
|
||||
|
||||
20
Dockerfile
20
Dockerfile
@@ -1,7 +1,7 @@
|
||||
ARG DEBIAN_VERSION=11.5-slim
|
||||
ARG POCO_VERSION=poco-tip-v2
|
||||
ARG DEBIAN_VERSION=bookworm
|
||||
ARG POCO_VERSION=poco-tip-v4-tag
|
||||
ARG CPPKAFKA_VERSION=tip-v1
|
||||
ARG VALIJASON_VERSION=tip-v1
|
||||
ARG VALIJASON_VERSION=tip-v1.0.2
|
||||
ARG APP_NAME=owgw
|
||||
ARG APP_HOME_DIR=/openwifi
|
||||
|
||||
@@ -17,8 +17,8 @@ FROM build-base AS poco-build
|
||||
|
||||
ARG POCO_VERSION
|
||||
|
||||
ADD https://api.github.com/repos/AriliaWireless/poco/git/refs/tags/${POCO_VERSION} version.json
|
||||
RUN git clone https://github.com/AriliaWireless/poco --branch ${POCO_VERSION} /poco
|
||||
ADD https://api.github.com/repos/Telecominfraproject/wlan-cloud-lib-poco/git/refs/tags/${POCO_VERSION} version.json
|
||||
RUN git clone https://github.com/Telecominfraproject/wlan-cloud-lib-poco --branch ${POCO_VERSION} /poco
|
||||
|
||||
WORKDIR /poco
|
||||
RUN mkdir cmake-build
|
||||
@@ -31,8 +31,8 @@ FROM build-base AS cppkafka-build
|
||||
|
||||
ARG CPPKAFKA_VERSION
|
||||
|
||||
ADD https://api.github.com/repos/AriliaWireless/cppkafka/git/refs/tags/${CPPKAFKA_VERSION} version.json
|
||||
RUN git clone https://github.com/AriliaWireless/cppkafka --branch ${CPPKAFKA_VERSION} /cppkafka
|
||||
ADD https://api.github.com/repos/Telecominfraproject/wlan-cloud-lib-cppkafka/git/refs/tags/${CPPKAFKA_VERSION} version.json
|
||||
RUN git clone https://github.com/Telecominfraproject/wlan-cloud-lib-cppkafka --branch ${CPPKAFKA_VERSION} /cppkafka
|
||||
|
||||
WORKDIR /cppkafka
|
||||
RUN mkdir cmake-build
|
||||
@@ -45,8 +45,8 @@ FROM build-base AS valijson-build
|
||||
|
||||
ARG VALIJASON_VERSION
|
||||
|
||||
ADD https://api.github.com/repos/AriliaWireless/valijson/git/refs/tags/${VALIJASON_VERSION} version.json
|
||||
RUN git clone https://github.com/AriliaWireless/valijson --branch ${VALIJASON_VERSION} /valijson
|
||||
ADD https://api.github.com/repos/Telecominfraproject/wlan-cloud-lib-valijson/git/refs/tags/${VALIJASON_VERSION} version.json
|
||||
RUN git clone https://github.com/Telecominfraproject/wlan-cloud-lib-valijson --branch ${VALIJASON_VERSION} /valijson
|
||||
|
||||
WORKDIR /valijson
|
||||
RUN mkdir cmake-build
|
||||
@@ -100,7 +100,7 @@ RUN mkdir -p $APP_ROOT $APP_CONFIG && \
|
||||
|
||||
RUN apt-get update && apt-get install --no-install-recommends -y \
|
||||
librdkafka++1 gosu gettext ca-certificates bash jq curl wget \
|
||||
libmariadb-dev-compat libpq5 unixodbc postgresql-client libfmt7 sqlite3
|
||||
libmariadb-dev-compat libpq5 unixodbc postgresql-client libfmt9 sqlite3
|
||||
|
||||
COPY readiness_check /readiness_check
|
||||
COPY test_scripts/curl/cli /cli
|
||||
|
||||
105
PROTOCOL.md
105
PROTOCOL.md
@@ -306,8 +306,54 @@ The device should answer:
|
||||
},
|
||||
"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 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
|
||||
@@ -355,6 +401,39 @@ The device should answer:
|
||||
- 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 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 sends this command when it believes the device should upgrade its firmware.
|
||||
```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 sends this when the device should change the controller it connects to without looking up a new redirector.
|
||||
|
||||
|
||||
@@ -32,6 +32,7 @@ if [[ "$TEMPLATE_CONFIG" = 'true' ]]; then
|
||||
FILEUPLOADER_HOST_KEY_PASSWORD=${FILEUPLOADER_HOST_KEY_PASSWORD:-"mypassword"} \
|
||||
FILEUPLOADER_PATH=${FILEUPLOADER_PATH:-"\${APP_ROOT}/uploads"} \
|
||||
FILEUPLOADER_URI=${FILEUPLOADER_URI:-"https://localhost:16003"} \
|
||||
FILEUPLOADER_MAXSIZE=${FILEUPLOADER_MAXSIZE:-"10000"} \
|
||||
SERVICE_KEY=${SERVICE_KEY:-"\${APP_ROOT}/certs/restapi-key.pem"} \
|
||||
SERVICE_KEY_PASSWORD=${SERVICE_KEY_PASSWORD:-"mypassword"} \
|
||||
SYSTEM_DATA=${SYSTEM_DATA:-"\${APP_ROOT}/data"} \
|
||||
@@ -76,6 +77,7 @@ if [[ "$TEMPLATE_CONFIG" = 'true' ]]; then
|
||||
CERTIFICATES_ALLOWMISMATCH=${CERTIFICATES_ALLOWMISMATCH:-"false"} \
|
||||
IPINFO_DEFAULT_COUNTRY=${IPINFO_DEFAULT_COUNTRY:-"US"} \
|
||||
DEVICE_SESSION_TIMEOUT=${DEVICE_SESSION_TIMEOUT:-"600"} \
|
||||
LOGGING_LEVEL=${LOGGING_LEVEL:-"information"} \
|
||||
envsubst < /"${APP_NAME}".properties.tmpl > "${APP_CONFIG}"/"${APP_NAME}".properties
|
||||
fi
|
||||
|
||||
|
||||
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
|
||||
|
||||
servers:
|
||||
- url: 'https://localhost:16001/api/v1'
|
||||
- url: 'https://localhost:16002/api/v1'
|
||||
|
||||
security:
|
||||
- bearerAuth: []
|
||||
@@ -42,12 +42,10 @@ components:
|
||||
schemas:
|
||||
DeviceType:
|
||||
type: string
|
||||
default: AP
|
||||
default: ap
|
||||
enum:
|
||||
- AP
|
||||
- SWITCH
|
||||
- IOT
|
||||
- MESH
|
||||
- ap
|
||||
- switch
|
||||
|
||||
DeviceRestrictionsKeyInfo:
|
||||
type: object
|
||||
@@ -157,6 +155,9 @@ components:
|
||||
lastRecordedContact:
|
||||
type: integer
|
||||
format: int64
|
||||
blackListed:
|
||||
type: boolean
|
||||
readOnly: true
|
||||
|
||||
DeviceWithStatus:
|
||||
type: object
|
||||
@@ -281,6 +282,9 @@ components:
|
||||
format: float
|
||||
connectReason:
|
||||
type: string
|
||||
blackListed:
|
||||
type: boolean
|
||||
readOnly: true
|
||||
|
||||
DeviceList:
|
||||
type: object
|
||||
@@ -545,6 +549,12 @@ components:
|
||||
lastModified:
|
||||
type: integer
|
||||
format: int64
|
||||
platform:
|
||||
type: string
|
||||
enum:
|
||||
- ap
|
||||
- switch
|
||||
default: ap
|
||||
|
||||
DefaultConfigurationList:
|
||||
properties:
|
||||
@@ -1566,6 +1576,107 @@ components:
|
||||
format: base64
|
||||
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
|
||||
|
||||
PackageGetResponse:
|
||||
type: object
|
||||
properties:
|
||||
serial:
|
||||
type: string
|
||||
status:
|
||||
type: object
|
||||
properties:
|
||||
package:
|
||||
type: string
|
||||
text:
|
||||
type: string
|
||||
uuid:
|
||||
type: number
|
||||
|
||||
|
||||
PackageInstallRequest:
|
||||
type: object
|
||||
properties:
|
||||
serialNumber:
|
||||
type: string
|
||||
packages:
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
properties:
|
||||
name:
|
||||
type: string
|
||||
url:
|
||||
type: string
|
||||
|
||||
PackageInstallResponse:
|
||||
type: object
|
||||
properties:
|
||||
serial:
|
||||
type: string
|
||||
status:
|
||||
type: object
|
||||
properties:
|
||||
error:
|
||||
type: number
|
||||
packages:
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
properties:
|
||||
name:
|
||||
type: string
|
||||
result:
|
||||
type: string
|
||||
text:
|
||||
type: string
|
||||
uuid:
|
||||
type: number
|
||||
|
||||
PackageRemoveRequest:
|
||||
type: object
|
||||
properties:
|
||||
serialNumber:
|
||||
type: string
|
||||
packages:
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
properties:
|
||||
name:
|
||||
type: string
|
||||
|
||||
paths:
|
||||
/devices:
|
||||
get:
|
||||
@@ -1657,6 +1768,22 @@ paths:
|
||||
type: integer
|
||||
default: 70
|
||||
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:
|
||||
200:
|
||||
description: List devices
|
||||
@@ -3006,6 +3133,152 @@ paths:
|
||||
404:
|
||||
$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'
|
||||
|
||||
/device/{serialNumber}/package:
|
||||
get:
|
||||
tags:
|
||||
- Commands
|
||||
summary: Get package installed on the remote device.
|
||||
operationId: getDevicePackages
|
||||
parameters:
|
||||
- in: path
|
||||
name: serialNumber
|
||||
schema:
|
||||
type: string
|
||||
required: true
|
||||
- in: query
|
||||
name: pkgName
|
||||
schema:
|
||||
type: string
|
||||
required: true
|
||||
description: The name or identifier of the package to retrieve.
|
||||
responses:
|
||||
200:
|
||||
description: Successful command execution
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/PackageGetResponse'
|
||||
403:
|
||||
$ref: '#/components/responses/Unauthorized'
|
||||
404:
|
||||
$ref: '#/components/responses/NotFound'
|
||||
|
||||
post:
|
||||
tags:
|
||||
- Commands
|
||||
summary: Install IPK files to remote device.
|
||||
operationId: postDevicePackages
|
||||
parameters:
|
||||
- in: path
|
||||
name: serialNumber
|
||||
schema:
|
||||
type: string
|
||||
required: true
|
||||
requestBody:
|
||||
description: Packages to be installed
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/PackageInstallRequest'
|
||||
responses:
|
||||
200:
|
||||
description: Successful command execution
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/PackageInstallResponse'
|
||||
|
||||
400:
|
||||
$ref: '#/components/responses/BadRequest'
|
||||
403:
|
||||
$ref: '#/components/responses/Unauthorized'
|
||||
404:
|
||||
$ref: '#/components/responses/NotFound'
|
||||
|
||||
delete:
|
||||
tags:
|
||||
- Commands
|
||||
summary: Remove install packages from remote device.
|
||||
operationId: deleteDevicePackages
|
||||
parameters:
|
||||
- in: path
|
||||
name: serialNumber
|
||||
schema:
|
||||
type: string
|
||||
required: true
|
||||
requestBody:
|
||||
description: Packages to be removed
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/PackageRemoveRequest'
|
||||
responses:
|
||||
200:
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/PackageInstallResponse'
|
||||
400:
|
||||
$ref: '#/components/responses/BadRequest'
|
||||
403:
|
||||
$ref: '#/components/responses/Unauthorized'
|
||||
404:
|
||||
$ref: '#/components/responses/NotFound'
|
||||
|
||||
/ouis:
|
||||
get:
|
||||
tags:
|
||||
|
||||
@@ -52,7 +52,8 @@ openwifi.fileuploader.host.0.cert = ${FILEUPLOADER_HOST_CERT}
|
||||
openwifi.fileuploader.host.0.key = ${FILEUPLOADER_HOST_KEY}
|
||||
openwifi.fileuploader.host.0.key.password = ${FILEUPLOADER_HOST_KEY_PASSWORD}
|
||||
openwifi.fileuploader.path = ${FILEUPLOADER_PATH}
|
||||
openwifi.fileuploader.maxsize = 10000
|
||||
# maxsize in KB
|
||||
openwifi.fileuploader.maxsize = ${FILEUPLOADER_MAXSIZE}
|
||||
openwifi.fileuploader.uri = ${FILEUPLOADER_URI}
|
||||
|
||||
#
|
||||
@@ -145,7 +146,7 @@ storage.type.sqlite.db = devices.db
|
||||
storage.type.sqlite.idletime = 120
|
||||
storage.type.sqlite.maxsessions = 128
|
||||
|
||||
storage.type.postgresql.maxsessions = 64
|
||||
storage.type.postgresql.maxsessions = 250
|
||||
storage.type.postgresql.idletime = 60
|
||||
storage.type.postgresql.host = ${STORAGE_TYPE_POSTGRESQL_HOST}
|
||||
storage.type.postgresql.username = ${STORAGE_TYPE_POSTGRESQL_USERNAME}
|
||||
@@ -182,4 +183,4 @@ archiver.db.3.keep = 7
|
||||
########################################################################
|
||||
logging.type = console
|
||||
logging.path = $OWGW_ROOT/logs
|
||||
logging.level = information
|
||||
logging.level = ${LOGGING_LEVEL}
|
||||
|
||||
@@ -9,14 +9,14 @@
|
||||
|
||||
namespace OpenWifi {
|
||||
|
||||
int AP_WS_ConfigAutoUpgrader::Start() {
|
||||
int AP_WS_ConfigAutoUpgradeAgent::Start() {
|
||||
poco_notice(Logger(), "Starting...");
|
||||
QueueManager_.start(*this);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void AP_WS_ConfigAutoUpgrader::Stop() {
|
||||
void AP_WS_ConfigAutoUpgradeAgent::Stop() {
|
||||
poco_notice(Logger(), "Stopping...");
|
||||
Running_ = false;
|
||||
Queue_.wakeUpAll();
|
||||
@@ -24,7 +24,7 @@ namespace OpenWifi {
|
||||
poco_notice(Logger(), "Stopped...");
|
||||
}
|
||||
|
||||
void AP_WS_ConfigAutoUpgrader::run() {
|
||||
void AP_WS_ConfigAutoUpgradeAgent::run() {
|
||||
Utils::SetThreadName("auto:cfgmgr");
|
||||
Running_ = true;
|
||||
|
||||
|
||||
@@ -28,14 +28,14 @@ namespace OpenWifi {
|
||||
std::uint64_t pending_config_=0;
|
||||
};
|
||||
|
||||
class AP_WS_ConfigAutoUpgrader : public SubSystemServer, Poco::Runnable {
|
||||
class AP_WS_ConfigAutoUpgradeAgent : public SubSystemServer, Poco::Runnable {
|
||||
public:
|
||||
int Start() final;
|
||||
void Stop() final;
|
||||
void run() final;
|
||||
|
||||
static auto instance() {
|
||||
static auto instance = new AP_WS_ConfigAutoUpgrader;
|
||||
static auto instance = new AP_WS_ConfigAutoUpgradeAgent;
|
||||
return instance;
|
||||
}
|
||||
|
||||
@@ -126,12 +126,12 @@ namespace OpenWifi {
|
||||
mutable std::mutex CacheMutex_;
|
||||
std::map<std::uint64_t, ConfigurationCacheEntry> Cache_;
|
||||
|
||||
AP_WS_ConfigAutoUpgrader() noexcept
|
||||
AP_WS_ConfigAutoUpgradeAgent() noexcept
|
||||
: 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
|
||||
|
||||
|
||||
@@ -2,56 +2,50 @@
|
||||
// Created by stephane bourque on 2022-02-03.
|
||||
//
|
||||
|
||||
#include "AP_WS_Connection.h"
|
||||
|
||||
#include "Poco/Base64Decoder.h"
|
||||
#include "Poco/Net/Context.h"
|
||||
#include "Poco/Net/HTTPServerRequestImpl.h"
|
||||
#include "Poco/Net/HTTPServerResponseImpl.h"
|
||||
#include "Poco/Net/NetException.h"
|
||||
#include "Poco/Net/SSLException.h"
|
||||
#include "Poco/Net/SecureStreamSocketImpl.h"
|
||||
#include "Poco/Net/WebSocketImpl.h"
|
||||
#include "Poco/zlib.h"
|
||||
#include <Poco/Base64Decoder.h>
|
||||
#include <Poco/Net/Context.h>
|
||||
#include <Poco/Net/HTTPServerRequestImpl.h>
|
||||
#include <Poco/Net/HTTPServerResponseImpl.h>
|
||||
#include <Poco/JSON/JSONException.h>
|
||||
#include <Poco/Net/NetException.h>
|
||||
#include <Poco/Net/SSLException.h>
|
||||
#include <Poco/Net/SecureStreamSocketImpl.h>
|
||||
#include <Poco/Net/WebSocketImpl.h>
|
||||
|
||||
#include "AP_WS_Server.h"
|
||||
#include "CentralConfig.h"
|
||||
#include "CommandManager.h"
|
||||
#include "ConfigurationCache.h"
|
||||
#include "StorageService.h"
|
||||
#include "TelemetryStream.h"
|
||||
#include <framework/KafkaManager.h>
|
||||
#include <framework/MicroServiceFuncs.h>
|
||||
#include <framework/utils.h>
|
||||
#include <framework/ow_constants.h>
|
||||
|
||||
#include "GWKafkaEvents.h"
|
||||
#include "UI_GW_WebSocketNotifications.h"
|
||||
#include "framework/KafkaManager.h"
|
||||
#include "framework/MicroServiceFuncs.h"
|
||||
#include "framework/utils.h"
|
||||
#include <fmt/format.h>
|
||||
|
||||
#include "fmt/format.h"
|
||||
|
||||
#include "framework/ow_constants.h"
|
||||
|
||||
#include "RADIUSSessionTracker.h"
|
||||
#include "RADIUS_proxy_server.h"
|
||||
#include <AP_WS_Connection.h>
|
||||
#include <AP_WS_Server.h>
|
||||
#include <CentralConfig.h>
|
||||
#include <CommandManager.h>
|
||||
#include <StorageService.h>
|
||||
#include <RADIUSSessionTracker.h>
|
||||
#include <RADIUS_proxy_server.h>
|
||||
#include <GWKafkaEvents.h>
|
||||
#include <UI_GW_WebSocketNotifications.h>
|
||||
|
||||
namespace OpenWifi {
|
||||
|
||||
#define DBL \
|
||||
{ \
|
||||
std::cout << __LINE__ << " ID: " << ConnectionId_ << " Ser: " << SerialNumber_ \
|
||||
<< std::endl; \
|
||||
}
|
||||
|
||||
void AP_WS_Connection::LogException(const Poco::Exception &E) {
|
||||
poco_information(Logger_, fmt::format("EXCEPTION({}): {}", CId_, E.displayText()));
|
||||
}
|
||||
|
||||
AP_WS_Connection::AP_WS_Connection(Poco::Net::HTTPServerRequest &request,
|
||||
Poco::Net::HTTPServerResponse &response,
|
||||
uint64_t connection_id, Poco::Logger &L,
|
||||
Poco::Net::SocketReactor &R)
|
||||
: Logger_(L), Reactor_(R) {
|
||||
State_.sessionId = connection_id;
|
||||
uint64_t session_id, Poco::Logger &L,
|
||||
std::pair<std::shared_ptr<Poco::Net::SocketReactor>, std::shared_ptr<LockedDbSession>> R)
|
||||
: Logger_(L), IncomingFrame_(0) {
|
||||
|
||||
Reactor_ = R.first;
|
||||
DbSession_ = R.second;
|
||||
State_.sessionId = session_id;
|
||||
|
||||
WS_ = std::make_unique<Poco::Net::WebSocket>(request, response);
|
||||
|
||||
auto TS = Poco::Timespan(360, 0);
|
||||
@@ -61,29 +55,87 @@ namespace OpenWifi {
|
||||
WS_->setNoDelay(false);
|
||||
WS_->setKeepAlive(true);
|
||||
WS_->setBlocking(false);
|
||||
|
||||
Reactor_.addEventHandler(*WS_,
|
||||
Poco::NObserver<AP_WS_Connection, Poco::Net::ReadableNotification>(
|
||||
*this, &AP_WS_Connection::OnSocketReadable));
|
||||
Reactor_.addEventHandler(*WS_,
|
||||
Poco::NObserver<AP_WS_Connection, Poco::Net::ShutdownNotification>(
|
||||
*this, &AP_WS_Connection::OnSocketShutdown));
|
||||
Reactor_.addEventHandler(*WS_,
|
||||
Poco::NObserver<AP_WS_Connection, Poco::Net::ErrorNotification>(
|
||||
*this, &AP_WS_Connection::OnSocketError));
|
||||
Registered_ = true;
|
||||
Valid_ = true;
|
||||
IncomingFrame_.resize(0);
|
||||
uuid_ = MicroServiceRandom(std::numeric_limits<std::uint64_t>::max()-1);
|
||||
|
||||
AP_WS_Server()->IncrementConnectionCount();
|
||||
}
|
||||
|
||||
void AP_WS_Connection::Start() {
|
||||
Registered_ = true;
|
||||
LastContact_ = Utils::Now();
|
||||
|
||||
Reactor_->addEventHandler(*WS_,
|
||||
Poco::NObserver<AP_WS_Connection, Poco::Net::ReadableNotification>(
|
||||
*this, &AP_WS_Connection::OnSocketReadable));
|
||||
Reactor_->addEventHandler(*WS_,
|
||||
Poco::NObserver<AP_WS_Connection, Poco::Net::ShutdownNotification>(
|
||||
*this, &AP_WS_Connection::OnSocketShutdown));
|
||||
Reactor_->addEventHandler(*WS_,
|
||||
Poco::NObserver<AP_WS_Connection, Poco::Net::ErrorNotification>(
|
||||
*this, &AP_WS_Connection::OnSocketError));
|
||||
|
||||
}
|
||||
|
||||
AP_WS_Connection::~AP_WS_Connection() {
|
||||
std::lock_guard G(ConnectionMutex_);
|
||||
AP_WS_Server()->DecrementConnectionCount();
|
||||
EndConnection();
|
||||
poco_debug(Logger_, fmt::format("TERMINATION({}): Session={}, Connection removed.", SerialNumber_,
|
||||
State_.sessionId));
|
||||
}
|
||||
|
||||
static void NotifyKafkaDisconnect(const std::string &SerialNumber, std::uint64_t uuid) {
|
||||
try {
|
||||
Poco::JSON::Object Disconnect;
|
||||
Poco::JSON::Object Details;
|
||||
Details.set(uCentralProtocol::SERIALNUMBER, SerialNumber);
|
||||
Details.set(uCentralProtocol::TIMESTAMP, Utils::Now());
|
||||
Details.set(uCentralProtocol::UUID,uuid);
|
||||
Disconnect.set(uCentralProtocol::DISCONNECTION, Details);
|
||||
KafkaManager()->PostMessage(KafkaTopics::CONNECTION, SerialNumber, Disconnect);
|
||||
} catch (...) {
|
||||
}
|
||||
}
|
||||
|
||||
void AP_WS_Connection::EndConnection() {
|
||||
bool expectedValue=false;
|
||||
if (Dead_.compare_exchange_strong(expectedValue,true,std::memory_order_release,std::memory_order_relaxed)) {
|
||||
|
||||
if(!SerialNumber_.empty() && State_.LastContact!=0) {
|
||||
StorageService()->SetDeviceLastRecordedContact(SerialNumber_, State_.LastContact);
|
||||
}
|
||||
|
||||
if (Registered_) {
|
||||
Registered_ = false;
|
||||
Reactor_->removeEventHandler(
|
||||
*WS_, Poco::NObserver<AP_WS_Connection, Poco::Net::ReadableNotification>(
|
||||
*this, &AP_WS_Connection::OnSocketReadable));
|
||||
Reactor_->removeEventHandler(
|
||||
*WS_, Poco::NObserver<AP_WS_Connection, Poco::Net::ShutdownNotification>(
|
||||
*this, &AP_WS_Connection::OnSocketShutdown));
|
||||
Reactor_->removeEventHandler(
|
||||
*WS_, Poco::NObserver<AP_WS_Connection, Poco::Net::ErrorNotification>(
|
||||
*this, &AP_WS_Connection::OnSocketError));
|
||||
Registered_=false;
|
||||
}
|
||||
WS_->close();
|
||||
|
||||
if(!SerialNumber_.empty()) {
|
||||
DeviceDisconnectionCleanup(SerialNumber_, uuid_);
|
||||
}
|
||||
AP_WS_Server()->AddCleanupSession(State_.sessionId, SerialNumberInt_);
|
||||
}
|
||||
}
|
||||
|
||||
bool AP_WS_Connection::ValidatedDevice() {
|
||||
|
||||
if(Dead_)
|
||||
return false;
|
||||
|
||||
if (DeviceValidated_)
|
||||
return true;
|
||||
|
||||
if (!Valid_)
|
||||
return false;
|
||||
|
||||
std::lock_guard Lock(ConnectionMutex_);
|
||||
try {
|
||||
auto SockImpl = dynamic_cast<Poco::Net::WebSocketImpl *>(WS_->impl());
|
||||
auto SS =
|
||||
@@ -98,7 +150,6 @@ namespace OpenWifi {
|
||||
poco_warning(Logger_, fmt::format("TLS-CONNECTION({}): Session={} Connection is "
|
||||
"NOT secure. Device is not allowed.",
|
||||
CId_, State_.sessionId));
|
||||
EndConnection();
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -111,7 +162,6 @@ namespace OpenWifi {
|
||||
Logger_,
|
||||
fmt::format("TLS-CONNECTION({}): Session={} No certificates available..", CId_,
|
||||
State_.sessionId));
|
||||
EndConnection();
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -122,11 +172,19 @@ namespace OpenWifi {
|
||||
fmt::format("TLS-CONNECTION({}): Session={} Device certificate is not "
|
||||
"valid. Device is not allowed.",
|
||||
CId_, State_.sessionId));
|
||||
EndConnection();
|
||||
return false;
|
||||
}
|
||||
|
||||
CN_ = Poco::trim(Poco::toLower(PeerCert.commonName()));
|
||||
if(!Utils::ValidSerialNumber(CN_)) {
|
||||
poco_trace(Logger_,
|
||||
fmt::format("TLS-CONNECTION({}): Session={} Invalid serial number: CN={}", CId_,
|
||||
State_.sessionId, CN_));
|
||||
return false;
|
||||
}
|
||||
SerialNumber_ = CN_;
|
||||
SerialNumberInt_ = Utils::SerialNumberToInt(SerialNumber_);
|
||||
|
||||
State_.VerifiedCertificate = GWObjects::VALID_CERTIFICATE;
|
||||
poco_trace(Logger_,
|
||||
fmt::format("TLS-CONNECTION({}): Session={} Valid certificate: CN={}", CId_,
|
||||
@@ -136,31 +194,28 @@ namespace OpenWifi {
|
||||
poco_warning(Logger_, fmt::format("TLS-CONNECTION({}): Session={} Sim Device {} is "
|
||||
"not allowed. Disconnecting.",
|
||||
CId_, State_.sessionId, CN_));
|
||||
EndConnection();
|
||||
return false;
|
||||
}
|
||||
|
||||
if(AP_WS_Server::IsSim(CN_)) {
|
||||
if(AP_WS_Server::IsSim(SerialNumber_)) {
|
||||
State_.VerifiedCertificate = GWObjects::SIMULATED;
|
||||
Simulated_ = true;
|
||||
}
|
||||
|
||||
std::string reason, author;
|
||||
std::uint64_t created;
|
||||
if (!CN_.empty() && StorageService()->IsBlackListed(CN_, reason, author, created)) {
|
||||
if (!CN_.empty() && StorageService()->IsBlackListed(SerialNumberInt_, reason, author, created)) {
|
||||
DeviceBlacklistedKafkaEvent KE(Utils::SerialNumberToInt(CN_), Utils::Now(), reason, author, created, CId_);
|
||||
poco_warning(
|
||||
Logger_,
|
||||
fmt::format(
|
||||
"TLS-CONNECTION({}): Session={} Device {} is black listed. Disconnecting.",
|
||||
CId_, State_.sessionId, CN_));
|
||||
EndConnection();
|
||||
return false;
|
||||
}
|
||||
|
||||
State_.certificateExpiryDate = PeerCert.expiresOn().timestamp().epochTime();
|
||||
SerialNumber_ = CN_;
|
||||
SerialNumberInt_ = Utils::SerialNumberToInt(SerialNumber_);
|
||||
State_.certificateIssuerName = PeerCert.issuerName();
|
||||
|
||||
poco_trace(Logger_,
|
||||
fmt::format("TLS-CONNECTION({}): Session={} CN={} Completed. (t={})", CId_,
|
||||
@@ -224,149 +279,14 @@ namespace OpenWifi {
|
||||
return false;
|
||||
}
|
||||
|
||||
static void NotifyKafkaDisconnect(const std::string &SerialNumber, std::uint64_t uuid) {
|
||||
try {
|
||||
Poco::JSON::Object Disconnect;
|
||||
Poco::JSON::Object Details;
|
||||
Details.set(uCentralProtocol::SERIALNUMBER, SerialNumber);
|
||||
Details.set(uCentralProtocol::TIMESTAMP, Utils::Now());
|
||||
Details.set(uCentralProtocol::UUID,uuid);
|
||||
Disconnect.set(uCentralProtocol::DISCONNECTION, Details);
|
||||
KafkaManager()->PostMessage(KafkaTopics::CONNECTION, SerialNumber, Disconnect);
|
||||
} catch (...) {
|
||||
}
|
||||
}
|
||||
|
||||
AP_WS_Connection::~AP_WS_Connection() {
|
||||
Valid_ = false;
|
||||
EndConnection();
|
||||
}
|
||||
|
||||
void DeviceDisconnectionCleanup(const std::string &SerialNumber, std::uint64_t uuid) {
|
||||
void AP_WS_Connection::DeviceDisconnectionCleanup(const std::string &SerialNumber, std::uint64_t uuid) {
|
||||
if (KafkaManager()->Enabled()) {
|
||||
NotifyKafkaDisconnect(SerialNumber, uuid);
|
||||
}
|
||||
RADIUSSessionTracker()->DeviceDisconnect(SerialNumber);
|
||||
}
|
||||
|
||||
void AP_WS_Connection::EndConnection(bool DeleteSession) {
|
||||
Valid_ = false;
|
||||
if (!Dead_.test_and_set()) {
|
||||
|
||||
if(!SerialNumber_.empty() && State_.LastContact!=0) {
|
||||
StorageService()->SetDeviceLastRecordedContact(SerialNumber_, State_.LastContact);
|
||||
}
|
||||
|
||||
if (Registered_) {
|
||||
Registered_ = false;
|
||||
Reactor_.removeEventHandler(
|
||||
*WS_, Poco::NObserver<AP_WS_Connection, Poco::Net::ReadableNotification>(
|
||||
*this, &AP_WS_Connection::OnSocketReadable));
|
||||
Reactor_.removeEventHandler(
|
||||
*WS_, Poco::NObserver<AP_WS_Connection, Poco::Net::ShutdownNotification>(
|
||||
*this, &AP_WS_Connection::OnSocketShutdown));
|
||||
Reactor_.removeEventHandler(
|
||||
*WS_, Poco::NObserver<AP_WS_Connection, Poco::Net::ErrorNotification>(
|
||||
*this, &AP_WS_Connection::OnSocketError));
|
||||
}
|
||||
WS_->close();
|
||||
|
||||
if(!SerialNumber_.empty()) {
|
||||
std::thread Cleanup(DeviceDisconnectionCleanup,SerialNumber_, uuid_);
|
||||
Cleanup.detach();
|
||||
}
|
||||
|
||||
bool SessionDeleted = false;
|
||||
if(DeleteSession)
|
||||
SessionDeleted = AP_WS_Server()->EndSession(State_.sessionId, SerialNumberInt_);
|
||||
|
||||
if (SessionDeleted || !DeleteSession) {
|
||||
GWWebSocketNotifications::SingleDevice_t N;
|
||||
N.content.serialNumber = SerialNumber_;
|
||||
GWWebSocketNotifications::DeviceDisconnected(N);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool AP_WS_Connection::LookForUpgrade(const uint64_t UUID, uint64_t &UpgradedUUID) {
|
||||
|
||||
// A UUID of zero means ignore updates for that connection.
|
||||
if (UUID == 0)
|
||||
return false;
|
||||
|
||||
uint64_t GoodConfig = ConfigurationCache().CurrentConfig(SerialNumberInt_);
|
||||
if (GoodConfig && (GoodConfig == UUID || GoodConfig == State_.PendingUUID)) {
|
||||
UpgradedUUID = UUID;
|
||||
return false;
|
||||
}
|
||||
|
||||
GWObjects::Device D;
|
||||
if (StorageService()->GetDevice(SerialNumber_, D)) {
|
||||
|
||||
if(D.pendingUUID!=0 && UUID==D.pendingUUID) {
|
||||
// so we sent an upgrade to a device, and now it is completing now...
|
||||
UpgradedUUID = D.pendingUUID;
|
||||
StorageService()->CompleteDeviceConfigurationChange(SerialNumber_);
|
||||
return true;
|
||||
}
|
||||
|
||||
// This is the case where the cache is empty after a restart. So GoodConfig will 0. If
|
||||
// the device already has the right UUID, we just return.
|
||||
if (D.UUID == UUID) {
|
||||
UpgradedUUID = UUID;
|
||||
ConfigurationCache().Add(SerialNumberInt_, UUID);
|
||||
return false;
|
||||
}
|
||||
|
||||
Config::Config Cfg(D.Configuration);
|
||||
if (UUID > D.UUID) {
|
||||
// so we have a problem, the device has a newer config than we have. So we need to
|
||||
// make sure our config is newer.
|
||||
D.UUID = UUID + 2;
|
||||
UpgradedUUID = D.UUID;
|
||||
}
|
||||
|
||||
Cfg.SetUUID(D.UUID);
|
||||
D.Configuration = Cfg.get();
|
||||
State_.PendingUUID = UpgradedUUID = D.UUID;
|
||||
|
||||
GWObjects::CommandDetails Cmd;
|
||||
Cmd.SerialNumber = SerialNumber_;
|
||||
Cmd.UUID = MicroServiceCreateUUID();
|
||||
Cmd.SubmittedBy = uCentralProtocol::SUBMITTED_BY_SYSTEM;
|
||||
Cmd.Status = uCentralProtocol::PENDING;
|
||||
Cmd.Command = uCentralProtocol::CONFIGURE;
|
||||
Poco::JSON::Parser P;
|
||||
auto ParsedConfig = P.parse(D.Configuration).extract<Poco::JSON::Object::Ptr>();
|
||||
Poco::JSON::Object Params;
|
||||
Params.set(uCentralProtocol::SERIAL, SerialNumber_);
|
||||
Params.set(uCentralProtocol::UUID, D.UUID);
|
||||
Params.set(uCentralProtocol::WHEN, 0);
|
||||
Params.set(uCentralProtocol::CONFIG, ParsedConfig);
|
||||
|
||||
std::ostringstream O;
|
||||
Poco::JSON::Stringifier::stringify(Params, O);
|
||||
Cmd.Details = O.str();
|
||||
poco_information(Logger_,
|
||||
fmt::format("CFG-UPGRADE({}): Current ID: {}, newer configuration {}.",
|
||||
CId_, UUID, D.UUID));
|
||||
bool Sent;
|
||||
|
||||
StorageService()->AddCommand(SerialNumber_, Cmd,
|
||||
Storage::CommandExecutionType::COMMAND_EXECUTED);
|
||||
CommandManager()->PostCommand(
|
||||
CommandManager()->Next_RPC_ID(), APCommands::to_apcommand(Cmd.Command.c_str()),
|
||||
SerialNumber_, Cmd.Command, Params, Cmd.UUID, Sent, false, false);
|
||||
|
||||
GWWebSocketNotifications::SingleDeviceConfigurationChange_t Notification;
|
||||
Notification.content.serialNumber = D.SerialNumber;
|
||||
Notification.content.oldUUID = UUID;
|
||||
Notification.content.newUUID = UpgradedUUID;
|
||||
GWWebSocketNotifications::DeviceConfigurationChange(Notification);
|
||||
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
GWWebSocketNotifications::SingleDevice_t N;
|
||||
N.content.serialNumber = SerialNumber;
|
||||
GWWebSocketNotifications::DeviceDisconnected(N);
|
||||
}
|
||||
|
||||
void AP_WS_Connection::ProcessJSONRPCResult(Poco::JSON::Object::Ptr Doc) {
|
||||
@@ -447,7 +367,7 @@ namespace OpenWifi {
|
||||
|
||||
std::string reason, author;
|
||||
std::uint64_t created;
|
||||
if (StorageService()->IsBlackListed(Serial, reason, author, created)) {
|
||||
if (StorageService()->IsBlackListed(SerialNumberInt_, reason, author, created)) {
|
||||
DeviceBlacklistedKafkaEvent KE(Utils::SerialNumberToInt(CN_), Utils::Now(), reason, author, created, CId_);
|
||||
Poco::Exception E(
|
||||
fmt::format("BLACKLIST({}): device is blacklisted and not allowed to connect.",
|
||||
@@ -578,17 +498,17 @@ namespace OpenWifi {
|
||||
}
|
||||
|
||||
bool AP_WS_Connection::SetWebSocketTelemetryReporting(
|
||||
uint64_t RPCID, uint64_t Interval, uint64_t LifeTime,
|
||||
std::uint64_t RPCID, std::uint64_t Interval, std::uint64_t LifeTime,
|
||||
const std::vector<std::string> &TelemetryTypes) {
|
||||
std::unique_lock Lock(TelemetryMutex_);
|
||||
TelemetryWebSocketRefCount_++;
|
||||
TelemetryInterval_ = TelemetryInterval_
|
||||
? (Interval < TelemetryInterval_ ? Interval : TelemetryInterval_)
|
||||
? (Interval < (std::uint64_t)TelemetryInterval_ ? Interval : (std::uint64_t )TelemetryInterval_)
|
||||
: Interval;
|
||||
auto TelemetryWebSocketTimer = LifeTime + Utils::Now();
|
||||
TelemetryWebSocketTimer_ = TelemetryWebSocketTimer > TelemetryWebSocketTimer_
|
||||
? TelemetryWebSocketTimer
|
||||
: TelemetryWebSocketTimer_;
|
||||
TelemetryWebSocketTimer_ = TelemetryWebSocketTimer > (std::uint64_t)TelemetryWebSocketTimer_
|
||||
? (std::uint64_t)TelemetryWebSocketTimer
|
||||
: (std::uint64_t)TelemetryWebSocketTimer_;
|
||||
UpdateCounts();
|
||||
if (!TelemetryReporting_) {
|
||||
TelemetryReporting_ = true;
|
||||
@@ -604,11 +524,11 @@ namespace OpenWifi {
|
||||
std::unique_lock Lock(TelemetryMutex_);
|
||||
TelemetryKafkaRefCount_++;
|
||||
TelemetryInterval_ = TelemetryInterval_
|
||||
? (Interval < TelemetryInterval_ ? Interval : TelemetryInterval_)
|
||||
? (Interval < (std::uint64_t)TelemetryInterval_ ? (std::uint64_t)Interval : (std::uint64_t)TelemetryInterval_)
|
||||
: Interval;
|
||||
auto TelemetryKafkaTimer = LifeTime + Utils::Now();
|
||||
TelemetryKafkaTimer_ =
|
||||
TelemetryKafkaTimer > TelemetryKafkaTimer_ ? TelemetryKafkaTimer : TelemetryKafkaTimer_;
|
||||
TelemetryKafkaTimer > (std::uint64_t)TelemetryKafkaTimer_ ? (std::uint64_t)TelemetryKafkaTimer : (std::uint64_t)TelemetryKafkaTimer_;
|
||||
UpdateCounts();
|
||||
if (!TelemetryReporting_) {
|
||||
TelemetryReporting_ = true;
|
||||
@@ -644,223 +564,272 @@ namespace OpenWifi {
|
||||
void AP_WS_Connection::OnSocketShutdown(
|
||||
[[maybe_unused]] const Poco::AutoPtr<Poco::Net::ShutdownNotification> &pNf) {
|
||||
poco_trace(Logger_, fmt::format("SOCKET-SHUTDOWN({}): Closing.", CId_));
|
||||
// std::lock_guard G(ConnectionMutex_);
|
||||
return EndConnection();
|
||||
}
|
||||
|
||||
void AP_WS_Connection::OnSocketError(
|
||||
[[maybe_unused]] const Poco::AutoPtr<Poco::Net::ErrorNotification> &pNf) {
|
||||
poco_trace(Logger_, fmt::format("SOCKET-ERROR({}): Closing.", CId_));
|
||||
// std::lock_guard G(ConnectionMutex_);
|
||||
return EndConnection();
|
||||
}
|
||||
|
||||
void AP_WS_Connection::OnSocketReadable(
|
||||
[[maybe_unused]] const Poco::AutoPtr<Poco::Net::ReadableNotification> &pNf) {
|
||||
|
||||
if (!Valid_)
|
||||
if (Dead_) // we are dead, so we do not process anything.
|
||||
return;
|
||||
|
||||
if (!AP_WS_Server()->Running())
|
||||
return EndConnection();
|
||||
std::lock_guard G(ConnectionMutex_);
|
||||
|
||||
if (!ValidatedDevice())
|
||||
return;
|
||||
|
||||
try {
|
||||
return ProcessIncomingFrame();
|
||||
} catch (const Poco::Exception &E) {
|
||||
Logger_.log(E);
|
||||
return EndConnection();
|
||||
} catch (const std::exception &E) {
|
||||
std::string W = E.what();
|
||||
poco_information(
|
||||
Logger_,
|
||||
fmt::format("std::exception caught: {}. Connection terminated with {}", W, CId_));
|
||||
return EndConnection();
|
||||
} catch (...) {
|
||||
poco_information(Logger_,
|
||||
fmt::format("Unknown exception for {}. Connection terminated.", CId_));
|
||||
return EndConnection();
|
||||
State_.LastContact = LastContact_ = Utils::Now();
|
||||
if (AP_WS_Server()->Running() && (DeviceValidated_ || ValidatedDevice())) {
|
||||
try {
|
||||
return ProcessIncomingFrame();
|
||||
} catch (const Poco::Exception &E) {
|
||||
Logger_.log(E);
|
||||
} catch (const std::exception &E) {
|
||||
std::string W = E.what();
|
||||
poco_information(
|
||||
Logger_, fmt::format("std::exception caught: {}. Connection terminated with {}",
|
||||
W, CId_));
|
||||
} catch (...) {
|
||||
poco_information(
|
||||
Logger_, fmt::format("Unknown exception for {}. Connection terminated.", CId_));
|
||||
}
|
||||
}
|
||||
EndConnection();
|
||||
}
|
||||
|
||||
void AP_WS_Connection::ProcessWSFinalPayload() {
|
||||
auto IncomingSize = IncomingFrame_.size();
|
||||
|
||||
if (IncomingSize == 0) {
|
||||
poco_debug(Logger_,
|
||||
fmt::format("ProcessWSFrame({}): Final Acc. Frame received but empty",
|
||||
CId_));
|
||||
return;
|
||||
}
|
||||
IncomingFrame_.append(0);
|
||||
|
||||
poco_trace(Logger_,
|
||||
fmt::format("ProcessWSFrame({}): Final Acc. Frame received (len={}, Msg={}",
|
||||
CId_, IncomingSize, IncomingFrame_.begin()));
|
||||
|
||||
Poco::JSON::Parser parser;
|
||||
auto ParsedMessage = parser.parse(IncomingFrame_.begin());
|
||||
auto IncomingJSON = ParsedMessage.extract<Poco::JSON::Object::Ptr>();
|
||||
|
||||
if (IncomingJSON->has(uCentralProtocol::JSONRPC)) {
|
||||
if (IncomingJSON->has(uCentralProtocol::METHOD) &&
|
||||
IncomingJSON->has(uCentralProtocol::PARAMS)) {
|
||||
ProcessJSONRPCEvent(IncomingJSON);
|
||||
} else if (IncomingJSON->has(uCentralProtocol::RESULT) &&
|
||||
IncomingJSON->has(uCentralProtocol::ID)) {
|
||||
poco_trace(Logger_, fmt::format("RPC-RESULT({}): payload: {}", CId_,
|
||||
IncomingFrame_.begin()));
|
||||
ProcessJSONRPCResult(IncomingJSON);
|
||||
} else {
|
||||
poco_warning(
|
||||
Logger_,
|
||||
fmt::format("INVALID-PAYLOAD({}): Payload is not JSON-RPC 2.0: {}",
|
||||
CId_, IncomingFrame_.begin()));
|
||||
}
|
||||
} else if (IncomingJSON->has(uCentralProtocol::RADIUS)) {
|
||||
ProcessIncomingRadiusData(IncomingJSON);
|
||||
} else {
|
||||
std::ostringstream iS;
|
||||
IncomingJSON->stringify(iS);
|
||||
poco_warning(
|
||||
Logger_,
|
||||
fmt::format("FRAME({}): illegal transaction header, missing 'jsonrpc': {}",
|
||||
CId_, iS.str()));
|
||||
Errors_++;
|
||||
}
|
||||
IncomingFrame_.clear();
|
||||
IncomingFrame_.resize(0);
|
||||
}
|
||||
|
||||
void AP_WS_Connection::ProcessIncomingFrame() {
|
||||
Poco::Buffer<char> IncomingFrame(0);
|
||||
Poco::Buffer<char> CurrentFrame(0);
|
||||
bool KillConnection = false;
|
||||
int flags = 0;
|
||||
int IncomingSize = 0;
|
||||
|
||||
try {
|
||||
int Op, flags;
|
||||
auto IncomingSize = WS_->receiveFrame(IncomingFrame, flags);
|
||||
IncomingSize = WS_->receiveFrame(CurrentFrame, flags);
|
||||
int Op;
|
||||
|
||||
Op = flags & Poco::Net::WebSocket::FRAME_OP_BITMASK;
|
||||
|
||||
if (IncomingSize == 0 && flags == 0 && Op == 0) {
|
||||
if (IncomingSize < 0 && flags == 0) {
|
||||
poco_trace(Logger_,
|
||||
fmt::format("EMPTY({}): Non-blocking try-again empty frame (len={}, flags={})",
|
||||
CId_, IncomingSize, flags));
|
||||
} else if (IncomingSize == 0 && flags == 0) {
|
||||
poco_information(Logger_,
|
||||
fmt::format("DISCONNECT({}): device has disconnected. Session={}",
|
||||
CId_, State_.sessionId));
|
||||
return EndConnection();
|
||||
}
|
||||
|
||||
IncomingFrame.append(0);
|
||||
|
||||
State_.RX += IncomingSize;
|
||||
AP_WS_Server()->AddRX(IncomingSize);
|
||||
if (IncomingSize > 0) {
|
||||
State_.RX += IncomingSize;
|
||||
AP_WS_Server()->AddRX(IncomingSize);
|
||||
IncomingFrame_.append(CurrentFrame);
|
||||
}
|
||||
State_.MessageCount++;
|
||||
State_.LastContact = Utils::Now();
|
||||
poco_trace(Logger_,
|
||||
fmt::format("FRAME({}): Frame rx (op={} len={}, flags={}, acc.len={})",
|
||||
CId_, Op, IncomingSize, flags, IncomingFrame_.size()));
|
||||
|
||||
switch (Op) {
|
||||
case Poco::Net::WebSocket::FRAME_OP_PING: {
|
||||
poco_trace(Logger_, fmt::format("WS-PING({}): received. PONG sent back.", CId_));
|
||||
WS_->sendFrame("", 0,
|
||||
(int)Poco::Net::WebSocket::FRAME_OP_PONG |
|
||||
case Poco::Net::WebSocket::FRAME_OP_PING: {
|
||||
poco_trace(Logger_, fmt::format("PING({}): received. PONG sent back.", CId_));
|
||||
WS_->sendFrame("", 0,
|
||||
(int)Poco::Net::WebSocket::FRAME_OP_PONG |
|
||||
(int)Poco::Net::WebSocket::FRAME_FLAG_FIN);
|
||||
|
||||
if (KafkaManager()->Enabled()) {
|
||||
Poco::JSON::Object PingObject;
|
||||
Poco::JSON::Object PingDetails;
|
||||
PingDetails.set(uCentralProtocol::FIRMWARE, State_.Firmware);
|
||||
PingDetails.set(uCentralProtocol::SERIALNUMBER, SerialNumber_);
|
||||
PingDetails.set(uCentralProtocol::COMPATIBLE, Compatible_);
|
||||
PingDetails.set(uCentralProtocol::CONNECTIONIP, CId_);
|
||||
PingDetails.set(uCentralProtocol::TIMESTAMP, Utils::Now());
|
||||
PingDetails.set(uCentralProtocol::UUID, uuid_);
|
||||
PingDetails.set("locale", State_.locale);
|
||||
PingObject.set(uCentralProtocol::PING, PingDetails);
|
||||
poco_trace(Logger_,fmt::format("Sending PING for {}", SerialNumber_));
|
||||
KafkaManager()->PostMessage(KafkaTopics::CONNECTION, SerialNumber_,PingObject);
|
||||
}
|
||||
return;
|
||||
} break;
|
||||
|
||||
case Poco::Net::WebSocket::FRAME_OP_PONG: {
|
||||
poco_trace(Logger_, fmt::format("PONG({}): received and ignored.", CId_));
|
||||
return;
|
||||
} break;
|
||||
|
||||
case Poco::Net::WebSocket::FRAME_OP_TEXT: {
|
||||
poco_trace(Logger_,
|
||||
fmt::format("FRAME({}): Frame received (length={}, flags={}). Msg={}",
|
||||
CId_, IncomingSize, flags, IncomingFrame.begin()));
|
||||
|
||||
Poco::JSON::Parser parser;
|
||||
auto ParsedMessage = parser.parse(IncomingFrame.begin());
|
||||
auto IncomingJSON = ParsedMessage.extract<Poco::JSON::Object::Ptr>();
|
||||
|
||||
if (IncomingJSON->has(uCentralProtocol::JSONRPC)) {
|
||||
if (IncomingJSON->has(uCentralProtocol::METHOD) &&
|
||||
IncomingJSON->has(uCentralProtocol::PARAMS)) {
|
||||
ProcessJSONRPCEvent(IncomingJSON);
|
||||
} else if (IncomingJSON->has(uCentralProtocol::RESULT) &&
|
||||
IncomingJSON->has(uCentralProtocol::ID)) {
|
||||
poco_trace(Logger_, fmt::format("RPC-RESULT({}): payload: {}", CId_,
|
||||
IncomingFrame.begin()));
|
||||
ProcessJSONRPCResult(IncomingJSON);
|
||||
} else {
|
||||
poco_warning(
|
||||
Logger_,
|
||||
fmt::format("INVALID-PAYLOAD({}): Payload is not JSON-RPC 2.0: {}",
|
||||
CId_, IncomingFrame.begin()));
|
||||
if (KafkaManager()->Enabled()) {
|
||||
Poco::JSON::Object PingObject;
|
||||
Poco::JSON::Object PingDetails;
|
||||
PingDetails.set(uCentralProtocol::FIRMWARE, State_.Firmware);
|
||||
PingDetails.set(uCentralProtocol::SERIALNUMBER, SerialNumber_);
|
||||
PingDetails.set(uCentralProtocol::COMPATIBLE, Compatible_);
|
||||
PingDetails.set(uCentralProtocol::CONNECTIONIP, CId_);
|
||||
PingDetails.set(uCentralProtocol::TIMESTAMP, Utils::Now());
|
||||
PingDetails.set(uCentralProtocol::UUID, uuid_);
|
||||
PingDetails.set("locale", State_.locale);
|
||||
PingObject.set(uCentralProtocol::PING, PingDetails);
|
||||
poco_trace(Logger_,fmt::format("Sending PING for {}", SerialNumber_));
|
||||
KafkaManager()->PostMessage(KafkaTopics::CONNECTION, SerialNumber_,
|
||||
PingObject);
|
||||
}
|
||||
} else if (IncomingJSON->has(uCentralProtocol::RADIUS)) {
|
||||
ProcessIncomingRadiusData(IncomingJSON);
|
||||
} else {
|
||||
std::ostringstream iS;
|
||||
IncomingJSON->stringify(iS);
|
||||
std::cout << iS.str() << std::endl;
|
||||
poco_warning(
|
||||
Logger_,
|
||||
fmt::format("FRAME({}): illegal transaction header, missing 'jsonrpc'",
|
||||
CId_));
|
||||
return;
|
||||
} break;
|
||||
|
||||
case Poco::Net::WebSocket::FRAME_OP_PONG: {
|
||||
poco_trace(Logger_, fmt::format("PONG({}): received and ignored.", CId_));
|
||||
return;
|
||||
} break;
|
||||
|
||||
case Poco::Net::WebSocket::FRAME_OP_CONT: {
|
||||
poco_trace(Logger_, fmt::format("CONTINUATION({}): registered.", CId_));
|
||||
} break;
|
||||
|
||||
case Poco::Net::WebSocket::FRAME_OP_BINARY: {
|
||||
poco_trace(Logger_, fmt::format("BINARY({}): Invalid frame type.", CId_));
|
||||
KillConnection=true;
|
||||
return;
|
||||
} break;
|
||||
|
||||
case Poco::Net::WebSocket::FRAME_OP_TEXT: {
|
||||
poco_trace(Logger_,
|
||||
fmt::format("TEXT({}): Frame received (len={}, flags={}). Msg={}",
|
||||
CId_, IncomingSize, flags,
|
||||
CurrentFrame.begin() == nullptr ? "" : CurrentFrame.begin()));
|
||||
} break;
|
||||
|
||||
case Poco::Net::WebSocket::FRAME_OP_CLOSE: {
|
||||
poco_information(Logger_,
|
||||
fmt::format("CLOSE({}): Device is closing its connection.", CId_));
|
||||
KillConnection=true;
|
||||
} break;
|
||||
|
||||
default: {
|
||||
poco_warning(Logger_, fmt::format("UNKNOWN({}): unknown WS Frame operation: {}",
|
||||
CId_, std::to_string(Op)));
|
||||
Errors_++;
|
||||
return;
|
||||
}
|
||||
return;
|
||||
} break;
|
||||
|
||||
case Poco::Net::WebSocket::FRAME_OP_CLOSE: {
|
||||
poco_information(Logger_,
|
||||
fmt::format("CLOSE({}): Device is closing its connection.", CId_));
|
||||
return EndConnection();
|
||||
} break;
|
||||
|
||||
default: {
|
||||
poco_warning(Logger_, fmt::format("UNKNOWN({}): unknown WS Frame operation: {}",
|
||||
CId_, std::to_string(Op)));
|
||||
} break;
|
||||
}
|
||||
|
||||
// Check for final frame and process accumulated payload
|
||||
if (!KillConnection && (flags & Poco::Net::WebSocket::FRAME_FLAG_FIN) != 0) {
|
||||
ProcessWSFinalPayload();
|
||||
}
|
||||
|
||||
} catch (const Poco::Net::ConnectionResetException &E) {
|
||||
poco_warning(Logger_,
|
||||
fmt::format("ConnectionResetException({}): Text:{} Payload:{} Session:{}",
|
||||
CId_, E.displayText(),
|
||||
IncomingFrame.begin() == nullptr ? "" : IncomingFrame.begin(),
|
||||
CurrentFrame.begin() == nullptr ? "" : CurrentFrame.begin(),
|
||||
State_.sessionId));
|
||||
return EndConnection();
|
||||
KillConnection=true;
|
||||
} catch (const Poco::JSON::JSONException &E) {
|
||||
poco_warning(Logger_,
|
||||
fmt::format("JSONException({}): Text:{} Payload:{} Session:{}", CId_,
|
||||
E.displayText(),
|
||||
IncomingFrame.begin() == nullptr ? "" : IncomingFrame.begin(),
|
||||
CurrentFrame.begin() == nullptr ? "" : CurrentFrame.begin(),
|
||||
State_.sessionId));
|
||||
return EndConnection();
|
||||
KillConnection=true;
|
||||
} catch (const Poco::Net::WebSocketException &E) {
|
||||
poco_warning(Logger_,
|
||||
fmt::format("WebSocketException({}): Text:{} Payload:{} Session:{}", CId_,
|
||||
E.displayText(),
|
||||
IncomingFrame.begin() == nullptr ? "" : IncomingFrame.begin(),
|
||||
CurrentFrame.begin() == nullptr ? "" : CurrentFrame.begin(),
|
||||
State_.sessionId));
|
||||
return EndConnection();
|
||||
KillConnection=true;
|
||||
} catch (const Poco::Net::SSLConnectionUnexpectedlyClosedException &E) {
|
||||
poco_warning(
|
||||
Logger_,
|
||||
fmt::format(
|
||||
"SSLConnectionUnexpectedlyClosedException({}): Text:{} Payload:{} Session:{}",
|
||||
CId_, E.displayText(),
|
||||
IncomingFrame.begin() == nullptr ? "" : IncomingFrame.begin(),
|
||||
CurrentFrame.begin() == nullptr ? "" : CurrentFrame.begin(),
|
||||
State_.sessionId));
|
||||
return EndConnection();
|
||||
KillConnection=true;
|
||||
} catch (const Poco::Net::SSLException &E) {
|
||||
poco_warning(Logger_,
|
||||
fmt::format("SSLException({}): Text:{} Payload:{} Session:{}", CId_,
|
||||
E.displayText(),
|
||||
IncomingFrame.begin() == nullptr ? "" : IncomingFrame.begin(),
|
||||
CurrentFrame.begin() == nullptr ? "" : CurrentFrame.begin(),
|
||||
State_.sessionId));
|
||||
return EndConnection();
|
||||
KillConnection=true;
|
||||
} catch (const Poco::Net::NetException &E) {
|
||||
poco_warning(Logger_,
|
||||
fmt::format("NetException({}): Text:{} Payload:{} Session:{}", CId_,
|
||||
E.displayText(),
|
||||
IncomingFrame.begin() == nullptr ? "" : IncomingFrame.begin(),
|
||||
CurrentFrame.begin() == nullptr ? "" : CurrentFrame.begin(),
|
||||
State_.sessionId));
|
||||
return EndConnection();
|
||||
KillConnection=true;
|
||||
} catch (const Poco::IOException &E) {
|
||||
poco_warning(Logger_,
|
||||
fmt::format("IOException({}): Text:{} Payload:{} Session:{}", CId_,
|
||||
E.displayText(),
|
||||
IncomingFrame.begin() == nullptr ? "" : IncomingFrame.begin(),
|
||||
CurrentFrame.begin() == nullptr ? "" : CurrentFrame.begin(),
|
||||
State_.sessionId));
|
||||
return EndConnection();
|
||||
KillConnection=true;
|
||||
} catch (const Poco::Exception &E) {
|
||||
poco_warning(Logger_,
|
||||
fmt::format("Exception({}): Text:{} Payload:{} Session:{}", CId_,
|
||||
E.displayText(),
|
||||
IncomingFrame.begin() == nullptr ? "" : IncomingFrame.begin(),
|
||||
CurrentFrame.begin() == nullptr ? "" : CurrentFrame.begin(),
|
||||
State_.sessionId));
|
||||
return EndConnection();
|
||||
KillConnection=true;
|
||||
} catch (const std::exception &E) {
|
||||
poco_warning(Logger_,
|
||||
fmt::format("std::exception({}): Text:{} Payload:{} Session:{}", CId_,
|
||||
E.what(),
|
||||
IncomingFrame.begin() == nullptr ? "" : IncomingFrame.begin(),
|
||||
CurrentFrame.begin() == nullptr ? "" : CurrentFrame.begin(),
|
||||
State_.sessionId));
|
||||
return EndConnection();
|
||||
KillConnection=true;
|
||||
} catch (...) {
|
||||
poco_error(Logger_, fmt::format("UnknownException({}): Device must be disconnected. "
|
||||
"Unknown exception. Session:{}",
|
||||
CId_, State_.sessionId));
|
||||
return EndConnection();
|
||||
KillConnection=true;
|
||||
}
|
||||
|
||||
if (Errors_ < 10)
|
||||
if (!KillConnection && Errors_ < 10)
|
||||
return;
|
||||
|
||||
poco_warning(Logger_, fmt::format("DISCONNECTING({}): Too many errors", CId_));
|
||||
return EndConnection();
|
||||
poco_warning(Logger_,
|
||||
fmt::format("DISCONNECTING({}): ConnectionException: {} Errors: {}",
|
||||
CId_, KillConnection, Errors_ ));
|
||||
EndConnection();
|
||||
}
|
||||
|
||||
bool AP_WS_Connection::Send(const std::string &Payload) {
|
||||
@@ -972,4 +941,36 @@ namespace OpenWifi {
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace OpenWifi
|
||||
|
||||
void AP_WS_Connection::SetLastStats(const std::string &LastStats) {
|
||||
RawLastStats_ = LastStats;
|
||||
try {
|
||||
Poco::JSON::Parser P;
|
||||
auto Stats = P.parse(LastStats).extract<Poco::JSON::Object::Ptr>();
|
||||
State_.hasGPS = Stats->isObject("gps");
|
||||
auto Unit = Stats->getObject("unit");
|
||||
auto Memory = Unit->getObject("memory");
|
||||
std::uint64_t TotalMemory = Memory->get("total");
|
||||
std::uint64_t FreeMemory = Memory->get("free");
|
||||
if (TotalMemory > 0) {
|
||||
State_.memoryUsed =
|
||||
(100.0 * ((double)TotalMemory - (double)FreeMemory)) / (double)TotalMemory;
|
||||
}
|
||||
if (Unit->isArray("load")) {
|
||||
Poco::JSON::Array::Ptr Load = Unit->getArray("load");
|
||||
if (Load->size() > 1) {
|
||||
State_.load = Load->get(1);
|
||||
}
|
||||
}
|
||||
if (Unit->isArray("temperature")) {
|
||||
Poco::JSON::Array::Ptr Temperature = Unit->getArray("temperature");
|
||||
if (Temperature->size() > 1) {
|
||||
State_.temperature = Temperature->get(0);
|
||||
}
|
||||
}
|
||||
} catch (const Poco::Exception &E) {
|
||||
poco_error(Logger_, "Failed to parse last stats: " + E.displayText());
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace OpenWifi
|
||||
|
||||
@@ -14,27 +14,31 @@
|
||||
#include "Poco/Net/SocketReactor.h"
|
||||
#include "Poco/Net/StreamSocket.h"
|
||||
#include "Poco/Net/WebSocket.h"
|
||||
#include <Poco/Data/Session.h>
|
||||
|
||||
#include "RESTObjects/RESTAPI_GWobjects.h"
|
||||
#include <AP_WS_Reactor_Pool.h>
|
||||
|
||||
namespace OpenWifi {
|
||||
|
||||
class AP_WS_Connection {
|
||||
static constexpr int BufSize = 256000;
|
||||
static constexpr int BufSize = 512000;
|
||||
|
||||
public:
|
||||
explicit AP_WS_Connection(Poco::Net::HTTPServerRequest &request,
|
||||
Poco::Net::HTTPServerResponse &response, uint64_t connection_id,
|
||||
Poco::Logger &L, Poco::Net::SocketReactor &R);
|
||||
Poco::Logger &L, std::pair<std::shared_ptr<Poco::Net::SocketReactor>, std::shared_ptr<LockedDbSession>> R);
|
||||
~AP_WS_Connection();
|
||||
|
||||
void EndConnection(bool DeleteSession=true);
|
||||
void EndConnection();
|
||||
void ProcessJSONRPCEvent(Poco::JSON::Object::Ptr &Doc);
|
||||
void ProcessJSONRPCResult(Poco::JSON::Object::Ptr Doc);
|
||||
void ProcessWSFinalPayload();
|
||||
void ProcessIncomingFrame();
|
||||
void ProcessIncomingRadiusData(const Poco::JSON::Object::Ptr &Doc);
|
||||
|
||||
[[nodiscard]] bool Send(const std::string &Payload);
|
||||
[[nodiscard]] inline bool MustBeSecureRTTY() const { return RTTYMustBeSecure_; }
|
||||
|
||||
bool SendRadiusAuthenticationData(const unsigned char *buffer, std::size_t size);
|
||||
bool SendRadiusAccountingData(const unsigned char *buffer, std::size_t size);
|
||||
@@ -43,10 +47,7 @@ namespace OpenWifi {
|
||||
void OnSocketReadable(const Poco::AutoPtr<Poco::Net::ReadableNotification> &pNf);
|
||||
void OnSocketShutdown(const Poco::AutoPtr<Poco::Net::ShutdownNotification> &pNf);
|
||||
void OnSocketError(const Poco::AutoPtr<Poco::Net::ErrorNotification> &pNf);
|
||||
bool LookForUpgrade(uint64_t UUID, uint64_t &UpgradedUUID);
|
||||
static bool ExtractBase64CompressedData(const std::string &CompressedData,
|
||||
std::string &UnCompressedData,
|
||||
uint64_t compress_sz);
|
||||
bool LookForUpgrade(Poco::Data::Session &Session, uint64_t UUID, uint64_t &UpgradedUUID);
|
||||
void LogException(const Poco::Exception &E);
|
||||
inline Poco::Logger &Logger() { return Logger_; }
|
||||
bool SetWebSocketTelemetryReporting(uint64_t RPCID, uint64_t interval,
|
||||
@@ -59,81 +60,33 @@ namespace OpenWifi {
|
||||
bool StopKafkaTelemetry(uint64_t RPCID);
|
||||
|
||||
inline void GetLastStats(std::string &LastStats) {
|
||||
std::lock_guard G(ConnectionMutex_);
|
||||
LastStats = RawLastStats_;
|
||||
}
|
||||
|
||||
inline void SetLastStats(const std::string &LastStats) {
|
||||
std::lock_guard G(ConnectionMutex_);
|
||||
RawLastStats_ = LastStats;
|
||||
try {
|
||||
Poco::JSON::Parser P;
|
||||
auto Stats = P.parse(LastStats).extract<Poco::JSON::Object::Ptr>();
|
||||
hasGPS = Stats->isObject("gps");
|
||||
auto Unit = Stats->getObject("unit");
|
||||
auto Memory = Unit->getObject("memory");
|
||||
std::uint64_t TotalMemory = Memory->get("total");
|
||||
std::uint64_t FreeMemory = Memory->get("free");
|
||||
if(TotalMemory>0) {
|
||||
memory_used_ =
|
||||
(100.0 * ((double)TotalMemory - (double)FreeMemory)) / (double)TotalMemory;
|
||||
}
|
||||
if(Unit->isArray("load")) {
|
||||
Poco::JSON::Array::Ptr Load = Unit->getArray("load");
|
||||
if(Load->size()>1) {
|
||||
cpu_load_ = Load->get(1);
|
||||
}
|
||||
}
|
||||
if(Unit->isArray("temperature")) {
|
||||
Poco::JSON::Array::Ptr Temperature = Unit->getArray("temperature");
|
||||
if(Temperature->size()>1) {
|
||||
temperature_ = Temperature->get(0);
|
||||
}
|
||||
}
|
||||
} catch (...) {
|
||||
|
||||
if(!Dead_) {
|
||||
std::lock_guard G(ConnectionMutex_);
|
||||
LastStats = RawLastStats_;
|
||||
}
|
||||
}
|
||||
|
||||
inline void SetLastHealthCheck(const GWObjects::HealthCheck &H) {
|
||||
std::lock_guard G(ConnectionMutex_);
|
||||
RawLastHealthcheck_ = H;
|
||||
}
|
||||
|
||||
inline void GetLastHealthCheck(GWObjects::HealthCheck &H) {
|
||||
std::lock_guard G(ConnectionMutex_);
|
||||
H = RawLastHealthcheck_;
|
||||
if(!Dead_) {
|
||||
std::lock_guard G(ConnectionMutex_);
|
||||
H = RawLastHealthcheck_;
|
||||
}
|
||||
}
|
||||
|
||||
inline void GetState(GWObjects::ConnectionState &State) const {
|
||||
std::lock_guard G(ConnectionMutex_);
|
||||
State = State_;
|
||||
inline void GetState(GWObjects::ConnectionState &State) {
|
||||
if(!Dead_) {
|
||||
std::lock_guard G(ConnectionMutex_);
|
||||
State = State_;
|
||||
}
|
||||
}
|
||||
|
||||
inline bool HasGPS() { return hasGPS; }
|
||||
|
||||
inline void GetRestrictions(GWObjects::DeviceRestrictions &R) const {
|
||||
inline GWObjects::DeviceRestrictions GetRestrictions() {
|
||||
std::lock_guard G(ConnectionMutex_);
|
||||
R = Restrictions_;
|
||||
return Restrictions_;
|
||||
}
|
||||
|
||||
void Process_connect(Poco::JSON::Object::Ptr ParamsObj, const std::string &Serial);
|
||||
void Process_state(Poco::JSON::Object::Ptr ParamsObj);
|
||||
void Process_healthcheck(Poco::JSON::Object::Ptr ParamsObj);
|
||||
void Process_log(Poco::JSON::Object::Ptr ParamsObj);
|
||||
void Process_crashlog(Poco::JSON::Object::Ptr ParamsObj);
|
||||
void Process_ping(Poco::JSON::Object::Ptr ParamsObj);
|
||||
void Process_cfgpending(Poco::JSON::Object::Ptr ParamsObj);
|
||||
void Process_recovery(Poco::JSON::Object::Ptr ParamsObj);
|
||||
void Process_deviceupdate(Poco::JSON::Object::Ptr ParamsObj, std::string &Serial);
|
||||
void Process_telemetry(Poco::JSON::Object::Ptr ParamsObj);
|
||||
void Process_venuebroadcast(Poco::JSON::Object::Ptr ParamsObj);
|
||||
void Process_event(Poco::JSON::Object::Ptr ParamsObj);
|
||||
void Process_wifiscan(Poco::JSON::Object::Ptr ParamsObj);
|
||||
void Process_alarm(Poco::JSON::Object::Ptr ParamsObj);
|
||||
void Process_rebootLog(Poco::JSON::Object::Ptr ParamsObj);
|
||||
|
||||
bool ValidatedDevice();
|
||||
[[nodiscard]] inline bool HasGPS() const { return hasGPS_; }
|
||||
[[nodiscard]] bool ValidatedDevice();
|
||||
|
||||
inline bool GetTelemetryParameters(bool &Reporting, uint64_t &Interval,
|
||||
uint64_t &WebSocketTimer, uint64_t &KafkaTimer,
|
||||
@@ -153,18 +106,14 @@ namespace OpenWifi {
|
||||
|
||||
friend class AP_WS_Server;
|
||||
|
||||
inline GWObjects::DeviceRestrictions Restrictions() const {
|
||||
std::lock_guard G(ConnectionMutex_);
|
||||
return Restrictions_;
|
||||
}
|
||||
|
||||
inline bool MustBeSecureRtty() const { return RttyMustBeSecure_; }
|
||||
void Start();
|
||||
|
||||
private:
|
||||
mutable std::mutex ConnectionMutex_;
|
||||
mutable std::recursive_mutex ConnectionMutex_;
|
||||
std::mutex TelemetryMutex_;
|
||||
Poco::Logger &Logger_;
|
||||
Poco::Net::SocketReactor &Reactor_;
|
||||
std::shared_ptr<Poco::Net::SocketReactor> Reactor_;
|
||||
std::shared_ptr<LockedDbSession> DbSession_;
|
||||
std::unique_ptr<Poco::Net::WebSocket> WS_;
|
||||
std::string SerialNumber_;
|
||||
uint64_t SerialNumberInt_ = 0;
|
||||
@@ -175,34 +124,57 @@ namespace OpenWifi {
|
||||
uint64_t Errors_ = 0;
|
||||
Poco::Net::IPAddress PeerAddress_;
|
||||
volatile bool TelemetryReporting_ = false;
|
||||
volatile uint64_t TelemetryWebSocketRefCount_ = 0;
|
||||
volatile uint64_t TelemetryKafkaRefCount_ = 0;
|
||||
volatile uint64_t TelemetryWebSocketTimer_ = 0;
|
||||
volatile uint64_t TelemetryKafkaTimer_ = 0;
|
||||
volatile uint64_t TelemetryInterval_ = 0;
|
||||
volatile uint64_t TelemetryWebSocketPackets_ = 0;
|
||||
volatile uint64_t TelemetryKafkaPackets_ = 0;
|
||||
std::atomic_uint64_t TelemetryWebSocketRefCount_ = 0;
|
||||
std::atomic_uint64_t TelemetryKafkaRefCount_ = 0;
|
||||
std::atomic_uint64_t TelemetryWebSocketTimer_ = 0;
|
||||
std::atomic_uint64_t TelemetryKafkaTimer_ = 0;
|
||||
std::atomic_uint64_t TelemetryInterval_ = 0;
|
||||
std::atomic_uint64_t TelemetryWebSocketPackets_ = 0;
|
||||
std::atomic_uint64_t TelemetryKafkaPackets_ = 0;
|
||||
GWObjects::ConnectionState State_;
|
||||
std::string RawLastStats_;
|
||||
Utils::CompressedString RawLastStats_;
|
||||
GWObjects::HealthCheck RawLastHealthcheck_;
|
||||
std::chrono::time_point<std::chrono::high_resolution_clock> ConnectionStart_ =
|
||||
std::chrono::high_resolution_clock::now();
|
||||
std::chrono::duration<double, std::milli> ConnectionCompletionTime_{0.0};
|
||||
std::atomic_flag Dead_ = false;
|
||||
std::atomic<bool> Dead_ = false;
|
||||
std::atomic_bool DeviceValidated_ = false;
|
||||
std::atomic_bool Valid_ = false;
|
||||
OpenWifi::GWObjects::DeviceRestrictions Restrictions_;
|
||||
bool RttyMustBeSecure_ = false;
|
||||
bool RTTYMustBeSecure_ = false;
|
||||
bool hasGPS_=false;
|
||||
std::double_t memory_used_=0.0, cpu_load_ = 0.0, temperature_ = 0.0;
|
||||
std::uint64_t uuid_=0;
|
||||
bool Simulated_=false;
|
||||
std::atomic_uint64_t LastContact_=0;
|
||||
Poco::Buffer<char> IncomingFrame_;
|
||||
|
||||
static inline std::atomic_uint64_t ConcurrentStartingDevices_ = 0;
|
||||
|
||||
bool StartTelemetry(uint64_t RPCID, const std::vector<std::string> &TelemetryTypes);
|
||||
bool StopTelemetry(uint64_t RPCID);
|
||||
void UpdateCounts();
|
||||
bool hasGPS=false;
|
||||
std::double_t memory_used_=0.0, cpu_load_ = 0.0, temperature_ = 0.0;
|
||||
std::uint64_t uuid_=0;
|
||||
bool Simulated_=false;
|
||||
static void DeviceDisconnectionCleanup(const std::string &SerialNumber, std::uint64_t uuid);
|
||||
void SetLastStats(const std::string &LastStats);
|
||||
void Process_connect(Poco::JSON::Object::Ptr ParamsObj, const std::string &Serial);
|
||||
void Process_state(Poco::JSON::Object::Ptr ParamsObj);
|
||||
void Process_healthcheck(Poco::JSON::Object::Ptr ParamsObj);
|
||||
void Process_log(Poco::JSON::Object::Ptr ParamsObj);
|
||||
void Process_crashlog(Poco::JSON::Object::Ptr ParamsObj);
|
||||
void Process_ping(Poco::JSON::Object::Ptr ParamsObj);
|
||||
void Process_cfgpending(Poco::JSON::Object::Ptr ParamsObj);
|
||||
void Process_recovery(Poco::JSON::Object::Ptr ParamsObj);
|
||||
void Process_deviceupdate(Poco::JSON::Object::Ptr ParamsObj, std::string &Serial);
|
||||
void Process_telemetry(Poco::JSON::Object::Ptr ParamsObj);
|
||||
void Process_venuebroadcast(Poco::JSON::Object::Ptr ParamsObj);
|
||||
void Process_event(Poco::JSON::Object::Ptr ParamsObj);
|
||||
void Process_wifiscan(Poco::JSON::Object::Ptr ParamsObj);
|
||||
void Process_alarm(Poco::JSON::Object::Ptr ParamsObj);
|
||||
void Process_rebootLog(Poco::JSON::Object::Ptr ParamsObj);
|
||||
|
||||
inline void SetLastHealthCheck(const GWObjects::HealthCheck &H) {
|
||||
RawLastHealthcheck_ = H;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
} // namespace OpenWifi
|
||||
} // namespace OpenWifi
|
||||
|
||||
111
src/AP_WS_LookForUpgrade.cpp
Normal file
111
src/AP_WS_LookForUpgrade.cpp
Normal file
@@ -0,0 +1,111 @@
|
||||
|
||||
#include <AP_WS_Connection.h>
|
||||
#include "ConfigurationCache.h"
|
||||
#include "UI_GW_WebSocketNotifications.h"
|
||||
#include "CommandManager.h"
|
||||
|
||||
namespace OpenWifi {
|
||||
bool AP_WS_Connection::LookForUpgrade(Poco::Data::Session &Session, const uint64_t UUID, uint64_t &UpgradedUUID) {
|
||||
|
||||
// A UUID of zero means ignore updates for that connection.
|
||||
if (UUID == 0)
|
||||
return false;
|
||||
|
||||
uint64_t GoodConfig = GetCurrentConfigurationID(SerialNumberInt_);
|
||||
if (GoodConfig && (GoodConfig == UUID || GoodConfig == State_.PendingUUID)) {
|
||||
UpgradedUUID = UUID;
|
||||
State_.PendingUUID = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
GWObjects::Device D;
|
||||
if (!StorageService()->GetDevice(Session,SerialNumber_, D)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -71,9 +71,8 @@ namespace OpenWifi {
|
||||
|
||||
CommandManager()->ClearQueue(SerialNumberInt_);
|
||||
|
||||
AP_WS_Server()->SetSessionDetails(State_.sessionId, SerialNumberInt_);
|
||||
AP_WS_Server()->StartSession(State_.sessionId, SerialNumberInt_);
|
||||
|
||||
std::lock_guard Lock(ConnectionMutex_);
|
||||
Config::Capabilities Caps(Capabilities);
|
||||
|
||||
Compatible_ = Caps.Compatible();
|
||||
@@ -84,6 +83,8 @@ namespace OpenWifi {
|
||||
State_.Address = Utils::FormatIPv6(WS_->peerAddress().toString());
|
||||
CId_ = SerialNumber_ + "@" + CId_;
|
||||
|
||||
auto Platform = Poco::toLower(Caps.Platform());
|
||||
|
||||
if(ParamsObj->has("reason")) {
|
||||
State_.connectReason = ParamsObj->get("reason").toString();
|
||||
}
|
||||
@@ -100,36 +101,24 @@ namespace OpenWifi {
|
||||
Restrictions_.from_json(RestrictionObject);
|
||||
}
|
||||
|
||||
if (Capabilities->has("developer")) {
|
||||
if (Capabilities->has("developer") && !Capabilities->isNull("developer")) {
|
||||
Restrictions_.developer = Capabilities->getValue<bool>("developer");
|
||||
}
|
||||
|
||||
if(Capabilities->has("secure-rtty")) {
|
||||
RttyMustBeSecure_ = Capabilities->getValue<bool>("secure-rtty");
|
||||
if (Capabilities->has("secure-rtty")) {
|
||||
RTTYMustBeSecure_ = Capabilities->getValue<bool>("secure-rtty");
|
||||
}
|
||||
|
||||
State_.locale = FindCountryFromIP()->Get(IP);
|
||||
GWObjects::Device DeviceInfo;
|
||||
auto DeviceExists = StorageService()->GetDevice(SerialNumber_, DeviceInfo);
|
||||
std::lock_guard DbSessionLock(DbSession_->Mutex());
|
||||
|
||||
auto DeviceExists = StorageService()->GetDevice(DbSession_->Session(), SerialNumber_, DeviceInfo);
|
||||
if (Daemon()->AutoProvisioning() && !DeviceExists) {
|
||||
// check the firmware version. if this is too old, we cannot let that device connect yet, we must
|
||||
// force a firmware upgrade
|
||||
GWObjects::DefaultFirmware MinimumFirmware;
|
||||
if(FirmwareRevisionCache()->DeviceMustUpgrade(Compatible_, Firmware, MinimumFirmware)) {
|
||||
/*
|
||||
|
||||
{ "jsonrpc" : "2.0" ,
|
||||
"method" : "upgrade" ,
|
||||
"params" : {
|
||||
"serial" : <serial number> ,
|
||||
"when" : Optional - <UTC time when to upgrade the firmware, 0 mean immediate, this is a suggestion>,
|
||||
"uri" : <URI to download the firmware>,
|
||||
"FWsignature" : <string representation of the signature for the FW> (optional)
|
||||
},
|
||||
"id" : <some number>
|
||||
}
|
||||
|
||||
*/
|
||||
Poco::JSON::Object UpgradeCommand, Params;
|
||||
UpgradeCommand.set(uCentralProtocol::JSONRPC,uCentralProtocol::JSONRPC_VERSION);
|
||||
UpgradeCommand.set(uCentralProtocol::METHOD,uCentralProtocol::UPGRADE);
|
||||
@@ -157,7 +146,7 @@ namespace OpenWifi {
|
||||
}
|
||||
return;
|
||||
} else {
|
||||
StorageService()->CreateDefaultDevice(
|
||||
StorageService()->CreateDefaultDevice( DbSession_->Session(),
|
||||
SerialNumber_, Caps, Firmware, PeerAddress_,
|
||||
State_.VerifiedCertificate == GWObjects::SIMULATED);
|
||||
}
|
||||
@@ -166,7 +155,7 @@ namespace OpenWifi {
|
||||
poco_warning(Logger(),fmt::format("Device {} is a {} from {} and cannot be provisioned.",SerialNumber_,Compatible_, CId_));
|
||||
return EndConnection();
|
||||
} else if (DeviceExists) {
|
||||
StorageService()->UpdateDeviceCapabilities(SerialNumber_, Caps);
|
||||
StorageService()->UpdateDeviceCapabilities(DbSession_->Session(), SerialNumber_, Caps);
|
||||
int Updated{0};
|
||||
if (!Firmware.empty()) {
|
||||
if (Firmware != DeviceInfo.Firmware) {
|
||||
@@ -217,8 +206,13 @@ namespace OpenWifi {
|
||||
++Updated;
|
||||
}
|
||||
|
||||
if (Compatible_ != DeviceInfo.DeviceType) {
|
||||
DeviceInfo.DeviceType = Compatible_;
|
||||
if (Compatible_ != DeviceInfo.Compatible) {
|
||||
DeviceInfo.Compatible = Compatible_;
|
||||
++Updated;
|
||||
}
|
||||
|
||||
if (Platform != DeviceInfo.DeviceType) {
|
||||
DeviceInfo.DeviceType = Platform;
|
||||
++Updated;
|
||||
}
|
||||
|
||||
@@ -238,12 +232,13 @@ namespace OpenWifi {
|
||||
}
|
||||
|
||||
if (Updated) {
|
||||
StorageService()->UpdateDevice(DeviceInfo);
|
||||
StorageService()->UpdateDevice(DbSession_->Session(), DeviceInfo);
|
||||
}
|
||||
}
|
||||
|
||||
if(!Simulated_) {
|
||||
uint64_t UpgradedUUID = 0;
|
||||
LookForUpgrade(UUID, UpgradedUUID);
|
||||
if(!Simulated_) {
|
||||
uint64_t UpgradedUUID = 0;
|
||||
if (LookForUpgrade(DbSession_->Session(), UUID, UpgradedUUID)) {
|
||||
State_.UUID = UpgradedUUID;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@ namespace OpenWifi {
|
||||
.Recorded = Utils::Now(),
|
||||
.LogType = 1,
|
||||
.UUID = ParamsObj->get(uCentralProtocol::UUID)};
|
||||
StorageService()->AddLog(DeviceLog);
|
||||
StorageService()->AddLog(*DbSession_, DeviceLog);
|
||||
DeviceLogKafkaEvent E(DeviceLog);
|
||||
} else {
|
||||
poco_warning(Logger_, fmt::format("LOG({}): Missing parameters.", CId_));
|
||||
|
||||
@@ -21,7 +21,7 @@ namespace OpenWifi {
|
||||
if (ParamsObj->has("currentPassword")) {
|
||||
auto Password = ParamsObj->get("currentPassword").toString();
|
||||
|
||||
StorageService()->SetDevicePassword(Serial, Password);
|
||||
StorageService()->SetDevicePassword(*DbSession_,Serial, Password);
|
||||
poco_trace(
|
||||
Logger_,
|
||||
fmt::format("DEVICE-UPDATE({}): Device is updating its login password.", Serial));
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
//
|
||||
|
||||
#include "AP_WS_Connection.h"
|
||||
#include "AP_WS_Server.h"
|
||||
#include "StorageService.h"
|
||||
|
||||
#include "fmt/format.h"
|
||||
@@ -25,6 +26,7 @@ namespace OpenWifi {
|
||||
|
||||
uint64_t UUID = ParamsObj->get(uCentralProtocol::UUID);
|
||||
auto Sanity = ParamsObj->get(uCentralProtocol::SANITY);
|
||||
State_.sanity = Sanity;
|
||||
auto CheckData = ParamsObj->get(uCentralProtocol::DATA).toString();
|
||||
if (CheckData.empty())
|
||||
CheckData = uCentralProtocol::EMPTY_JSON_DOC;
|
||||
@@ -48,14 +50,14 @@ namespace OpenWifi {
|
||||
Check.Data = CheckData;
|
||||
Check.Sanity = Sanity;
|
||||
|
||||
StorageService()->AddHealthCheckData(Check);
|
||||
StorageService()->AddHealthCheckData(*DbSession_, Check);
|
||||
|
||||
if (!request_uuid.empty()) {
|
||||
StorageService()->SetCommandResult(request_uuid, CheckData);
|
||||
}
|
||||
|
||||
SetLastHealthCheck(Check);
|
||||
if (KafkaManager()->Enabled()) {
|
||||
if (KafkaManager()->Enabled() && !AP_WS_Server()->KafkaDisableHealthChecks()) {
|
||||
KafkaManager()->PostMessage(KafkaTopics::HEALTHCHECK, SerialNumber_, *ParamsObj);
|
||||
}
|
||||
} else {
|
||||
|
||||
@@ -36,7 +36,7 @@ namespace OpenWifi {
|
||||
.Recorded = (uint64_t)time(nullptr),
|
||||
.LogType = 0,
|
||||
.UUID = State_.UUID};
|
||||
StorageService()->AddLog(DeviceLog);
|
||||
StorageService()->AddLog(*DbSession_, DeviceLog);
|
||||
DeviceLogKafkaEvent E(DeviceLog);
|
||||
} else {
|
||||
poco_warning(Logger_, fmt::format("LOG({}): Missing parameters.", CId_));
|
||||
|
||||
@@ -35,7 +35,7 @@ namespace OpenWifi {
|
||||
.Recorded = ParamsObj->get(uCentralProtocol::DATE),
|
||||
.LogType = 2,
|
||||
.UUID = ParamsObj->get(uCentralProtocol::UUID)};
|
||||
StorageService()->AddLog(DeviceLog);
|
||||
StorageService()->AddLog(*DbSession_, DeviceLog);
|
||||
DeviceLogKafkaEvent E(DeviceLog);
|
||||
} else {
|
||||
poco_warning(Logger_, fmt::format("REBOOT-LOG({}): Missing parameters.", CId_));
|
||||
|
||||
@@ -35,7 +35,7 @@ namespace OpenWifi {
|
||||
.LogType = 1,
|
||||
.UUID = 0};
|
||||
|
||||
StorageService()->AddLog(DeviceLog);
|
||||
StorageService()->AddLog(*DbSession_, DeviceLog);
|
||||
|
||||
if (ParamsObj->get(uCentralProtocol::REBOOT).toString() == "true") {
|
||||
GWObjects::CommandDetails Cmd;
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
//
|
||||
|
||||
#include "AP_WS_Connection.h"
|
||||
#include "AP_WS_Server.h"
|
||||
#include "StateUtils.h"
|
||||
#include "StorageService.h"
|
||||
|
||||
@@ -39,25 +40,27 @@ namespace OpenWifi {
|
||||
UUID, request_uuid));
|
||||
}
|
||||
|
||||
std::lock_guard Guard(DbSession_->Mutex());
|
||||
if(!Simulated_) {
|
||||
uint64_t UpgradedUUID;
|
||||
LookForUpgrade(UUID, UpgradedUUID);
|
||||
LookForUpgrade(DbSession_->Session(), UUID, UpgradedUUID);
|
||||
State_.UUID = UpgradedUUID;
|
||||
}
|
||||
|
||||
SetLastStats(StateStr);
|
||||
|
||||
GWObjects::Statistics Stats{
|
||||
.SerialNumber = SerialNumber_, .UUID = UUID, .Data = StateStr};
|
||||
Stats.Recorded = Utils::Now();
|
||||
StorageService()->AddStatisticsData(Stats);
|
||||
StorageService()->AddStatisticsData(DbSession_->Session(),Stats);
|
||||
if (!request_uuid.empty()) {
|
||||
StorageService()->SetCommandResult(request_uuid, StateStr);
|
||||
}
|
||||
|
||||
StateUtils::ComputeAssociations(StateObj, State_.Associations_2G,
|
||||
State_.Associations_5G, State_.Associations_6G);
|
||||
State_.Associations_5G, State_.Associations_6G, State_.uptime);
|
||||
|
||||
if (KafkaManager()->Enabled()) {
|
||||
if (KafkaManager()->Enabled() && !AP_WS_Server()->KafkaDisableState()) {
|
||||
KafkaManager()->PostMessage(KafkaTopics::STATE, SerialNumber_, *ParamsObj);
|
||||
}
|
||||
|
||||
|
||||
@@ -35,8 +35,7 @@ namespace OpenWifi {
|
||||
}
|
||||
if (TelemetryWebSocketRefCount_) {
|
||||
if (now < TelemetryWebSocketTimer_) {
|
||||
// std::cout << SerialNumber_ << ": Updating WebSocket telemetry" <<
|
||||
// std::endl;
|
||||
|
||||
TelemetryWebSocketPackets_++;
|
||||
State_.websocketPackets = TelemetryWebSocketPackets_;
|
||||
TelemetryStream()->NotifyEndPoint(SerialNumberInt_, KafkaPayload);
|
||||
@@ -46,7 +45,6 @@ namespace OpenWifi {
|
||||
}
|
||||
if (TelemetryKafkaRefCount_) {
|
||||
if (KafkaManager()->Enabled() && now < TelemetryKafkaTimer_) {
|
||||
// std::cout << SerialNumber_ << ": Updating Kafka telemetry" << std::endl;
|
||||
TelemetryKafkaPackets_++;
|
||||
State_.kafkaPackets = TelemetryKafkaPackets_;
|
||||
KafkaManager()->PostMessage(KafkaTopics::DEVICE_TELEMETRY, SerialNumber_,
|
||||
|
||||
@@ -1,62 +0,0 @@
|
||||
//
|
||||
// Created by stephane bourque on 2022-02-03.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <mutex>
|
||||
#include <string>
|
||||
|
||||
#include "Poco/Environment.h"
|
||||
#include "Poco/Net/SocketAcceptor.h"
|
||||
|
||||
#include "framework/utils.h"
|
||||
|
||||
namespace OpenWifi {
|
||||
class AP_WS_ReactorThreadPool {
|
||||
public:
|
||||
explicit AP_WS_ReactorThreadPool() {
|
||||
NumberOfThreads_ = Poco::Environment::processorCount() * 4;
|
||||
if (NumberOfThreads_ == 0)
|
||||
NumberOfThreads_ = 4;
|
||||
}
|
||||
|
||||
~AP_WS_ReactorThreadPool() { Stop(); }
|
||||
|
||||
void Start() {
|
||||
for (uint64_t i = 0; i < NumberOfThreads_; ++i) {
|
||||
auto NewReactor = std::make_unique<Poco::Net::SocketReactor>();
|
||||
auto NewThread = std::make_unique<Poco::Thread>();
|
||||
NewThread->start(*NewReactor);
|
||||
std::string ThreadName{"ap:react:" + std::to_string(i)};
|
||||
Utils::SetThreadName(*NewThread, ThreadName.c_str());
|
||||
Reactors_.emplace_back(std::move(NewReactor));
|
||||
Threads_.emplace_back(std::move(NewThread));
|
||||
}
|
||||
}
|
||||
|
||||
void Stop() {
|
||||
for (auto &i : Reactors_)
|
||||
i->stop();
|
||||
for (auto &i : Threads_) {
|
||||
i->join();
|
||||
}
|
||||
Reactors_.clear();
|
||||
Threads_.clear();
|
||||
}
|
||||
|
||||
Poco::Net::SocketReactor &NextReactor() {
|
||||
std::lock_guard Lock(Mutex_);
|
||||
NextReactor_++;
|
||||
NextReactor_ %= NumberOfThreads_;
|
||||
return *Reactors_[NextReactor_];
|
||||
}
|
||||
|
||||
private:
|
||||
std::mutex Mutex_;
|
||||
uint64_t NumberOfThreads_;
|
||||
uint64_t NextReactor_ = 0;
|
||||
std::vector<std::unique_ptr<Poco::Net::SocketReactor>> Reactors_;
|
||||
std::vector<std::unique_ptr<Poco::Thread>> Threads_;
|
||||
};
|
||||
} // namespace OpenWifi
|
||||
77
src/AP_WS_Reactor_Pool.h
Normal file
77
src/AP_WS_Reactor_Pool.h
Normal file
@@ -0,0 +1,77 @@
|
||||
//
|
||||
// Created by stephane bourque on 2022-02-03.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <mutex>
|
||||
#include <string>
|
||||
|
||||
#include <framework/utils.h>
|
||||
|
||||
#include <Poco/Environment.h>
|
||||
#include <Poco/Net/SocketAcceptor.h>
|
||||
#include <Poco/Data/SessionPool.h>
|
||||
|
||||
#include <StorageService.h>
|
||||
|
||||
namespace OpenWifi {
|
||||
|
||||
class AP_WS_ReactorThreadPool {
|
||||
public:
|
||||
explicit AP_WS_ReactorThreadPool(Poco::Logger &Logger) : Logger_(Logger) {
|
||||
NumberOfThreads_ = Poco::Environment::processorCount() * 4;
|
||||
if (NumberOfThreads_ == 0)
|
||||
NumberOfThreads_ = 8;
|
||||
NumberOfThreads_ = std::min(NumberOfThreads_, (std::uint64_t) 128);
|
||||
}
|
||||
|
||||
~AP_WS_ReactorThreadPool() { Stop(); }
|
||||
|
||||
void Start() {
|
||||
Reactors_.reserve(NumberOfThreads_);
|
||||
DbSessions_.reserve(NumberOfThreads_);
|
||||
Threads_.reserve(NumberOfThreads_);
|
||||
Logger_.information(fmt::format("WebSocket Processor: starting {} threads.", NumberOfThreads_));
|
||||
for (uint64_t i = 0; i < NumberOfThreads_; ++i) {
|
||||
auto NewReactor = std::make_shared<Poco::Net::SocketReactor>();
|
||||
auto NewThread = std::make_unique<Poco::Thread>();
|
||||
NewThread->start(*NewReactor);
|
||||
std::string ThreadName{"ap:react:" + std::to_string(i)};
|
||||
Utils::SetThreadName(*NewThread, ThreadName.c_str());
|
||||
Reactors_.emplace_back(std::move(NewReactor));
|
||||
Threads_.emplace_back(std::move(NewThread));
|
||||
DbSessions_.emplace_back(std::make_shared<LockedDbSession>());
|
||||
}
|
||||
Logger_.information(fmt::format("WebSocket Processor: {} threads started.", NumberOfThreads_));
|
||||
}
|
||||
|
||||
void Stop() {
|
||||
for (auto &i : Reactors_)
|
||||
i->stop();
|
||||
for (auto &i : Threads_) {
|
||||
i->join();
|
||||
}
|
||||
Reactors_.clear();
|
||||
Threads_.clear();
|
||||
DbSessions_.clear();
|
||||
}
|
||||
|
||||
auto NextReactor() {
|
||||
std::lock_guard Lock(Mutex_);
|
||||
NextReactor_++;
|
||||
NextReactor_ %= NumberOfThreads_;
|
||||
return std::make_pair(Reactors_[NextReactor_], DbSessions_[NextReactor_]);
|
||||
}
|
||||
|
||||
private:
|
||||
std::mutex Mutex_;
|
||||
uint64_t NumberOfThreads_;
|
||||
uint64_t NextReactor_ = 0;
|
||||
std::vector<std::shared_ptr<Poco::Net::SocketReactor>> Reactors_;
|
||||
std::vector<std::unique_ptr<Poco::Thread>> Threads_;
|
||||
std::vector<std::shared_ptr<LockedDbSession>> DbSessions_;
|
||||
Poco::Logger &Logger_;
|
||||
|
||||
};
|
||||
} // namespace OpenWifi
|
||||
@@ -6,45 +6,83 @@
|
||||
// Arilia Wireless Inc.
|
||||
//
|
||||
|
||||
#include "Poco/Net/Context.h"
|
||||
#include "Poco/Net/HTTPHeaderStream.h"
|
||||
#include "Poco/Net/HTTPServerRequest.h"
|
||||
#include <Poco/Net/Context.h>
|
||||
#include <Poco/Net/HTTPHeaderStream.h>
|
||||
#include <Poco/Net/HTTPServerRequest.h>
|
||||
|
||||
#include "AP_WS_Connection.h"
|
||||
#include "AP_WS_Server.h"
|
||||
#include "ConfigurationCache.h"
|
||||
#include "TelemetryStream.h"
|
||||
#include <AP_WS_Connection.h>
|
||||
#include <AP_WS_Server.h>
|
||||
#include <ConfigurationCache.h>
|
||||
#include <TelemetryStream.h>
|
||||
|
||||
#include "UI_GW_WebSocketNotifications.h"
|
||||
#include "fmt/format.h"
|
||||
#include "framework/MicroServiceFuncs.h"
|
||||
#include "framework/utils.h"
|
||||
#include <fmt/format.h>
|
||||
|
||||
#include <framework/MicroServiceFuncs.h>
|
||||
#include <framework/utils.h>
|
||||
#include <framework/KafkaManager.h>
|
||||
|
||||
#include <UI_GW_WebSocketNotifications.h>
|
||||
|
||||
namespace OpenWifi {
|
||||
|
||||
void AP_WS_RequestHandler::handleRequest(Poco::Net::HTTPServerRequest &request,
|
||||
Poco::Net::HTTPServerResponse &response) {
|
||||
try {
|
||||
AP_WS_Server()->AddConnection(
|
||||
id_, std::make_shared<AP_WS_Connection>(request, response, id_, Logger_,
|
||||
AP_WS_Server()->NextReactor()));
|
||||
} catch (...) {
|
||||
poco_warning(Logger_, "Exception during WS creation");
|
||||
class AP_WS_RequestHandler : public Poco::Net::HTTPRequestHandler {
|
||||
public:
|
||||
explicit AP_WS_RequestHandler(Poco::Logger &L, std::uint64_t session_id) : Logger_(L),
|
||||
session_id_(session_id) {
|
||||
};
|
||||
|
||||
void handleRequest( Poco::Net::HTTPServerRequest &request,
|
||||
Poco::Net::HTTPServerResponse &response) override {
|
||||
try {
|
||||
auto NewConnection = std::make_shared<AP_WS_Connection>(request, response, session_id_, Logger_,
|
||||
AP_WS_Server()->NextReactor());
|
||||
AP_WS_Server()->AddConnection(NewConnection);
|
||||
NewConnection->Start();
|
||||
} catch (...) {
|
||||
poco_warning(Logger_, "Exception during WS creation");
|
||||
}
|
||||
};
|
||||
|
||||
private:
|
||||
Poco::Logger &Logger_;
|
||||
std::uint64_t session_id_;
|
||||
};
|
||||
|
||||
class AP_WS_RequestHandlerFactory : public Poco::Net::HTTPRequestHandlerFactory {
|
||||
public:
|
||||
inline explicit AP_WS_RequestHandlerFactory(Poco::Logger &L) : Logger_(L) {}
|
||||
|
||||
inline Poco::Net::HTTPRequestHandler *
|
||||
createRequestHandler(const Poco::Net::HTTPServerRequest &request) override {
|
||||
if (request.find("Upgrade") != request.end() &&
|
||||
Poco::icompare(request["Upgrade"], "websocket") == 0) {
|
||||
Utils::SetThreadName("ws:conn-init");
|
||||
session_id_++;
|
||||
return new AP_WS_RequestHandler(Logger_, session_id_);
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
private:
|
||||
Poco::Logger &Logger_;
|
||||
inline static std::atomic_uint64_t session_id_ = 0;
|
||||
};
|
||||
|
||||
bool AP_WS_Server::ValidateCertificate(const std::string &ConnectionId,
|
||||
const Poco::Crypto::X509Certificate &Certificate) {
|
||||
if (IsCertOk()) {
|
||||
if (!Certificate.issuedBy(*IssuerCert_)) {
|
||||
poco_warning(
|
||||
Logger(),
|
||||
fmt::format("CERTIFICATE({}): issuer mismatch. Local='{}' Incoming='{}'",
|
||||
ConnectionId, IssuerCert_->issuerName(), Certificate.issuerName()));
|
||||
return false;
|
||||
// validate certificate agains trusted chain
|
||||
for (const auto &cert : ClientCasCerts_) {
|
||||
if (Certificate.issuedBy(cert)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
poco_warning(
|
||||
Logger(),
|
||||
fmt::format(
|
||||
"CERTIFICATE({}): issuer mismatch. Certificate not issued by any trusted CA",
|
||||
ConnectionId)
|
||||
);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -57,7 +95,7 @@ namespace OpenWifi {
|
||||
|
||||
SessionTimeOut_ = MicroServiceConfigGetInt("openwifi.session.timeout", 10*60);
|
||||
|
||||
Reactor_pool_ = std::make_unique<AP_WS_ReactorThreadPool>();
|
||||
Reactor_pool_ = std::make_unique<AP_WS_ReactorThreadPool>(Logger());
|
||||
Reactor_pool_->Start();
|
||||
|
||||
for (const auto &Svr : ConfigServersList_) {
|
||||
@@ -82,7 +120,6 @@ namespace OpenWifi {
|
||||
P.verificationDepth = 9;
|
||||
P.loadDefaultCAs = Svr.RootCA().empty();
|
||||
P.cipherList = "ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH";
|
||||
P.dhUse2048Bits = true;
|
||||
P.caLocation = Svr.Cas();
|
||||
|
||||
auto Context = Poco::AutoPtr<Poco::Net::Context>(
|
||||
@@ -99,6 +136,13 @@ namespace OpenWifi {
|
||||
Context->addChainCertificate(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());
|
||||
Context->usePrivateKey(Key);
|
||||
|
||||
@@ -135,6 +179,9 @@ namespace OpenWifi {
|
||||
WebServerHttpParams);
|
||||
WebServers_.push_back(std::move(NewWebServer));
|
||||
}
|
||||
|
||||
KafkaDisableState_ = MicroServiceConfigGetBool("openwifi.kafka.disablestate", false);
|
||||
KafkaDisableHealthChecks_ = MicroServiceConfigGetBool("openwifi.kafka.disablehealthchecks", false);
|
||||
}
|
||||
|
||||
for (auto &server : WebServers_) {
|
||||
@@ -156,243 +203,420 @@ namespace OpenWifi {
|
||||
UseDefaultConfig_ = true;
|
||||
}
|
||||
|
||||
SimulatorId_ = MicroServiceConfigGetString("simulatorid", "");
|
||||
SimulatorId_ = Poco::toLower(MicroServiceConfigGetString("simulatorid", ""));
|
||||
SimulatorEnabled_ = !SimulatorId_.empty();
|
||||
Utils::SetThreadName(ReactorThread_, "dev:react:head");
|
||||
|
||||
GarbageCollectorCallback_ = std::make_unique<Poco::TimerCallback<AP_WS_Server>>(
|
||||
*this, &AP_WS_Server::onGarbageCollecting);
|
||||
Timer_.setStartInterval(10 * 1000);
|
||||
Timer_.setPeriodicInterval(10 * 1000); // every minute
|
||||
Timer_.start(*GarbageCollectorCallback_, MicroServiceTimerPool());
|
||||
|
||||
Running_ = true;
|
||||
GarbageCollector_.setName("ws:garbage");
|
||||
GarbageCollector_.start(*this);
|
||||
|
||||
std::thread CleanupThread([this](){ CleanupSessions(); });
|
||||
CleanupThread.detach();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void AP_WS_Server::onGarbageCollecting([[maybe_unused]] Poco::Timer &timer) {
|
||||
static uint64_t last_log = Utils::Now(), last_zombie_run = 0;
|
||||
auto now = Utils::Now();
|
||||
|
||||
bool AP_WS_Server::Disconnect(uint64_t SerialNumber) {
|
||||
std::shared_ptr<AP_WS_Connection> Connection;
|
||||
{
|
||||
{
|
||||
std::lock_guard SessionLock(SessionMutex_);
|
||||
if (!Garbage_.empty()) {
|
||||
Garbage_.clear();
|
||||
}
|
||||
}
|
||||
|
||||
uint64_t total_connected_time = 0;
|
||||
|
||||
if(now-last_zombie_run > 20) {
|
||||
poco_information(Logger(), fmt::format("Garbage collecting..."));
|
||||
std::vector<std::uint64_t> SessionsToRemove;
|
||||
NumberOfConnectedDevices_ = 0;
|
||||
NumberOfConnectingDevices_ = 0;
|
||||
AverageDeviceConnectionTime_ = 0;
|
||||
last_zombie_run = now;
|
||||
for(int hashIndex=0;hashIndex<256;hashIndex++) {
|
||||
std::lock_guard Lock(SerialNumbersMutex_[hashIndex]);
|
||||
auto hint = SerialNumbers_[hashIndex].begin();
|
||||
while (hint != end(SerialNumbers_[hashIndex])) {
|
||||
if (hint->second.second == nullptr) {
|
||||
hint = SerialNumbers_[hashIndex].erase(hint);
|
||||
} else if ((now - hint->second.second->State_.LastContact) >
|
||||
SessionTimeOut_) {
|
||||
hint->second.second->EndConnection(false);
|
||||
poco_information(
|
||||
Logger(),
|
||||
fmt::format(
|
||||
"{}: Session seems idle. Controller disconnecting device.",
|
||||
hint->second.second->SerialNumber_));
|
||||
SessionsToRemove.emplace_back(hint->second.first);
|
||||
Garbage_.push_back(hint->second.second);
|
||||
hint = SerialNumbers_[hashIndex].erase(hint);
|
||||
} else if (hint->second.second->State_.Connected) {
|
||||
NumberOfConnectedDevices_++;
|
||||
total_connected_time += (now - hint->second.second->State_.started);
|
||||
hint++;
|
||||
} else {
|
||||
NumberOfConnectingDevices_++;
|
||||
hint++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(SessionsToRemove.empty()) {
|
||||
poco_information(Logger(), fmt::format("Removing {} sessions.", SessionsToRemove.size()));
|
||||
std::lock_guard Lock(SessionMutex_);
|
||||
for (const auto &Session : SessionsToRemove) {
|
||||
Sessions_.erase(Session);
|
||||
}
|
||||
}
|
||||
|
||||
AverageDeviceConnectionTime_ =
|
||||
NumberOfConnectedDevices_ > 0 ? total_connected_time / NumberOfConnectedDevices_
|
||||
: 0;
|
||||
|
||||
poco_information(Logger(), fmt::format("Garbage collecting done..."));
|
||||
} else {
|
||||
std::lock_guard SessionLock(SessionMutex_);
|
||||
NumberOfConnectedDevices_ = Sessions_.size();
|
||||
AverageDeviceConnectionTime_ += 10;
|
||||
}
|
||||
|
||||
if ((now - last_log) > 120) {
|
||||
last_log = now;
|
||||
poco_information(Logger(),
|
||||
fmt::format("Active AP connections: {} Connecting: {} Average connection time: {} seconds",
|
||||
NumberOfConnectedDevices_, NumberOfConnectingDevices_,
|
||||
AverageDeviceConnectionTime_));
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
{
|
||||
auto H = SessionHash::Hash(Connection->State_.sessionId);
|
||||
std::lock_guard SessionLock(SessionMutex_[H]);
|
||||
Sessions_[H].erase(Connection->State_.sessionId);
|
||||
}
|
||||
|
||||
Poco::JSON::Object KafkaNotification;
|
||||
Notification.to_json(KafkaNotification);
|
||||
return true;
|
||||
}
|
||||
|
||||
Poco::JSON::Object FullEvent;
|
||||
FullEvent.set("type", "load-update");
|
||||
FullEvent.set("timestamp", now);
|
||||
FullEvent.set("payload", KafkaNotification);
|
||||
void AP_WS_Server::CleanupSessions() {
|
||||
|
||||
KafkaManager()->PostMessage(KafkaTopics::DEVICE_EVENT_QUEUE, "system", FullEvent);
|
||||
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() {
|
||||
uint64_t last_log = Utils::Now(),
|
||||
last_zombie_run = 0,
|
||||
last_garbage_run = 0;
|
||||
|
||||
Poco::Logger &LocalLogger = Poco::Logger::create(
|
||||
"WS-Session-Janitor", Poco::Logger::root().getChannel(), Poco::Logger::root().getLevel());
|
||||
|
||||
while(Running_) {
|
||||
|
||||
if(!Poco::Thread::trySleep(30000)) {
|
||||
break;
|
||||
}
|
||||
|
||||
LocalLogger.information(fmt::format("Garbage collecting starting run." ));
|
||||
|
||||
uint64_t total_connected_time = 0, now = Utils::Now();
|
||||
|
||||
if(now-last_zombie_run > 60) {
|
||||
try {
|
||||
poco_information(LocalLogger,
|
||||
fmt::format("Garbage collecting zombies... (step 1)"));
|
||||
NumberOfConnectingDevices_ = 0;
|
||||
AverageDeviceConnectionTime_ = 0;
|
||||
int waits = 0;
|
||||
for (int hashIndex = 0; hashIndex < MACHash::HashMax(); hashIndex++) {
|
||||
last_zombie_run = now;
|
||||
waits = 0;
|
||||
while (true) {
|
||||
if (SerialNumbersMutex_[hashIndex].try_lock()) {
|
||||
waits = 0;
|
||||
auto hint = SerialNumbers_[hashIndex].begin();
|
||||
while (hint != end(SerialNumbers_[hashIndex])) {
|
||||
if (hint->second == nullptr) {
|
||||
poco_information(
|
||||
LocalLogger,
|
||||
fmt::format("Dead device found in hash index {}", hashIndex));
|
||||
hint = SerialNumbers_[hashIndex].erase(hint);
|
||||
} else {
|
||||
auto Device = hint->second;
|
||||
auto RightNow = Utils::Now();
|
||||
if (Device->Dead_) {
|
||||
AddCleanupSession(Device->State_.sessionId, Device->SerialNumberInt_);
|
||||
++hint;
|
||||
// hint = SerialNumbers_[hashIndex].erase(hint);
|
||||
} else if (RightNow > Device->LastContact_ &&
|
||||
(RightNow - Device->LastContact_) > SessionTimeOut_) {
|
||||
poco_information(
|
||||
LocalLogger,
|
||||
fmt::format(
|
||||
"{}: Session seems idle. Controller disconnecting device.",
|
||||
Device->SerialNumber_));
|
||||
// hint = SerialNumbers_[hashIndex].erase(hint);
|
||||
AddCleanupSession(Device->State_.sessionId, Device->SerialNumberInt_);
|
||||
++hint;
|
||||
} else {
|
||||
if (Device->State_.Connected) {
|
||||
total_connected_time +=
|
||||
(RightNow - Device->State_.started);
|
||||
}
|
||||
++hint;
|
||||
}
|
||||
}
|
||||
}
|
||||
SerialNumbersMutex_[hashIndex].unlock();
|
||||
break;
|
||||
} else if (waits < 5) {
|
||||
waits++;
|
||||
Poco::Thread::trySleep(10);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
poco_information(LocalLogger, fmt::format("Garbage collecting zombies... (step 2)"));
|
||||
LeftOverSessions_ = 0;
|
||||
for (int i = 0; i < SessionHash::HashMax(); i++) {
|
||||
waits = 0;
|
||||
while (true) {
|
||||
if (SessionMutex_[i].try_lock()) {
|
||||
waits = 0;
|
||||
auto hint = Sessions_[i].begin();
|
||||
auto RightNow = Utils::Now();
|
||||
while (hint != end(Sessions_[i])) {
|
||||
if (hint->second == nullptr) {
|
||||
hint = Sessions_[i].erase(hint);
|
||||
} else if (hint->second->Dead_) {
|
||||
// hint = Sessions_[i].erase(hint);
|
||||
AddCleanupSession(hint->second->State_.sessionId, hint->second->SerialNumberInt_);
|
||||
++hint;
|
||||
} else if (RightNow > hint->second->LastContact_ &&
|
||||
(RightNow - hint->second->LastContact_) >
|
||||
SessionTimeOut_) {
|
||||
poco_information(
|
||||
LocalLogger,
|
||||
fmt::format("{}: Session seems idle. Controller disconnecting device.",
|
||||
hint->second->SerialNumber_));
|
||||
AddCleanupSession(hint->second->State_.sessionId, hint->second->SerialNumberInt_);
|
||||
++hint;
|
||||
// hint = Sessions_[i].erase(hint);
|
||||
} else {
|
||||
++LeftOverSessions_;
|
||||
++hint;
|
||||
}
|
||||
}
|
||||
SessionMutex_[i].unlock();
|
||||
break;
|
||||
} else if (waits < 5) {
|
||||
Poco::Thread::trySleep(10);
|
||||
waits++;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
AverageDeviceConnectionTime_ = NumberOfConnectedDevices_ > 0
|
||||
? total_connected_time / NumberOfConnectedDevices_
|
||||
: 0;
|
||||
poco_information(LocalLogger, fmt::format("Garbage collecting zombies done..."));
|
||||
} catch (const Poco::Exception &E) {
|
||||
poco_error(LocalLogger, fmt::format("Poco::Exception: Garbage collecting zombies failed: {}", E.displayText()));
|
||||
} catch (const std::exception &E) {
|
||||
poco_error(LocalLogger, fmt::format("std::exception: Garbage collecting zombies failed: {}", E.what()));
|
||||
} catch (...) {
|
||||
poco_error(LocalLogger, fmt::format("exception:Garbage collecting zombies failed: {}", "unknown"));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if(NumberOfConnectedDevices_) {
|
||||
if (last_garbage_run > 0) {
|
||||
AverageDeviceConnectionTime_ += (now - last_garbage_run);
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
if ((now - last_log) > 60) {
|
||||
last_log = now;
|
||||
poco_information(
|
||||
LocalLogger,
|
||||
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"));
|
||||
}
|
||||
}
|
||||
LocalLogger.information(fmt::format("Garbage collector done for the day." ));
|
||||
}
|
||||
|
||||
void AP_WS_Server::Stop() {
|
||||
poco_information(Logger(), "Stopping...");
|
||||
Running_ = false;
|
||||
|
||||
Timer_.stop();
|
||||
GarbageCollector_.wakeUp();
|
||||
GarbageCollector_.join();
|
||||
|
||||
for (auto &server : WebServers_) {
|
||||
server->stopAll();
|
||||
}
|
||||
|
||||
Reactor_pool_->Stop();
|
||||
Reactor_.stop();
|
||||
ReactorThread_.join();
|
||||
poco_information(Logger(), "Stopped...");
|
||||
}
|
||||
|
||||
bool AP_WS_Server::GetStatistics(uint64_t SerialNumber, std::string &Statistics) const {
|
||||
|
||||
auto hashIndex = Utils::CalculateMacAddressHash(SerialNumber);
|
||||
std::lock_guard Lock(SerialNumbersMutex_[hashIndex]);
|
||||
auto Device = SerialNumbers_[hashIndex].find(SerialNumber);
|
||||
if (Device == SerialNumbers_[hashIndex].end() || Device->second.second == nullptr) {
|
||||
return false;
|
||||
bool AP_WS_Server::GetHealthDevices(std::uint64_t lowLimit, std::uint64_t highLimit, std::vector<std::string> & SerialNumbers) {
|
||||
SerialNumbers.clear();
|
||||
for(int i=0;i<SessionHash::HashMax();i++) {
|
||||
std::lock_guard Lock(SessionMutex_[i]);
|
||||
for (const auto &connection : Sessions_[i]) {
|
||||
if (connection.second->RawLastHealthcheck_.Sanity >= lowLimit &&
|
||||
connection.second->RawLastHealthcheck_.Sanity <= highLimit) {
|
||||
SerialNumbers.push_back(connection.second->SerialNumber_);
|
||||
}
|
||||
}
|
||||
}
|
||||
Device->second.second->GetLastStats(Statistics);
|
||||
return true;
|
||||
}
|
||||
|
||||
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 DeviceLock(SerialNumbersMutex_[hashIndex]);
|
||||
auto DeviceHint = SerialNumbers_[hashIndex].find(SerialNumber);
|
||||
if (DeviceHint == SerialNumbers_[hashIndex].end() || DeviceHint->second == nullptr) {
|
||||
return false;
|
||||
}
|
||||
Connection = DeviceHint->second;
|
||||
}
|
||||
Connection->GetLastStats(Statistics);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool AP_WS_Server::GetState(uint64_t SerialNumber, GWObjects::ConnectionState &State) const {
|
||||
auto hashIndex = Utils::CalculateMacAddressHash(SerialNumber);
|
||||
std::lock_guard Lock(SerialNumbersMutex_[hashIndex]);
|
||||
auto Device = SerialNumbers_[hashIndex].find(SerialNumber);
|
||||
if (Device == SerialNumbers_[hashIndex].end() || Device->second.second == nullptr) {
|
||||
return false;
|
||||
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;
|
||||
}
|
||||
Device->second.second->GetState(State);
|
||||
Connection->GetState(State);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool AP_WS_Server::GetHealthcheck(uint64_t SerialNumber,
|
||||
GWObjects::HealthCheck &CheckData) const {
|
||||
|
||||
auto hashIndex = Utils::CalculateMacAddressHash(SerialNumber);
|
||||
std::lock_guard Lock(SerialNumbersMutex_[hashIndex]);
|
||||
auto Device = SerialNumbers_[hashIndex].find(SerialNumber);
|
||||
if (Device == SerialNumbers_[hashIndex].end() || Device->second.second == nullptr) {
|
||||
return false;
|
||||
std::shared_ptr<AP_WS_Connection> Connection;
|
||||
{
|
||||
auto hashIndex = MACHash::Hash(SerialNumber);
|
||||
std::lock_guard DeviceLock(SerialNumbersMutex_[hashIndex]);
|
||||
auto Device = SerialNumbers_[hashIndex].find(SerialNumber);
|
||||
if (Device == SerialNumbers_[hashIndex].end() || Device->second == nullptr) {
|
||||
return false;
|
||||
}
|
||||
Connection = Device->second;
|
||||
}
|
||||
Device->second.second->GetLastHealthCheck(CheckData);
|
||||
Connection->GetLastHealthCheck(CheckData);
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
void AP_WS_Server::SetSessionDetails(uint64_t connection_id, uint64_t SerialNumber) {
|
||||
std::lock_guard SessionLock(SessionMutex_);
|
||||
auto Conn = Sessions_.find(connection_id);
|
||||
if (Conn == end(Sessions_))
|
||||
return;
|
||||
|
||||
auto hashIndex = Utils::CalculateMacAddressHash(SerialNumber);
|
||||
std::lock_guard Lock(SerialNumbersMutex_[hashIndex]);
|
||||
auto CurrentSerialNumber = SerialNumbers_[hashIndex].find(SerialNumber);
|
||||
if ((CurrentSerialNumber == SerialNumbers_[hashIndex].end()) ||
|
||||
(CurrentSerialNumber->second.first < connection_id)) {
|
||||
SerialNumbers_[hashIndex][SerialNumber] = std::make_pair(connection_id, Conn->second);
|
||||
return;
|
||||
void AP_WS_Server::StartSession(uint64_t session_id, uint64_t SerialNumber) {
|
||||
auto sessionHash = SessionHash::Hash(session_id);
|
||||
std::shared_ptr<AP_WS_Connection> Connection;
|
||||
{
|
||||
std::lock_guard SessionLock(SessionMutex_[sessionHash]);
|
||||
auto SessionHint = Sessions_[sessionHash].find(session_id);
|
||||
if (SessionHint == end(Sessions_[sessionHash])) {
|
||||
return;
|
||||
}
|
||||
Connection = SessionHint->second;
|
||||
Sessions_[sessionHash].erase(SessionHint);
|
||||
}
|
||||
|
||||
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) {
|
||||
std::lock_guard SessionLock(SessionMutex_);
|
||||
auto Session = Sessions_.find(session_id);
|
||||
if (Session == end(Sessions_))
|
||||
return false;
|
||||
|
||||
Garbage_.push_back(Session->second);
|
||||
|
||||
auto hashIndex = Utils::CalculateMacAddressHash(SerialNumber);
|
||||
std::lock_guard Lock(SerialNumbersMutex_[hashIndex]);
|
||||
auto Device = SerialNumbers_[hashIndex].find(SerialNumber);
|
||||
if (Device == end(SerialNumbers_[hashIndex])) {
|
||||
Sessions_.erase(Session);
|
||||
return false;
|
||||
{
|
||||
poco_trace(Logger(), fmt::format("Ending session 1: {} for device: {}", session_id, Utils::IntToSerialNumber(SerialNumber)));
|
||||
auto sessionHash = SessionHash::Hash(session_id);
|
||||
std::lock_guard SessionLock(SessionMutex_[sessionHash]);
|
||||
Sessions_[sessionHash].erase(session_id);
|
||||
poco_trace(Logger(), fmt::format("Ended session 1: {} for device: {}", session_id, Utils::IntToSerialNumber(SerialNumber)));
|
||||
}
|
||||
|
||||
if (Device->second.first == session_id) {
|
||||
Sessions_.erase(Session);
|
||||
SerialNumbers_[hashIndex].erase(Device);
|
||||
return true;
|
||||
{
|
||||
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]);
|
||||
poco_trace(Logger(), fmt::format("Ending session 2.1: {} for device: {} hi:{}", session_id, Utils::IntToSerialNumber(SerialNumber), hashIndex));
|
||||
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()
|
||||
|| DeviceHint->second == nullptr
|
||||
|| 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;
|
||||
}
|
||||
SerialNumbers_[hashIndex].erase(DeviceHint);
|
||||
poco_trace(Logger(), fmt::format("Ended session 2: {} for device: {}", session_id, Utils::IntToSerialNumber(SerialNumber)));
|
||||
}
|
||||
|
||||
Sessions_.erase(Session);
|
||||
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool AP_WS_Server::Connected(uint64_t SerialNumber,
|
||||
GWObjects::DeviceRestrictions &Restrictions) const {
|
||||
auto hashIndex = Utils::CalculateMacAddressHash(SerialNumber);
|
||||
std::lock_guard Lock(SerialNumbersMutex_[hashIndex]);
|
||||
auto Device = SerialNumbers_[hashIndex].find(SerialNumber);
|
||||
if (Device == end(SerialNumbers_[hashIndex]) || Device->second.second == nullptr) {
|
||||
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 == end(SerialNumbers_[hashIndex]) || DeviceHint->second == nullptr) {
|
||||
return false;
|
||||
}
|
||||
Connection = DeviceHint->second;
|
||||
}
|
||||
|
||||
if(Connection->Dead_) {
|
||||
return false;
|
||||
}
|
||||
Device->second.second->GetRestrictions(Restrictions);
|
||||
return Device->second.second->State_.Connected;
|
||||
Restrictions = Connection->GetRestrictions();
|
||||
return Connection->State_.Connected;
|
||||
}
|
||||
|
||||
|
||||
bool AP_WS_Server::Connected(uint64_t SerialNumber) const {
|
||||
auto hashIndex = Utils::CalculateMacAddressHash(SerialNumber);
|
||||
std::lock_guard Lock(SerialNumbersMutex_[hashIndex]);
|
||||
auto Device = SerialNumbers_[hashIndex].find(SerialNumber);
|
||||
if (Device == end(SerialNumbers_[hashIndex]) || Device->second.second == nullptr) {
|
||||
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 == end(SerialNumbers_[hashIndex]) || DeviceHint->second == nullptr) {
|
||||
return false;
|
||||
}
|
||||
Connection = DeviceHint->second;
|
||||
}
|
||||
|
||||
if(Connection->Dead_) {
|
||||
return false;
|
||||
}
|
||||
return Device->second.second->State_.Connected;
|
||||
return Connection->State_.Connected;
|
||||
}
|
||||
|
||||
bool AP_WS_Server::SendFrame(uint64_t SerialNumber, const std::string &Payload) const {
|
||||
auto hashIndex = Utils::CalculateMacAddressHash(SerialNumber);
|
||||
std::lock_guard Lock(SerialNumbersMutex_[hashIndex]);
|
||||
auto Device = SerialNumbers_[hashIndex].find(SerialNumber);
|
||||
if (Device == end(SerialNumbers_[hashIndex]) || Device->second.second == nullptr) {
|
||||
auto hashIndex = MACHash::Hash(SerialNumber);
|
||||
|
||||
std::shared_ptr<AP_WS_Connection> Connection;
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
try {
|
||||
return Device->second.second->Send(Payload);
|
||||
return Connection->Send(Payload);
|
||||
} catch (...) {
|
||||
poco_debug(Logger(), fmt::format(": SendFrame: Could not send data to device '{}'",
|
||||
Utils::IntToSerialNumber(SerialNumber)));
|
||||
@@ -401,48 +625,64 @@ namespace OpenWifi {
|
||||
}
|
||||
|
||||
void AP_WS_Server::StopWebSocketTelemetry(uint64_t RPCID, uint64_t SerialNumber) {
|
||||
auto hashIndex = Utils::CalculateMacAddressHash(SerialNumber);
|
||||
std::lock_guard Lock(SerialNumbersMutex_[hashIndex]);
|
||||
auto Device = SerialNumbers_[hashIndex].find(SerialNumber);
|
||||
if (Device == end(SerialNumbers_[hashIndex]) || Device->second.second == nullptr) {
|
||||
return;
|
||||
std::shared_ptr<AP_WS_Connection> Connection;
|
||||
{
|
||||
auto hashIndex = MACHash::Hash(SerialNumber);
|
||||
std::lock_guard DeviceLock(SerialNumbersMutex_[hashIndex]);
|
||||
auto Device = SerialNumbers_[hashIndex].find(SerialNumber);
|
||||
if (Device == end(SerialNumbers_[hashIndex]) || Device->second == nullptr) {
|
||||
return;
|
||||
}
|
||||
Connection = Device->second;
|
||||
}
|
||||
Device->second.second->StopWebSocketTelemetry(RPCID);
|
||||
Connection->StopWebSocketTelemetry(RPCID);
|
||||
}
|
||||
|
||||
void
|
||||
AP_WS_Server::SetWebSocketTelemetryReporting(uint64_t RPCID, uint64_t SerialNumber,
|
||||
uint64_t Interval, uint64_t Lifetime,
|
||||
const std::vector<std::string> &TelemetryTypes) {
|
||||
auto hashIndex = Utils::CalculateMacAddressHash(SerialNumber);
|
||||
std::lock_guard Lock(SerialNumbersMutex_[hashIndex]);
|
||||
auto Device = SerialNumbers_[hashIndex].find(SerialNumber);
|
||||
if (Device == end(SerialNumbers_[hashIndex]) || Device->second.second == nullptr) {
|
||||
return;
|
||||
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 == end(SerialNumbers_[hashIndex]) || DeviceHint->second == nullptr) {
|
||||
return;
|
||||
}
|
||||
Connection = DeviceHint->second;
|
||||
}
|
||||
Device->second.second->SetWebSocketTelemetryReporting(RPCID, Interval, Lifetime, TelemetryTypes);
|
||||
Connection->SetWebSocketTelemetryReporting(RPCID, Interval, Lifetime, TelemetryTypes);
|
||||
}
|
||||
|
||||
void AP_WS_Server::SetKafkaTelemetryReporting(uint64_t RPCID, uint64_t SerialNumber,
|
||||
uint64_t Interval, uint64_t Lifetime,
|
||||
const std::vector<std::string> &TelemetryTypes) {
|
||||
auto hashIndex = Utils::CalculateMacAddressHash(SerialNumber);
|
||||
std::lock_guard Lock(SerialNumbersMutex_[hashIndex]);
|
||||
auto Device = SerialNumbers_[hashIndex].find(SerialNumber);
|
||||
if (Device == end(SerialNumbers_[hashIndex]) || Device->second.second == nullptr) {
|
||||
return;
|
||||
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 == end(SerialNumbers_[hashIndex]) || DeviceHint->second == nullptr) {
|
||||
return;
|
||||
}
|
||||
Connection = DeviceHint->second;
|
||||
}
|
||||
Device->second.second->SetKafkaTelemetryReporting(RPCID, Interval, Lifetime, TelemetryTypes);
|
||||
Connection->SetKafkaTelemetryReporting(RPCID, Interval, Lifetime, TelemetryTypes);
|
||||
}
|
||||
|
||||
void AP_WS_Server::StopKafkaTelemetry(uint64_t RPCID, uint64_t SerialNumber) {
|
||||
auto hashIndex = Utils::CalculateMacAddressHash(SerialNumber);
|
||||
std::lock_guard Lock(SerialNumbersMutex_[hashIndex]);
|
||||
auto Device = SerialNumbers_[hashIndex].find(SerialNumber);
|
||||
if (Device == end(SerialNumbers_[hashIndex]) || Device->second.second == nullptr) {
|
||||
return;
|
||||
std::shared_ptr<AP_WS_Connection> Connection;
|
||||
{
|
||||
auto hashIndex = MACHash::Hash(SerialNumber);
|
||||
std::lock_guard DevicesLock(SerialNumbersMutex_[hashIndex]);
|
||||
auto DeviceHint = SerialNumbers_[hashIndex].find(SerialNumber);
|
||||
if (DeviceHint == end(SerialNumbers_[hashIndex]) || DeviceHint->second == nullptr) {
|
||||
return;
|
||||
}
|
||||
Connection = DeviceHint->second;
|
||||
}
|
||||
Device->second.second->StopKafkaTelemetry(RPCID);
|
||||
Connection->StopKafkaTelemetry(RPCID);
|
||||
}
|
||||
|
||||
void AP_WS_Server::GetTelemetryParameters(
|
||||
@@ -451,14 +691,18 @@ namespace OpenWifi {
|
||||
uint64_t &TelemetryWebSocketCount, uint64_t &TelemetryKafkaCount,
|
||||
uint64_t &TelemetryWebSocketPackets, uint64_t &TelemetryKafkaPackets) {
|
||||
|
||||
auto hashIndex = Utils::CalculateMacAddressHash(SerialNumber);
|
||||
std::lock_guard Lock(SerialNumbersMutex_[hashIndex]);
|
||||
auto Device = SerialNumbers_[hashIndex].find(SerialNumber);
|
||||
if (Device == end(SerialNumbers_[hashIndex]) || Device->second.second == nullptr) {
|
||||
return;
|
||||
std::shared_ptr<AP_WS_Connection> Connection;
|
||||
{
|
||||
auto hashIndex = MACHash::Hash(SerialNumber);
|
||||
std::lock_guard DevicesLock(SerialNumbersMutex_[hashIndex]);
|
||||
auto DeviceHint = SerialNumbers_[hashIndex].find(SerialNumber);
|
||||
if (DeviceHint == end(SerialNumbers_[hashIndex]) || DeviceHint->second == nullptr) {
|
||||
return;
|
||||
}
|
||||
Connection = DeviceHint->second;
|
||||
}
|
||||
|
||||
Device->second.second->GetTelemetryParameters(TelemetryRunning, TelemetryInterval,
|
||||
Connection->GetTelemetryParameters(TelemetryRunning, TelemetryInterval,
|
||||
TelemetryWebSocketTimer, TelemetryKafkaTimer,
|
||||
TelemetryWebSocketCount, TelemetryKafkaCount,
|
||||
TelemetryWebSocketPackets, TelemetryKafkaPackets);
|
||||
@@ -467,16 +711,24 @@ namespace OpenWifi {
|
||||
bool AP_WS_Server::SendRadiusAccountingData(const std::string &SerialNumber,
|
||||
const unsigned char *buffer, std::size_t size) {
|
||||
|
||||
auto IntSerialNumber = Utils::SerialNumberToInt(SerialNumber);
|
||||
auto hashIndex = Utils::CalculateMacAddressHash(IntSerialNumber);
|
||||
std::lock_guard Lock(SerialNumbersMutex_[hashIndex]);
|
||||
auto Device = SerialNumbers_[hashIndex].find(IntSerialNumber);
|
||||
if (Device == end(SerialNumbers_[hashIndex]) || Device->second.second == nullptr) {
|
||||
std::shared_ptr<AP_WS_Connection> Connection;
|
||||
{
|
||||
auto IntSerialNumber = Utils::SerialNumberToInt(SerialNumber);
|
||||
auto hashIndex = MACHash::Hash(IntSerialNumber);
|
||||
std::lock_guard DevicesLock(SerialNumbersMutex_[hashIndex]);
|
||||
auto DeviceHint = SerialNumbers_[hashIndex].find(IntSerialNumber);
|
||||
if (DeviceHint == end(SerialNumbers_[hashIndex]) || DeviceHint->second == nullptr) {
|
||||
return false;
|
||||
}
|
||||
Connection = DeviceHint->second;
|
||||
}
|
||||
|
||||
if(Connection->Dead_) {
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
return Device->second.second->SendRadiusAccountingData(buffer, size);
|
||||
return Connection->SendRadiusAccountingData(buffer, size);
|
||||
} catch (...) {
|
||||
poco_debug(
|
||||
Logger(),
|
||||
@@ -488,16 +740,24 @@ namespace OpenWifi {
|
||||
|
||||
bool AP_WS_Server::SendRadiusAuthenticationData(const std::string &SerialNumber,
|
||||
const unsigned char *buffer, std::size_t size) {
|
||||
auto IntSerialNumber = Utils::SerialNumberToInt(SerialNumber);
|
||||
auto hashIndex = Utils::CalculateMacAddressHash(IntSerialNumber);
|
||||
std::lock_guard Lock(SerialNumbersMutex_[hashIndex]);
|
||||
auto Device = SerialNumbers_[hashIndex].find(IntSerialNumber);
|
||||
if (Device == end(SerialNumbers_[hashIndex]) || Device->second.second == nullptr) {
|
||||
std::shared_ptr<AP_WS_Connection> Connection;
|
||||
{
|
||||
auto IntSerialNumber = Utils::SerialNumberToInt(SerialNumber);
|
||||
auto hashIndex = MACHash::Hash(IntSerialNumber);
|
||||
std::lock_guard DevicesLock(SerialNumbersMutex_[hashIndex]);
|
||||
auto DeviceHint = SerialNumbers_[hashIndex].find(IntSerialNumber);
|
||||
if (DeviceHint == end(SerialNumbers_[hashIndex]) || DeviceHint->second == nullptr) {
|
||||
return false;
|
||||
}
|
||||
Connection = DeviceHint->second;
|
||||
}
|
||||
|
||||
if(Connection->Dead_) {
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
return Device->second.second->SendRadiusAuthenticationData(buffer, size);
|
||||
return Connection->SendRadiusAuthenticationData(buffer, size);
|
||||
} catch (...) {
|
||||
poco_debug(
|
||||
Logger(),
|
||||
@@ -509,16 +769,23 @@ namespace OpenWifi {
|
||||
|
||||
bool AP_WS_Server::SendRadiusCoAData(const std::string &SerialNumber,
|
||||
const unsigned char *buffer, std::size_t size) {
|
||||
auto IntSerialNumber = Utils::SerialNumberToInt(SerialNumber);
|
||||
auto hashIndex = Utils::CalculateMacAddressHash(IntSerialNumber);
|
||||
std::lock_guard Lock(SerialNumbersMutex_[hashIndex]);
|
||||
auto Device = SerialNumbers_[hashIndex].find(IntSerialNumber);
|
||||
if (Device == end(SerialNumbers_[hashIndex]) || Device->second.second == nullptr) {
|
||||
return false;
|
||||
std::shared_ptr<AP_WS_Connection> Connection;
|
||||
{
|
||||
auto IntSerialNumber = Utils::SerialNumberToInt(SerialNumber);
|
||||
auto hashIndex = MACHash::Hash(IntSerialNumber);
|
||||
std::lock_guard DeviceLock(SerialNumbersMutex_[hashIndex]);
|
||||
auto DeviceHint = SerialNumbers_[hashIndex].find(IntSerialNumber);
|
||||
if (DeviceHint == end(SerialNumbers_[hashIndex]) || DeviceHint->second == nullptr) {
|
||||
return false;
|
||||
}
|
||||
Connection = DeviceHint->second;
|
||||
}
|
||||
|
||||
if(Connection->Dead_) {
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
return Device->second.second->SendRadiusCoAData(buffer, size);
|
||||
return Connection->SendRadiusCoAData(buffer, size);
|
||||
} catch (...) {
|
||||
poco_debug(Logger(),
|
||||
fmt::format(": SendRadiusCoAData: Could not send data to device '{}'",
|
||||
@@ -527,4 +794,4 @@ namespace OpenWifi {
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace OpenWifi
|
||||
} // namespace OpenWifi
|
||||
|
||||
@@ -24,46 +24,51 @@
|
||||
#include "Poco/Timer.h"
|
||||
|
||||
#include "AP_WS_Connection.h"
|
||||
#include "AP_WS_ReactorPool.h"
|
||||
#include "AP_WS_Reactor_Pool.h"
|
||||
|
||||
#include "framework/SubSystemServer.h"
|
||||
#include "framework/utils.h"
|
||||
|
||||
namespace OpenWifi {
|
||||
|
||||
class AP_WS_RequestHandler : public Poco::Net::HTTPRequestHandler {
|
||||
constexpr uint MACHashMax = 256;
|
||||
constexpr uint MACHashMask = MACHashMax-1;
|
||||
class MACHash {
|
||||
public:
|
||||
explicit AP_WS_RequestHandler(Poco::Logger &L, uint64_t id) : Logger_(L), id_(id){};
|
||||
|
||||
void handleRequest(Poco::Net::HTTPServerRequest &request,
|
||||
Poco::Net::HTTPServerResponse &response) override;
|
||||
|
||||
private:
|
||||
Poco::Logger &Logger_;
|
||||
uint64_t id_ = 0;
|
||||
};
|
||||
|
||||
class AP_WS_RequestHandlerFactory : public Poco::Net::HTTPRequestHandlerFactory {
|
||||
public:
|
||||
inline explicit AP_WS_RequestHandlerFactory(Poco::Logger &L) : Logger_(L) {}
|
||||
|
||||
inline Poco::Net::HTTPRequestHandler *
|
||||
createRequestHandler(const Poco::Net::HTTPServerRequest &request) override {
|
||||
if (request.find("Upgrade") != request.end() &&
|
||||
Poco::icompare(request["Upgrade"], "websocket") == 0) {
|
||||
Utils::SetThreadName("ws:conn-init");
|
||||
return new AP_WS_RequestHandler(Logger_, id_++);
|
||||
} else {
|
||||
return nullptr;
|
||||
[[nodiscard]] static inline uint16_t Hash(std::uint64_t value) {
|
||||
uint8_t hash = 0, i=6;
|
||||
while(i) {
|
||||
hash ^= (value & MACHashMask) + 1;
|
||||
value >>= 8;
|
||||
--i;
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
|
||||
private:
|
||||
Poco::Logger &Logger_;
|
||||
inline static uint64_t id_ = 1;
|
||||
[[nodiscard]] static inline uint16_t Hash(const std::string & value) {
|
||||
return Hash(Utils::MACToInt(value));
|
||||
}
|
||||
|
||||
[[nodiscard]] static inline uint16_t HashMax() {
|
||||
return MACHashMax;
|
||||
}
|
||||
};
|
||||
|
||||
class AP_WS_Server : public SubSystemServer {
|
||||
constexpr uint SessionHashMax = 256;
|
||||
constexpr uint SessionHashMask = SessionHashMax-1;
|
||||
class SessionHash {
|
||||
public:
|
||||
[[nodiscard]] static inline uint16_t Hash(std::uint64_t value) {
|
||||
return (value & SessionHashMask);
|
||||
}
|
||||
|
||||
[[nodiscard]] static inline uint16_t HashMax() {
|
||||
return SessionHashMax;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class AP_WS_Server : public SubSystemServer, public Poco::Runnable {
|
||||
public:
|
||||
static auto instance() {
|
||||
static auto instance_ = new AP_WS_Server;
|
||||
@@ -77,48 +82,50 @@ namespace OpenWifi {
|
||||
const Poco::Crypto::X509Certificate &Certificate);
|
||||
|
||||
inline bool IsSimSerialNumber(const std::string &SerialNumber) const {
|
||||
return IsSim(Poco::toLower(SerialNumber)) &&
|
||||
Poco::toLower(SerialNumber) == Poco::toLower(SimulatorId_);
|
||||
return IsSim(SerialNumber) &&
|
||||
SerialNumber == SimulatorId_;
|
||||
}
|
||||
|
||||
inline static bool IsSim(const std::string &SerialNumber) {
|
||||
return SerialNumber.substr(0, 6) == "53494d";
|
||||
}
|
||||
|
||||
inline bool IsSimEnabled() const { return SimulatorEnabled_; }
|
||||
|
||||
inline bool AllowSerialNumberMismatch() const { return AllowSerialNumberMismatch_; }
|
||||
|
||||
inline uint64_t MismatchDepth() const { return MismatchDepth_; }
|
||||
|
||||
inline bool UseProvisioning() const { return LookAtProvisioning_; }
|
||||
inline bool UseDefaults() const { return UseDefaultConfig_; }
|
||||
|
||||
[[nodiscard]] inline Poco::Net::SocketReactor &NextReactor() {
|
||||
void run() override; // Garbage collector thread.
|
||||
[[nodiscard]] inline bool IsSimEnabled() const { return SimulatorEnabled_; }
|
||||
[[nodiscard]] inline bool AllowSerialNumberMismatch() const { return AllowSerialNumberMismatch_; }
|
||||
[[nodiscard]] inline uint64_t MismatchDepth() const { return MismatchDepth_; }
|
||||
[[nodiscard]] inline bool UseProvisioning() const { return LookAtProvisioning_; }
|
||||
[[nodiscard]] inline bool UseDefaults() const { return UseDefaultConfig_; }
|
||||
[[nodiscard]] inline bool Running() const { return Running_; }
|
||||
[[nodiscard]] inline std::pair<std::shared_ptr<Poco::Net::SocketReactor>, std::shared_ptr<LockedDbSession>> NextReactor() {
|
||||
return Reactor_pool_->NextReactor();
|
||||
}
|
||||
[[nodiscard]] inline bool Running() const { return Running_; }
|
||||
|
||||
inline void AddConnection(uint64_t session_id,
|
||||
std::shared_ptr<AP_WS_Connection> Connection) {
|
||||
std::lock_guard Lock(SessionMutex_);
|
||||
Sessions_[session_id] = std::move(Connection);
|
||||
inline void AddConnection(std::shared_ptr<AP_WS_Connection> Connection) {
|
||||
std::uint64_t sessionHash = SessionHash::Hash(Connection->State_.sessionId);
|
||||
std::lock_guard SessionLock(SessionMutex_[sessionHash]);
|
||||
if(Sessions_[sessionHash].find(Connection->State_.sessionId)==end(Sessions_[sessionHash])) {
|
||||
Sessions_[sessionHash][Connection->State_.sessionId] = std::move(Connection);
|
||||
}
|
||||
}
|
||||
|
||||
inline bool DeviceRequiresSecureRtty(uint64_t serialNumber) const {
|
||||
auto hashIndex = Utils::CalculateMacAddressHash(serialNumber);
|
||||
std::lock_guard G(SerialNumbersMutex_[hashIndex]);
|
||||
|
||||
auto Connection = SerialNumbers_[hashIndex].find(serialNumber);
|
||||
if (Connection==end(SerialNumbers_[hashIndex]) || Connection->second.second==nullptr)
|
||||
return false;
|
||||
return Connection->second.second->RttyMustBeSecure_;
|
||||
[[nodiscard]] inline bool DeviceRequiresSecureRTTY(uint64_t serialNumber) const {
|
||||
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 == end(SerialNumbers_[hashIndex]) || DeviceHint->second == nullptr)
|
||||
return false;
|
||||
Connection = DeviceHint->second;
|
||||
}
|
||||
return Connection->RTTYMustBeSecure_;
|
||||
}
|
||||
|
||||
inline bool GetStatistics(const std::string &SerialNumber, std::string &Statistics) const {
|
||||
return GetStatistics(Utils::SerialNumberToInt(SerialNumber), Statistics);
|
||||
}
|
||||
bool GetStatistics(uint64_t SerialNumber, std::string &Statistics) const;
|
||||
[[nodiscard]] bool GetStatistics(uint64_t SerialNumber, std::string &Statistics) const;
|
||||
|
||||
inline bool GetState(const std::string &SerialNumber,
|
||||
GWObjects::ConnectionState &State) const {
|
||||
@@ -134,13 +141,8 @@ namespace OpenWifi {
|
||||
|
||||
bool Connected(uint64_t SerialNumber, GWObjects::DeviceRestrictions &Restrictions) const;
|
||||
bool Connected(uint64_t SerialNumber) const;
|
||||
|
||||
inline bool SendFrame(const std::string &SerialNumber, const std::string &Payload) const {
|
||||
return SendFrame(Utils::SerialNumberToInt(SerialNumber), Payload);
|
||||
}
|
||||
|
||||
bool Disconnect(uint64_t SerialNumber);
|
||||
bool SendFrame(uint64_t SerialNumber, const std::string &Payload) const;
|
||||
|
||||
bool SendRadiusAuthenticationData(const std::string &SerialNumber,
|
||||
const unsigned char *buffer, std::size_t size);
|
||||
bool SendRadiusAccountingData(const std::string &SerialNumber, const unsigned char *buffer,
|
||||
@@ -148,9 +150,8 @@ namespace OpenWifi {
|
||||
bool SendRadiusCoAData(const std::string &SerialNumber, const unsigned char *buffer,
|
||||
std::size_t size);
|
||||
|
||||
void SetSessionDetails(uint64_t connection_id, uint64_t SerialNumber);
|
||||
bool EndSession(uint64_t connection_id, uint64_t serial_number);
|
||||
bool EndSessionUnSafe(uint64_t session_id, uint64_t serial_number);
|
||||
void StartSession(uint64_t session_id, uint64_t SerialNumber);
|
||||
bool EndSession(uint64_t session_id, uint64_t SerialNumber);
|
||||
void SetWebSocketTelemetryReporting(uint64_t RPCID, uint64_t SerialNumber,
|
||||
uint64_t Interval, uint64_t Lifetime,
|
||||
const std::vector<std::string> &TelemetryTypes);
|
||||
@@ -167,7 +168,9 @@ namespace OpenWifi {
|
||||
uint64_t &TelemetryWebSocketPackets,
|
||||
uint64_t &TelemetryKafkaPackets);
|
||||
|
||||
void onGarbageCollecting(Poco::Timer &timer);
|
||||
bool GetHealthDevices(std::uint64_t lowLimit, std::uint64_t highLimit, std::vector<std::string> & SerialNumbers);
|
||||
// bool ExtendedAttributes(const std::string &serialNumber, bool & hasGPS, std::uint64_t &Sanity,
|
||||
// std::double_t &MemoryUsed, std::double_t &Load, std::double_t &Temperature);
|
||||
|
||||
inline void AverageDeviceStatistics(uint64_t &Connections, uint64_t &AverageConnectionTime,
|
||||
uint64_t &NumberOfConnectingDevices) const {
|
||||
@@ -176,94 +179,81 @@ namespace OpenWifi {
|
||||
NumberOfConnectingDevices = NumberOfConnectingDevices_;
|
||||
}
|
||||
|
||||
inline bool SendFrame(const std::string &SerialNumber, const std::string &Payload) const {
|
||||
return SendFrame(Utils::SerialNumberToInt(SerialNumber), Payload);
|
||||
}
|
||||
|
||||
inline void AddRX(std::uint64_t bytes) {
|
||||
std::lock_guard G(StatsMutex_);
|
||||
RX_ += bytes;
|
||||
}
|
||||
|
||||
inline void AddTX(std::uint64_t bytes) {
|
||||
std::lock_guard G(StatsMutex_);
|
||||
TX_ += bytes;
|
||||
}
|
||||
|
||||
inline void GetTotalDataStatistics(std::uint64_t &TX, std::uint64_t &RX) const {
|
||||
std::lock_guard G(StatsMutex_);
|
||||
TX = TX_;
|
||||
RX = RX_;
|
||||
}
|
||||
|
||||
// TOD: move to hash based map.
|
||||
inline bool GetHealthDevices(std::uint64_t lowLimit, std::uint64_t highLimit, std::vector<std::string> & SerialNumbers) {
|
||||
std::lock_guard Lock(SessionMutex_);
|
||||
for(const auto &connection:Sessions_) {
|
||||
if( connection.second->RawLastHealthcheck_.Sanity>=lowLimit &&
|
||||
connection.second->RawLastHealthcheck_.Sanity<=highLimit) {
|
||||
SerialNumbers.push_back(connection.second->SerialNumber_);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
bool KafkaDisableState() const { return KafkaDisableState_; }
|
||||
bool KafkaDisableHealthChecks() const { return KafkaDisableHealthChecks_; }
|
||||
|
||||
inline void IncrementConnectionCount() {
|
||||
++NumberOfConnectedDevices_;
|
||||
}
|
||||
|
||||
inline bool ExtendedAttributes(const std::string &serialNumber,
|
||||
bool & hasGPS,
|
||||
std::uint64_t &Sanity,
|
||||
std::double_t &MemoryUsed,
|
||||
std::double_t &Load,
|
||||
std::double_t &Temperature
|
||||
) {
|
||||
|
||||
auto serialNumberInt = Utils::SerialNumberToInt(serialNumber);
|
||||
auto hashIndex = Utils::CalculateMacAddressHash(serialNumberInt);
|
||||
std::lock_guard G(SerialNumbersMutex_[hashIndex]);
|
||||
auto session_hint = SerialNumbers_[hashIndex].find(Utils::SerialNumberToInt(serialNumber));
|
||||
if(session_hint==end(SerialNumbers_[hashIndex])) {
|
||||
return false;
|
||||
}
|
||||
hasGPS = session_hint->second.second->hasGPS;
|
||||
Sanity = session_hint->second.second->RawLastHealthcheck_.Sanity;
|
||||
MemoryUsed = session_hint->second.second->memory_used_;
|
||||
Load = session_hint->second.second->cpu_load_;
|
||||
Temperature = session_hint->second.second->temperature_;
|
||||
return true;
|
||||
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:
|
||||
mutable std::mutex SessionMutex_;
|
||||
mutable std::mutex StatsMutex_;
|
||||
std::array<std::mutex,SessionHashMax> SessionMutex_;
|
||||
std::array<std::map<std::uint64_t, std::shared_ptr<AP_WS_Connection>>,SessionHashMax> Sessions_;
|
||||
using SerialNumberMap = std::map<uint64_t /* serial number */,
|
||||
std::shared_ptr<AP_WS_Connection>>;
|
||||
std::array<SerialNumberMap,MACHashMax> SerialNumbers_;
|
||||
mutable std::array<std::mutex,MACHashMax> SerialNumbersMutex_;
|
||||
|
||||
std::unique_ptr<Poco::Crypto::X509Certificate> IssuerCert_;
|
||||
std::vector<Poco::Crypto::X509Certificate> ClientCasCerts_;
|
||||
std::list<std::unique_ptr<Poco::Net::HTTPServer>> WebServers_;
|
||||
Poco::ThreadPool DeviceConnectionPool_{"ws:dev-pool", 4, 256};
|
||||
Poco::Net::SocketReactor Reactor_;
|
||||
Poco::Thread ReactorThread_;
|
||||
std::string SimulatorId_;
|
||||
Poco::ThreadPool DeviceConnectionPool_{"ws:dev-pool", 2, 64};
|
||||
bool LookAtProvisioning_ = false;
|
||||
bool UseDefaultConfig_ = true;
|
||||
bool SimulatorEnabled_ = false;
|
||||
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::atomic_bool Running_ = false;
|
||||
std::map<std::uint64_t, std::shared_ptr<AP_WS_Connection>> Sessions_;
|
||||
|
||||
using SerialNumberMap = std::map<uint64_t /* serial number */, std::pair<uint64_t /* session id*/,
|
||||
std::shared_ptr<AP_WS_Connection>>>;
|
||||
std::uint64_t MismatchDepth_ = 2;
|
||||
|
||||
std::array<SerialNumberMap,256> SerialNumbers_;
|
||||
mutable std::array<std::mutex,256> SerialNumbersMutex_;
|
||||
|
||||
std::atomic_bool AllowSerialNumberMismatch_ = true;
|
||||
std::atomic_uint64_t MismatchDepth_ = 2;
|
||||
|
||||
std::uint64_t 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 SessionTimeOut_ = 10*60;
|
||||
|
||||
std::uint64_t LeftOverSessions_ = 0;
|
||||
std::atomic_uint64_t TX_=0,RX_=0;
|
||||
|
||||
std::vector<std::shared_ptr<AP_WS_Connection>> Garbage_;
|
||||
std::atomic_bool KafkaDisableState_=false,
|
||||
KafkaDisableHealthChecks_=false;
|
||||
|
||||
std::unique_ptr<Poco::TimerCallback<AP_WS_Server>> GarbageCollectorCallback_;
|
||||
Poco::Timer Timer_;
|
||||
Poco::Thread GarbageCollector_;
|
||||
Poco::Thread GarbageCollector_;
|
||||
|
||||
AP_WS_Server() noexcept
|
||||
: SubSystemServer("WebSocketServer", "WS-SVR", "ucentral.websocket") {}
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include <string>
|
||||
|
||||
#include "framework/MicroServiceFuncs.h"
|
||||
#include "framework/ow_constants.h"
|
||||
|
||||
#include "CentralConfig.h"
|
||||
#include "nlohmann/json.hpp"
|
||||
@@ -34,7 +35,7 @@ namespace OpenWifi {
|
||||
std::lock_guard G(Mutex_);
|
||||
if (!PlatformsLoaded_)
|
||||
LoadPlatforms();
|
||||
auto P = Poco::toUpper(Caps.Platform());
|
||||
auto P = Poco::toLower(Caps.Platform());
|
||||
auto Hint = Platforms_.find(Caps.Compatible());
|
||||
if (Hint == Platforms_.end()) {
|
||||
Platforms_.insert(std::make_pair(Caps.Compatible(), P));
|
||||
@@ -68,7 +69,7 @@ namespace OpenWifi {
|
||||
|
||||
auto Hint = Platforms_.find(DeviceType);
|
||||
if (Hint == Platforms_.end())
|
||||
return "AP";
|
||||
return Platforms::AP;
|
||||
return Hint->second;
|
||||
}
|
||||
|
||||
@@ -110,7 +111,7 @@ namespace OpenWifi {
|
||||
i >> cache;
|
||||
|
||||
for (const auto &[Type, Platform] : cache.items()) {
|
||||
Platforms_[Type] = Platform;
|
||||
Platforms_[Type] = Poco::toLower(Platform.get<std::string>());
|
||||
}
|
||||
} catch (...) {
|
||||
}
|
||||
|
||||
@@ -204,6 +204,17 @@ namespace OpenWifi::Config {
|
||||
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() {
|
||||
try {
|
||||
Poco::JSON::Parser Parser;
|
||||
@@ -254,7 +265,11 @@ namespace OpenWifi::Config {
|
||||
Model_ = Caps->get("model").toString();
|
||||
|
||||
if (Caps->has("platform"))
|
||||
Platform_ = Caps->get("platform").toString();
|
||||
Platform_ = Poco::toLower(Caps->get("platform").toString());
|
||||
|
||||
if(Compatible_.empty()) {
|
||||
Compatible_ = Model_;
|
||||
}
|
||||
|
||||
std::ostringstream OS;
|
||||
Caps->stringify(OS);
|
||||
|
||||
@@ -23,6 +23,7 @@ namespace OpenWifi::Config {
|
||||
[[nodiscard]] std::string get() { return Config_; };
|
||||
[[nodiscard]] std::string Default();
|
||||
[[nodiscard]] Poco::JSON::Object::Ptr to_json();
|
||||
[[nodiscard]] std::uint64_t UUID();
|
||||
|
||||
private:
|
||||
void Init();
|
||||
|
||||
@@ -45,11 +45,9 @@ namespace OpenWifi {
|
||||
std::lock_guard Lock(LocalMutex_);
|
||||
auto RPC = OutStandingRequests_.find(ID);
|
||||
if (RPC == OutStandingRequests_.end()) {
|
||||
// std::cout << __LINE__ << std::endl;
|
||||
poco_debug(Logger(), fmt::format("({}): RPC {} cannot be found.",
|
||||
SerialNumberStr, ID));
|
||||
} else if (RPC->second.SerialNumber != Resp->SerialNumber_) {
|
||||
// std::cout << __LINE__ << std::endl;
|
||||
poco_debug(
|
||||
Logger(),
|
||||
fmt::format("({}): RPC {} serial number mismatch {}!={}.",
|
||||
@@ -60,7 +58,6 @@ namespace OpenWifi {
|
||||
std::chrono::duration<double, std::milli> rpc_execution_time =
|
||||
std::chrono::high_resolution_clock::now() -
|
||||
RPC->second.submitted;
|
||||
// std::cout << __LINE__ << std::endl;
|
||||
poco_debug(Logger(),
|
||||
fmt::format("({}): Received RPC answer {}. Command={}",
|
||||
SerialNumberStr, ID,
|
||||
@@ -140,7 +137,6 @@ namespace OpenWifi {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// std::cout << __LINE__ << std::endl;
|
||||
}
|
||||
Command.State = 0;
|
||||
|
||||
@@ -163,7 +159,6 @@ namespace OpenWifi {
|
||||
if (Command.rpc_entry) {
|
||||
TmpRpcEntry = Command.rpc_entry;
|
||||
}
|
||||
// std::cout << __LINE__ << " State=" << Command.State << std::endl;
|
||||
if (Command.State == 2) {
|
||||
// look at the payload to see if we should continue or not...
|
||||
if (Payload->has("result")) {
|
||||
@@ -173,12 +168,10 @@ namespace OpenWifi {
|
||||
|
||||
std::uint64_t Error = Status->get("error");
|
||||
if (Error == 0) {
|
||||
// std::cout << __LINE__ << std::endl;
|
||||
StorageService()->CommandCompleted(Command.UUID, Payload,
|
||||
rpc_execution_time, true);
|
||||
Command.State = 1;
|
||||
} else {
|
||||
// std::cout << __LINE__ << std::endl;
|
||||
StorageService()->CommandCompleted(Command.UUID, Payload,
|
||||
rpc_execution_time, true);
|
||||
std::string ErrorTxt = Status->get("result");
|
||||
@@ -186,14 +179,11 @@ namespace OpenWifi {
|
||||
Command.State = 0;
|
||||
}
|
||||
} else {
|
||||
// std::cout << __LINE__ << std::endl;
|
||||
}
|
||||
} else {
|
||||
// std::cout << __LINE__ << std::endl;
|
||||
Command.State = 0;
|
||||
}
|
||||
} else if (Command.State == 1) {
|
||||
// std::cout << "Completing script 2 phase commit." << std::endl;
|
||||
StorageService()->CommandCompleted(Command.UUID, Payload, rpc_execution_time, true);
|
||||
if (Command.Deferred) {
|
||||
Reply = false;
|
||||
@@ -202,7 +192,6 @@ namespace OpenWifi {
|
||||
}
|
||||
|
||||
if (Command.State == 0) {
|
||||
// std::cout << __LINE__ << " State=" << Command.State << std::endl;
|
||||
OutStandingRequests_.erase(Command.Id);
|
||||
}
|
||||
if (Reply && TmpRpcEntry != nullptr)
|
||||
@@ -262,8 +251,6 @@ namespace OpenWifi {
|
||||
for (auto request = OutStandingRequests_.begin(); request != OutStandingRequests_.end();) {
|
||||
std::chrono::duration<double, std::milli> delta = now - request->second.submitted;
|
||||
if (delta > 10min) {
|
||||
// std::cout << __LINE__ << " -->> " << request->second.Id <<
|
||||
// std::endl;
|
||||
MyLogger.debug(fmt::format("{}: Command={} for {} Timed out.", request->second.UUID,
|
||||
APCommands::to_string(request->second.Command),
|
||||
Utils::IntToSerialNumber(request->second.SerialNumber)));
|
||||
@@ -275,8 +262,6 @@ namespace OpenWifi {
|
||||
StorageService()->SetCommandTimedOut(request->second.UUID);
|
||||
request = OutStandingRequests_.erase(request);
|
||||
} else {
|
||||
// std::cout << __LINE__ << " -->> " << request->second.Id <<
|
||||
// std::endl;
|
||||
++request;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,12 +11,12 @@
|
||||
namespace OpenWifi {
|
||||
class ConfigurationCache {
|
||||
public:
|
||||
static ConfigurationCache &instance() {
|
||||
static ConfigurationCache instance;
|
||||
static auto instance() {
|
||||
static auto instance = new ConfigurationCache;
|
||||
return instance;
|
||||
}
|
||||
|
||||
inline uint64_t CurrentConfig(uint64_t SerialNumber) {
|
||||
inline uint64_t GetCurrentConfig(std::uint64_t SerialNumber) {
|
||||
std::lock_guard G(Mutex_);
|
||||
const auto Hint = Cache_.find(SerialNumber);
|
||||
if (Hint == end(Cache_))
|
||||
@@ -24,25 +24,25 @@ namespace OpenWifi {
|
||||
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_);
|
||||
Cache_[SerialNumber] = Id;
|
||||
}
|
||||
|
||||
private:
|
||||
std::recursive_mutex Mutex_;
|
||||
std::mutex Mutex_;
|
||||
std::map<uint64_t, uint64_t> Cache_;
|
||||
};
|
||||
|
||||
inline uint64_t GetCurrentConfigurationID(uint64_t SerialNumber) {
|
||||
return ConfigurationCache::instance().CurrentConfig(SerialNumber);
|
||||
inline auto GetCurrentConfigurationID(std::uint64_t SerialNumber) {
|
||||
return ConfigurationCache::instance()->GetCurrentConfig(SerialNumber);
|
||||
}
|
||||
|
||||
inline void SetCurrentConfigurationID(const std::string &SerialNumber, uint64_t ID) {
|
||||
return ConfigurationCache::instance().Add(Utils::SerialNumberToInt(SerialNumber), ID);
|
||||
inline void SetCurrentConfigurationID(const std::string &SerialNumber, std::uint64_t ID) {
|
||||
return ConfigurationCache::instance()->SetCurrentConfig(Utils::SerialNumberToInt(SerialNumber), ID);
|
||||
}
|
||||
|
||||
inline void SetCurrentConfigurationID(uint64_t SerialNumber, uint64_t ID) {
|
||||
return ConfigurationCache::instance().Add(SerialNumber, ID);
|
||||
inline void SetCurrentConfigurationID(uint64_t SerialNumber, std::uint64_t ID) {
|
||||
return ConfigurationCache::instance()->SetCurrentConfig(SerialNumber, ID);
|
||||
}
|
||||
} // namespace OpenWifi
|
||||
|
||||
@@ -49,7 +49,7 @@ namespace OpenWifi {
|
||||
SignatureManager(), AP_WS_Server(),
|
||||
RegulatoryInfo(),
|
||||
RADIUSSessionTracker(),
|
||||
AP_WS_ConfigAutoUpgrader(),
|
||||
AP_WS_ConfigAutoUpgradeAgent(),
|
||||
FirmwareRevisionCache()
|
||||
});
|
||||
return &instance;
|
||||
@@ -78,7 +78,7 @@ namespace OpenWifi {
|
||||
if (Id == DeviceType)
|
||||
return Type;
|
||||
}
|
||||
return "AP";
|
||||
return Platforms::AP;
|
||||
}
|
||||
|
||||
void DaemonPostInitialization(Poco::Util::Application &self) {
|
||||
|
||||
@@ -21,7 +21,6 @@ namespace OpenWifi {
|
||||
|
||||
void DeviceDashboard::Generate(GWObjects::Dashboard &D, Poco::Logger &Logger) {
|
||||
if (GeneratingDashboard_.load()) {
|
||||
// std::cout << "Trying to generate dashboard but already being generated" << std::endl;
|
||||
while (GeneratingDashboard_.load()) {
|
||||
Poco::Thread::trySleep(100);
|
||||
}
|
||||
@@ -31,7 +30,6 @@ namespace OpenWifi {
|
||||
GeneratingDashboard_ = true;
|
||||
ValidDashboard_ = false;
|
||||
try {
|
||||
// std::cout << "Generating dashboard." << std::endl;
|
||||
poco_information(Logger, "DASHBOARD: Generating a new dashboard.");
|
||||
GWObjects::Dashboard NewData;
|
||||
StorageService()->AnalyzeCommands(NewData.commands);
|
||||
|
||||
@@ -315,4 +315,4 @@ namespace OpenWifi {
|
||||
poco_notice(Logger(), "Stopped...");
|
||||
}
|
||||
|
||||
} // namespace OpenWifi
|
||||
} // namespace OpenWifi
|
||||
|
||||
@@ -8,12 +8,12 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Poco/Net/HTTPRequestHandler.h"
|
||||
#include "Poco/Net/HTTPRequestHandlerFactory.h"
|
||||
#include "Poco/Net/HTTPServer.h"
|
||||
#include "Poco/Net/HTTPServerRequest.h"
|
||||
#include <Poco/Net/HTTPRequestHandler.h>
|
||||
#include <Poco/Net/HTTPRequestHandlerFactory.h>
|
||||
#include <Poco/Net/HTTPServer.h>
|
||||
#include <Poco/Net/HTTPServerRequest.h>
|
||||
|
||||
#include "framework/SubSystemServer.h"
|
||||
#include <framework/SubSystemServer.h>
|
||||
|
||||
namespace OpenWifi {
|
||||
|
||||
|
||||
@@ -50,12 +50,22 @@ namespace OpenWifi {
|
||||
class DeviceConfigurationChangeKafkaEvent : public GWKafkaEvents {
|
||||
public:
|
||||
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) {
|
||||
}
|
||||
|
||||
~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();
|
||||
}
|
||||
|
||||
|
||||
@@ -1753,7 +1753,6 @@ namespace OpenWifi {
|
||||
nlohmann::json new_ie;
|
||||
nlohmann::json content;
|
||||
|
||||
// std::cout << BufferToHex(&data[0],data.size()) << std::endl;
|
||||
uint offset = 0;
|
||||
auto sub_ie = data[offset++];
|
||||
switch (sub_ie) {
|
||||
@@ -1788,7 +1787,6 @@ namespace OpenWifi {
|
||||
|
||||
try {
|
||||
nlohmann::json D = nlohmann::json::parse(ofs.str());
|
||||
// std::cout << "Start of parsing wifi" << std::endl;
|
||||
if (D.contains("status")) {
|
||||
auto Status = D["status"];
|
||||
if (Status.contains("scan") && Status["scan"].is_array()) {
|
||||
@@ -1803,8 +1801,6 @@ namespace OpenWifi {
|
||||
if (ie.contains("type") && ie.contains("data")) {
|
||||
uint64_t ie_type = ie["type"];
|
||||
std::string ie_data = ie["data"];
|
||||
// std::cout << "TYPE:" << ie_type << " DATA:" << ie_data
|
||||
// << std::endl;
|
||||
auto data = Base64Decode2Vec(ie_data);
|
||||
if (ie_type == ieee80211_eid::WLAN_EID_COUNTRY) {
|
||||
new_ies.push_back(WFS_WLAN_EID_COUNTRY(data));
|
||||
@@ -1858,18 +1854,12 @@ namespace OpenWifi {
|
||||
} else if (ie_type == ieee80211_eid::WLAN_EID_EXTENSION) {
|
||||
new_ies.push_back(WFS_WLAN_EID_EXTENSION(data));
|
||||
} else {
|
||||
// std::cout
|
||||
// << "Skipping IE: no parsing available: " << ie_type
|
||||
// << std::endl;
|
||||
new_ies.push_back(ie);
|
||||
}
|
||||
} else {
|
||||
// std::cout << "Skipping IE: no data and type" <<
|
||||
// std::endl;
|
||||
new_ies.push_back(ie);
|
||||
}
|
||||
} catch (...) {
|
||||
// std::cout << "Skipping IE: exception" << std::endl;
|
||||
Logger.information(fmt::format("Error parsing IEs"));
|
||||
new_ies.push_back(ie);
|
||||
}
|
||||
@@ -1877,7 +1867,6 @@ namespace OpenWifi {
|
||||
scan_entry["ies"] = new_ies;
|
||||
ParsedScan.push_back(scan_entry);
|
||||
} else {
|
||||
// std::cout << "Skipping scan" << std::endl;
|
||||
ParsedScan.push_back(scan_entry);
|
||||
}
|
||||
}
|
||||
@@ -1886,7 +1875,6 @@ namespace OpenWifi {
|
||||
}
|
||||
}
|
||||
Result << to_string(D);
|
||||
// std::cout << "End of parsing wifi" << std::endl;
|
||||
return true;
|
||||
} catch (const Poco::Exception &E) {
|
||||
Logger.log(E);
|
||||
|
||||
@@ -177,15 +177,6 @@ namespace OpenWifi {
|
||||
} else {
|
||||
session_hint->second->lastTransaction = Utils::Now();
|
||||
}
|
||||
|
||||
/*
|
||||
if(ap_hint!=AccountingSessions_.end()) {
|
||||
std::cout << "Auth table:" << std::endl;
|
||||
for(const auto &session:ap_hint->second) {
|
||||
std::cout << Notification.SerialNumber_ << ": Index: " << session.first << ": ID: " << session.second->accountingSessionId << " MID:" << session.second->accountingMultiSessionId << std::endl;
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
std::uint32_t GetUiInt32(const std::uint8_t *buf) {
|
||||
@@ -423,15 +414,15 @@ namespace OpenWifi {
|
||||
}
|
||||
|
||||
void RADIUSSessionTracker::DisconnectSession(const std::string &SerialNumber) {
|
||||
poco_information(Logger(),fmt::format("{}: Disconnecting.", SerialNumber));
|
||||
|
||||
std::lock_guard Guard(Mutex_);
|
||||
|
||||
auto hint = AccountingSessions_.find(SerialNumber);
|
||||
if(hint==end(AccountingSessions_)) {
|
||||
return;
|
||||
}
|
||||
|
||||
poco_information(Logger(),fmt::format("{}: Disconnecting.", SerialNumber));
|
||||
|
||||
// we need to go through all sessions and send an accounting stop
|
||||
for(const auto &session:hint->second) {
|
||||
poco_debug(Logger(), fmt::format("Stopping accounting for {}:{}", SerialNumber, session.first ));
|
||||
|
||||
@@ -75,8 +75,10 @@ namespace OpenWifi {
|
||||
} else if ((Utils::Now() - LastKeepAlive) > Pool_.radsecKeepAlive) {
|
||||
RADIUS::RadiusOutputPacket P(Pool_.authConfig.servers[ServerIndex_].radsecSecret);
|
||||
P.MakeStatusMessage(Pool_.authConfig.servers[ServerIndex_].name);
|
||||
poco_trace(Logger_, fmt::format("{}: Keep-Alive message.", Pool_.authConfig.servers[ServerIndex_].name));
|
||||
Socket_->sendBytes(P.Data(), P.Len());
|
||||
if(Type_!=GWObjects::RadiusEndpointType::generic) {
|
||||
poco_trace(Logger_, fmt::format("{}: Keep-Alive message.", Pool_.authConfig.servers[ServerIndex_].name));
|
||||
Socket_->sendBytes(P.Data(), P.Len());
|
||||
}
|
||||
LastKeepAlive = Utils::Now();
|
||||
}
|
||||
Poco::Thread::trySleep(2000);
|
||||
@@ -163,17 +165,16 @@ namespace OpenWifi {
|
||||
fmt::format("Unknown packet: Type: {} (type={}) Length={}",
|
||||
P.PacketType(), P.PacketTypeInt(), P.BufferLen()));
|
||||
}
|
||||
return;
|
||||
} else {
|
||||
poco_warning(Logger_, "Invalid packet received. Resetting the connection.");
|
||||
Disconnect();
|
||||
}
|
||||
} catch (const Poco::Exception &E) {
|
||||
Logger_.log(E);
|
||||
Disconnect();
|
||||
} catch (...) {
|
||||
Disconnect();
|
||||
poco_warning(Logger_, "Exception occurred. Resetting the connection.");
|
||||
}
|
||||
Disconnect();
|
||||
}
|
||||
|
||||
inline void
|
||||
@@ -324,7 +325,7 @@ namespace OpenWifi {
|
||||
ofs << OpenRoamingRootCert;
|
||||
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, ""));
|
||||
|
||||
if (Pool_.acctConfig.servers[ServerIndex_].allowSelfSigned) {
|
||||
@@ -430,7 +431,7 @@ namespace OpenWifi {
|
||||
DecodeFile(CaCertFiles_[CaCertFiles_.size() - 1]->path(), cert);
|
||||
}
|
||||
|
||||
Poco::Net::Context::Ptr SecureContext =
|
||||
auto SecureContext =
|
||||
Poco::AutoPtr<Poco::Net::Context>(new Poco::Net::Context(
|
||||
Poco::Net::Context::TLS_CLIENT_USE, KeyFile_.path(), CertFile_.path(), ""));
|
||||
if (Pool_.acctConfig.servers[ServerIndex_].allowSelfSigned) {
|
||||
@@ -498,7 +499,9 @@ namespace OpenWifi {
|
||||
}
|
||||
|
||||
inline bool Connect_Generic() {
|
||||
if (TryAgain_) {
|
||||
poco_information(Logger_, fmt::format("Connecting {}", Pool_.name));
|
||||
if (TryAgain_ && !Connected_) {
|
||||
|
||||
std::lock_guard G(LocalMutex_);
|
||||
|
||||
Poco::Net::SocketAddress AuthSockAddrV4(
|
||||
@@ -520,26 +523,6 @@ namespace OpenWifi {
|
||||
MicroServiceConfigGetInt("radius.proxy.coa.port", DEFAULT_RADIUS_CoA_PORT));
|
||||
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(
|
||||
*AuthenticationSocketV4_,
|
||||
Poco::NObserver<RADIUS_Destination, Poco::Net::ReadableNotification>(
|
||||
@@ -551,7 +534,27 @@ namespace OpenWifi {
|
||||
Reactor_.addEventHandler(
|
||||
*CoASocketV4_, Poco::NObserver<RADIUS_Destination, Poco::Net::ReadableNotification>(
|
||||
*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(
|
||||
*AuthenticationSocketV6_,
|
||||
Poco::NObserver<RADIUS_Destination, Poco::Net::ReadableNotification>(
|
||||
@@ -565,6 +568,7 @@ namespace OpenWifi {
|
||||
*CoASocketV6_, Poco::NObserver<RADIUS_Destination, Poco::Net::ReadableNotification>(
|
||||
*this, &RADIUS_Destination::OnCoASocketReadable));
|
||||
*/
|
||||
Connected_ = true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -590,6 +594,8 @@ namespace OpenWifi {
|
||||
if (Connected_) {
|
||||
std::lock_guard G(LocalMutex_);
|
||||
if(Type_==GWObjects::RadiusEndpointType::generic) {
|
||||
poco_information(Logger_, fmt::format("Disconnecting {} generic server. Releasing all UDP resources.", Pool_.name));
|
||||
|
||||
if(AuthenticationSocketV4_) {
|
||||
Reactor_.removeEventHandler(
|
||||
*AuthenticationSocketV4_,
|
||||
@@ -617,7 +623,8 @@ namespace OpenWifi {
|
||||
CoASocketV4_.reset();
|
||||
}
|
||||
|
||||
/* if(AuthenticationSocketV6_) {
|
||||
/*
|
||||
if(AuthenticationSocketV6_) {
|
||||
Reactor_.removeEventHandler(
|
||||
*AuthenticationSocketV6_,
|
||||
Poco::NObserver<RADIUS_Destination, Poco::Net::ReadableNotification>(
|
||||
@@ -646,7 +653,6 @@ namespace OpenWifi {
|
||||
*/
|
||||
} else {
|
||||
if(Socket_!=nullptr) {
|
||||
std::lock_guard G(LocalMutex_);
|
||||
Reactor_.removeEventHandler(
|
||||
*Socket_, Poco::NObserver<RADIUS_Destination, Poco::Net::ReadableNotification>(
|
||||
*this, &RADIUS_Destination::onData));
|
||||
@@ -660,9 +666,9 @@ namespace OpenWifi {
|
||||
Socket_->close();
|
||||
}
|
||||
}
|
||||
Connected_ = false;
|
||||
}
|
||||
Connected_ = false;
|
||||
poco_information(Logger_, "Disconnecting.");
|
||||
poco_information(Logger_, fmt::format("Disconnecting {}", Pool_.name));
|
||||
}
|
||||
|
||||
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> 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> AuthenticationSocketV6_;
|
||||
*/
|
||||
|
||||
@@ -25,9 +25,23 @@ namespace OpenWifi::RESTAPI_RPC {
|
||||
if (StorageService()->AddCommand(Cmd.SerialNumber, Cmd, Status)) {
|
||||
Poco::JSON::Object RetObj;
|
||||
Cmd.to_json(RetObj);
|
||||
if (Handler != nullptr)
|
||||
return Handler->ReturnObject(RetObj);
|
||||
return;
|
||||
if (Handler == nullptr) {
|
||||
// nothing to process/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)
|
||||
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,
|
||||
RESTAPIHandler *Handler, Poco::Logger &Logger, bool Deferred) {
|
||||
|
||||
Logger.information(fmt::format("{},{}: New {} command. User={} Serial={}. ", Cmd.UUID,
|
||||
RPCID, Cmd.Command, Cmd.SubmittedBy, Cmd.SerialNumber));
|
||||
Logger.information(fmt::format("{},{}: New {} command. User={} Serial={} Details={}. ", Cmd.UUID,
|
||||
RPCID, Cmd.Command, Cmd.SubmittedBy, Cmd.SerialNumber, Cmd.Details));
|
||||
Cmd.Submitted = Utils::Now();
|
||||
Cmd.Executed = 0;
|
||||
|
||||
@@ -167,6 +181,20 @@ namespace OpenWifi::RESTAPI_RPC {
|
||||
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) {
|
||||
// we need to post a kafka event for this.
|
||||
if (Params.has(uCentralProtocol::CONFIG) && Params.isObject(uCentralProtocol::CONFIG)) {
|
||||
@@ -175,6 +203,7 @@ namespace OpenWifi::RESTAPI_RPC {
|
||||
DeviceConfigurationChangeKafkaEvent KEvent(
|
||||
Utils::SerialNumberToInt(Cmd.SerialNumber), Utils::Now(),
|
||||
Config);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -63,7 +63,7 @@ namespace OpenWifi {
|
||||
poco_debug(Logger(), fmt::format("BLACKLIST-POST: {}", D.serialNumber));
|
||||
|
||||
Poco::toLowerInPlace(D.serialNumber);
|
||||
if (StorageService()->IsBlackListed(D.serialNumber)) {
|
||||
if (StorageService()->IsBlackListed(Utils::MACToInt(D.serialNumber))) {
|
||||
return BadRequest(RESTAPI::Errors::SerialNumberExists);
|
||||
}
|
||||
|
||||
|
||||
@@ -56,17 +56,27 @@ namespace OpenWifi {
|
||||
return BadRequest(RESTAPI::Errors::InvalidJSONDocument);
|
||||
}
|
||||
|
||||
if (DefConfig.Models.empty()) {
|
||||
if (DefConfig.models.empty()) {
|
||||
return BadRequest(RESTAPI::Errors::ModelIDListCannotBeEmpty);
|
||||
}
|
||||
|
||||
std::vector<std::string> Error;
|
||||
if (!ValidateUCentralConfiguration(DefConfig.Configuration, Error,
|
||||
GetBoolParameter("strict", false))) {
|
||||
return BadRequest(RESTAPI::Errors::ConfigBlockInvalid);
|
||||
DefConfig.platform = DefConfig.platform.empty() ? Platforms::AP : DefConfig.platform;
|
||||
if(DefConfig.platform != Platforms::AP && DefConfig.platform != Platforms::SWITCH) {
|
||||
return BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
|
||||
}
|
||||
|
||||
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)) {
|
||||
return OK();
|
||||
}
|
||||
@@ -88,19 +98,31 @@ namespace OpenWifi {
|
||||
return NotFound();
|
||||
}
|
||||
|
||||
if (!NewConfig.Configuration.empty()) {
|
||||
std::vector<std::string> Error;
|
||||
if (!ValidateUCentralConfiguration(NewConfig.Configuration, Error,
|
||||
GetBoolParameter("strict", false))) {
|
||||
return BadRequest(RESTAPI::Errors::ConfigBlockInvalid);
|
||||
}
|
||||
Existing.Configuration = NewConfig.Configuration;
|
||||
if(Existing.platform.empty()) {
|
||||
Existing.platform = Platforms::AP;
|
||||
}
|
||||
|
||||
Existing.LastModified = Utils::Now();
|
||||
AssignIfPresent(Obj, "description", Existing.Description);
|
||||
if(ParsedBody_->has("platform")) {
|
||||
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"))
|
||||
Existing.Models = NewConfig.Models;
|
||||
Existing.models = NewConfig.models;
|
||||
|
||||
if (StorageService()->UpdateDefaultConfiguration(Name, Existing)) {
|
||||
GWObjects::DefaultConfiguration ModifiedConfig;
|
||||
|
||||
@@ -87,10 +87,35 @@ namespace OpenWifi {
|
||||
poco_debug(
|
||||
Logger_,
|
||||
fmt::format(
|
||||
"Command rtty TID={} can proceed. Identified as {} and RPCID as {}. thr_id={}",
|
||||
"Command RTTY TID={} can proceed. Identified as {} and RPCID as {}. thr_id={}",
|
||||
TransactionId_, UUID, RPC, Poco::Thread::current()->id()));
|
||||
return Rtty(UUID, RPC, 60000ms, Restrictions);
|
||||
};
|
||||
case APCommands::Commands::package:{
|
||||
GWObjects::DeviceRestrictions Restrictions;
|
||||
std::string pkg_name = "";
|
||||
if (!AP_WS_Server()->Connected(SerialNumberInt_, Restrictions)) {
|
||||
CallCanceled(Command_.c_str(), RESTAPI::Errors::DeviceNotConnected);
|
||||
return BadRequest(RESTAPI::Errors::DeviceNotConnected);
|
||||
}
|
||||
Poco::URI uri(Request->getURI());
|
||||
for (const auto ¶m : uri.getQueryParameters()) {
|
||||
if (param.first == "pkgName") {
|
||||
pkg_name = param.second;
|
||||
}
|
||||
}
|
||||
if (pkg_name.empty()) {
|
||||
return BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
|
||||
}
|
||||
auto UUID = MicroServiceCreateUUID();
|
||||
auto RPC = CommandManager()->Next_RPC_ID();
|
||||
poco_debug(
|
||||
Logger_,
|
||||
fmt::format(
|
||||
"Command Package TID={} can proceed. Identified as {} and RPCID as {}. thr_id={}",
|
||||
TransactionId_, UUID, RPC, Poco::Thread::current()->id()));
|
||||
return GetPackages(UUID, RPC, pkg_name, 300000ms, Restrictions);
|
||||
}
|
||||
default:
|
||||
return BadRequest(RESTAPI::Errors::InvalidCommand);
|
||||
}
|
||||
@@ -128,6 +153,21 @@ namespace OpenWifi {
|
||||
return DeleteChecks();
|
||||
case APCommands::Commands::statistics:
|
||||
return DeleteStatistics();
|
||||
case APCommands::Commands::package: {
|
||||
GWObjects::DeviceRestrictions Restrictions;
|
||||
if (!AP_WS_Server()->Connected(SerialNumberInt_, Restrictions)) {
|
||||
CallCanceled(Command_.c_str(), RESTAPI::Errors::DeviceNotConnected);
|
||||
return BadRequest(RESTAPI::Errors::DeviceNotConnected);
|
||||
}
|
||||
auto UUID = MicroServiceCreateUUID();
|
||||
auto RPC = CommandManager()->Next_RPC_ID();
|
||||
poco_debug(
|
||||
Logger_,
|
||||
fmt::format(
|
||||
"Command RTTY TID={} can proceed. Identified as {} and RPCID as {}. thr_id={}",
|
||||
TransactionId_, UUID, RPC, Poco::Thread::current()->id()));
|
||||
return DeletePackages(UUID, RPC, 300000ms, Restrictions);
|
||||
}
|
||||
default:
|
||||
return BadRequest(RESTAPI::Errors::InvalidCommand);
|
||||
}
|
||||
@@ -166,7 +206,12 @@ namespace OpenWifi {
|
||||
{APCommands::Commands::rrm, false, true, &RESTAPI_device_commandHandler::RRM, 60000ms},
|
||||
{APCommands::Commands::certupdate, false, true, &RESTAPI_device_commandHandler::CertUpdate, 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},
|
||||
{APCommands::Commands::package, false, true, &RESTAPI_device_commandHandler::PackageInstall, 120000ms},
|
||||
};
|
||||
|
||||
void RESTAPI_device_commandHandler::DoPost() {
|
||||
@@ -404,6 +449,210 @@ namespace OpenWifi {
|
||||
BadRequest(RESTAPI::Errors::NoRecordsDeleted);
|
||||
}
|
||||
|
||||
void RESTAPI_device_commandHandler::GetPackages(const std::string &CMD_UUID, uint64_t CMD_RPC,
|
||||
const std::string pkg_name,
|
||||
[[maybe_unused]] std::chrono::milliseconds timeout,
|
||||
[[maybe_unused]] const GWObjects::DeviceRestrictions &Restrictions) {
|
||||
poco_debug(Logger_, fmt::format("GET-PACKAGES: TID={}, user={} serial={}. thr_id={}",
|
||||
TransactionId_, Requester(), SerialNumber_,
|
||||
Poco::Thread::current()->id()));
|
||||
|
||||
if (IsDeviceSimulated(SerialNumber_)) {
|
||||
return BadRequest(RESTAPI::Errors::SimulatedDeviceNotSupported);
|
||||
}
|
||||
|
||||
Poco::JSON::Object Params;
|
||||
Params.set(uCentralProtocol::OPERATION, "list");
|
||||
Params.set(uCentralProtocol::SERIAL, SerialNumber_);
|
||||
Params.set(uCentralProtocol::PACKAGE, pkg_name);
|
||||
|
||||
std::stringstream ParamStream;
|
||||
Params.stringify(ParamStream);
|
||||
|
||||
GWObjects::CommandDetails Cmd;
|
||||
Cmd.SerialNumber = SerialNumber_;
|
||||
Cmd.UUID = CMD_UUID;
|
||||
Cmd.SubmittedBy = Requester();
|
||||
Cmd.Command = uCentralProtocol::PACKAGE;
|
||||
Cmd.RunAt = 0;
|
||||
Cmd.Details = ParamStream.str();
|
||||
|
||||
RESTAPI_RPC::WaitForCommand(CMD_RPC, APCommands::Commands::package, false, Cmd, Params,
|
||||
*Request, *Response, timeout, nullptr, nullptr, Logger_);
|
||||
|
||||
Poco::JSON::Object O, P;
|
||||
Cmd.to_json(O);
|
||||
|
||||
Poco::Dynamic::Var resultsVar = O.get("results");
|
||||
Poco::JSON::Object::Ptr resultsObj = resultsVar.extract<Poco::JSON::Object::Ptr>();
|
||||
|
||||
return ReturnObject(*resultsObj);
|
||||
}
|
||||
|
||||
void RESTAPI_device_commandHandler::PackageInstall(
|
||||
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("INSTALLPACKAGE", CMD_UUID, CMD_RPC, RESTAPI::Errors::ACCESS_DENIED);
|
||||
return UnAuthorized(RESTAPI::Errors::ACCESS_DENIED);
|
||||
}
|
||||
|
||||
poco_debug(Logger_, fmt::format("INSTALL-PACKAGES({},{}): TID={} user={} serial={}", CMD_UUID,
|
||||
CMD_RPC, TransactionId_, Requester(), SerialNumber_));
|
||||
|
||||
if (IsDeviceSimulated(SerialNumber_)) {
|
||||
CallCanceled("INSTALL-PACKAGES", CMD_UUID, CMD_RPC, RESTAPI::Errors::SimulatedDeviceNotSupported);
|
||||
return BadRequest(RESTAPI::Errors::SimulatedDeviceNotSupported);
|
||||
}
|
||||
|
||||
const auto &Obj = ParsedBody_;
|
||||
if (!Obj->has(RESTAPI::Protocol::SERIALNUMBER)) {
|
||||
return BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
|
||||
}
|
||||
|
||||
auto SNum = Obj->get(RESTAPI::Protocol::SERIALNUMBER).toString();
|
||||
if (SerialNumber_ != SNum) {
|
||||
CallCanceled("INSTALL-PACKAGES", CMD_UUID, CMD_RPC, RESTAPI::Errors::SerialNumberMismatch);
|
||||
return BadRequest(RESTAPI::Errors::SerialNumberMismatch);
|
||||
}
|
||||
|
||||
std::ostringstream os;
|
||||
ParsedBody_->stringify(os);
|
||||
|
||||
poco_information(Logger_, fmt::format("INSTALL_OBJECT: {} for device {}", os.str(), SerialNumber_));
|
||||
|
||||
GWObjects::PackageInstall PI;
|
||||
if (!PI.from_json(ParsedBody_)) {
|
||||
return BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
|
||||
}
|
||||
|
||||
Poco::JSON::Array::Ptr ArrayObj = Poco::SharedPtr<Poco::JSON::Array>(new Poco::JSON::Array);
|
||||
for (const auto &i : PI.pkgs) {
|
||||
Poco::JSON::Object::Ptr Obj =
|
||||
Poco::SharedPtr<Poco::JSON::Object>(new Poco::JSON::Object);
|
||||
i.to_json(*Obj);
|
||||
ArrayObj->add(Obj);
|
||||
}
|
||||
|
||||
Poco::JSON::Object Params;
|
||||
Params.set(uCentralProtocol::OPERATION, "install");
|
||||
Params.set(uCentralProtocol::SERIAL, SerialNumber_);
|
||||
Params.set(uCentralProtocol::PACKAGES, ArrayObj);
|
||||
|
||||
std::ostringstream os2;
|
||||
Params.stringify(os2);
|
||||
|
||||
poco_information(Logger_, fmt::format("INSTALL_OBJECT2: {} for device {}", os2.str(), SerialNumber_));
|
||||
|
||||
|
||||
std::stringstream ParamStream;
|
||||
Params.stringify(ParamStream);
|
||||
|
||||
GWObjects::CommandDetails Cmd;
|
||||
Cmd.SerialNumber = SerialNumber_;
|
||||
Cmd.UUID = CMD_UUID;
|
||||
Cmd.SubmittedBy = Requester();
|
||||
Cmd.Command = uCentralProtocol::PACKAGE;
|
||||
Cmd.RunAt = 0;
|
||||
Cmd.Details = ParamStream.str();
|
||||
|
||||
RESTAPI_RPC::WaitForCommand(CMD_RPC, APCommands::Commands::package, false, Cmd, Params,
|
||||
*Request, *Response, timeout, nullptr, nullptr, Logger_);
|
||||
|
||||
Poco::JSON::Object O, P;
|
||||
Cmd.to_json(O);
|
||||
|
||||
Poco::Dynamic::Var resultsVar = O.get("results");
|
||||
Poco::JSON::Object::Ptr resultsObj = resultsVar.extract<Poco::JSON::Object::Ptr>();
|
||||
|
||||
return ReturnObject(*resultsObj);
|
||||
}
|
||||
|
||||
void RESTAPI_device_commandHandler::DeletePackages(
|
||||
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("DELETE-PACKAGES", CMD_UUID, CMD_RPC, RESTAPI::Errors::ACCESS_DENIED);
|
||||
return UnAuthorized(RESTAPI::Errors::ACCESS_DENIED);
|
||||
}
|
||||
|
||||
poco_debug(Logger_, fmt::format("DELETE-PACKAGES({},{}): TID={} user={} serial={}", CMD_UUID,
|
||||
CMD_RPC, TransactionId_, Requester(), SerialNumber_));
|
||||
|
||||
if (IsDeviceSimulated(SerialNumber_)) {
|
||||
CallCanceled("DELETE-PACKAGES", CMD_UUID, CMD_RPC, RESTAPI::Errors::SimulatedDeviceNotSupported);
|
||||
return BadRequest(RESTAPI::Errors::SimulatedDeviceNotSupported);
|
||||
}
|
||||
|
||||
const auto &Obj = ParsedBody_;
|
||||
if (!Obj->has(RESTAPI::Protocol::SERIALNUMBER)) {
|
||||
return BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
|
||||
}
|
||||
|
||||
auto SNum = Obj->get(RESTAPI::Protocol::SERIALNUMBER).toString();
|
||||
if (SerialNumber_ != SNum) {
|
||||
CallCanceled("DELETE-PACKAGES", CMD_UUID, CMD_RPC, RESTAPI::Errors::SerialNumberMismatch);
|
||||
return BadRequest(RESTAPI::Errors::SerialNumberMismatch);
|
||||
}
|
||||
|
||||
std::ostringstream os;
|
||||
ParsedBody_->stringify(os);
|
||||
|
||||
poco_information(Logger_, fmt::format("DELETE_OBJECT: {} for device {}", os.str(), SerialNumber_));
|
||||
|
||||
GWObjects::PackageRemove PR;
|
||||
if (!PR.from_json(ParsedBody_)) {
|
||||
return BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
|
||||
}
|
||||
|
||||
Poco::JSON::Array::Ptr ArrayObj = Poco::SharedPtr<Poco::JSON::Array>(new Poco::JSON::Array);
|
||||
for (const auto &i : PR.pkgs) {
|
||||
Poco::JSON::Object::Ptr Obj =
|
||||
Poco::SharedPtr<Poco::JSON::Object>(new Poco::JSON::Object);
|
||||
i.to_json(*Obj);
|
||||
ArrayObj->add(Obj);
|
||||
}
|
||||
|
||||
Poco::JSON::Object Params;
|
||||
Params.set(uCentralProtocol::OPERATION, "delete");
|
||||
Params.set(uCentralProtocol::SERIAL, SerialNumber_);
|
||||
Params.set(uCentralProtocol::PACKAGES, ArrayObj);
|
||||
|
||||
std::ostringstream os2;
|
||||
Params.stringify(os2);
|
||||
|
||||
poco_information(Logger_, fmt::format("DELETE_OBJECT2: {} for device {}", os2.str(), SerialNumber_));
|
||||
|
||||
|
||||
std::stringstream ParamStream;
|
||||
Params.stringify(ParamStream);
|
||||
|
||||
GWObjects::CommandDetails Cmd;
|
||||
Cmd.SerialNumber = SerialNumber_;
|
||||
Cmd.UUID = CMD_UUID;
|
||||
Cmd.SubmittedBy = Requester();
|
||||
Cmd.Command = uCentralProtocol::PACKAGE;
|
||||
Cmd.RunAt = 0;
|
||||
Cmd.Details = ParamStream.str();
|
||||
|
||||
RESTAPI_RPC::WaitForCommand(CMD_RPC, APCommands::Commands::package, false, Cmd, Params,
|
||||
*Request, *Response, timeout, nullptr, nullptr, Logger_);
|
||||
|
||||
Poco::JSON::Object O, P;
|
||||
Cmd.to_json(O);
|
||||
|
||||
Poco::Dynamic::Var resultsVar = O.get("results");
|
||||
Poco::JSON::Object::Ptr resultsObj = resultsVar.extract<Poco::JSON::Object::Ptr>();
|
||||
|
||||
return ReturnObject(*resultsObj);
|
||||
}
|
||||
|
||||
void RESTAPI_device_commandHandler::Ping(
|
||||
const std::string &CMD_UUID, uint64_t CMD_RPC, std::chrono::milliseconds timeout,
|
||||
[[maybe_unused]] const GWObjects::DeviceRestrictions &Restrictions) {
|
||||
@@ -653,13 +902,18 @@ namespace OpenWifi {
|
||||
return BadRequest(RESTAPI::Errors::SerialNumberMismatch);
|
||||
}
|
||||
|
||||
GWObjects::Device DeviceInfo;
|
||||
if (!StorageService()->GetDevice(SerialNumber_, DeviceInfo)) {
|
||||
return NotFound();
|
||||
}
|
||||
auto Configuration =
|
||||
GetS(RESTAPI::Protocol::CONFIGURATION, Obj, uCentralProtocol::EMPTY_JSON_DOC);
|
||||
std::vector<std::string> Error;
|
||||
if (!ValidateUCentralConfiguration(Configuration, Error,
|
||||
std::string Error;
|
||||
if (!ValidateUCentralConfiguration(ConfigurationValidator::GetType(DeviceInfo.DeviceType),
|
||||
Configuration, Error,
|
||||
GetBoolParameter("strict", false))) {
|
||||
CallCanceled("CONFIGURE", CMD_UUID, CMD_RPC, RESTAPI::Errors::ConfigBlockInvalid);
|
||||
return BadRequest(RESTAPI::Errors::ConfigBlockInvalid);
|
||||
return BadRequest(RESTAPI::Errors::ConfigBlockInvalid, Error);
|
||||
}
|
||||
|
||||
auto When = GetWhen(Obj);
|
||||
@@ -685,9 +939,31 @@ namespace OpenWifi {
|
||||
Params.stringify(ParamStream);
|
||||
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);
|
||||
RESTAPI_RPC::WaitForCommand(CMD_RPC, APCommands::Commands::configure, true,
|
||||
Cmd, Params, *Request, *Response, timeout,
|
||||
Cmd, ConfigParams, *Request, *Response, timeout,
|
||||
nullptr, this, Logger_);
|
||||
|
||||
if(!Cmd.Executed) {
|
||||
@@ -1169,7 +1445,7 @@ namespace OpenWifi {
|
||||
|
||||
if (RTTYS_server()->UseInternal()) {
|
||||
std::uint64_t SN = Utils::SerialNumberToInt(SerialNumber_);
|
||||
bool mTLS = AP_WS_Server()->DeviceRequiresSecureRtty(SN);
|
||||
bool mTLS = AP_WS_Server()->DeviceRequiresSecureRTTY(SN);
|
||||
auto Hash = Utils::ComputeHash(UserInfo_.webtoken.refresh_token_, Utils::Now());
|
||||
Rtty.Token = Hash.substr(0, RTTY_DEVICE_TOKEN_LENGTH);
|
||||
if (!RTTYS_server()->CreateEndPoint(Rtty.ConnectionId, Rtty.Token, Requester(),
|
||||
@@ -1401,9 +1677,9 @@ namespace OpenWifi {
|
||||
Cmd.WaitingForFile = 0;
|
||||
Cmd.Status= "completed";
|
||||
if(CommandManager()->FireAndForget(SerialNumber_, uCentralProtocol::RRM, Params)) {
|
||||
Cmd.Status= "completed";
|
||||
StorageService()->AddCommand(SerialNumber_, Cmd,
|
||||
Storage::CommandExecutionType::COMMAND_COMPLETED);
|
||||
Cmd.Status= "completed";
|
||||
return OK();
|
||||
}
|
||||
Cmd.Status= "failed"; // should never happen
|
||||
@@ -1501,4 +1777,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
|
||||
|
||||
@@ -33,6 +33,13 @@ namespace OpenWifi {
|
||||
void GetStatus();
|
||||
void GetChecks();
|
||||
void DeleteChecks();
|
||||
void GetPackages(const std::string &UUID, uint64_t RPC,
|
||||
std::string pkg_name,
|
||||
std::chrono::milliseconds timeout,
|
||||
const GWObjects::DeviceRestrictions &R);
|
||||
void DeletePackages(const std::string &UUID, uint64_t RPC,
|
||||
std::chrono::milliseconds timeout,
|
||||
const GWObjects::DeviceRestrictions &R);
|
||||
|
||||
bool IsDeviceSimulated(std::string &Serial);
|
||||
|
||||
@@ -68,6 +75,16 @@ namespace OpenWifi {
|
||||
const GWObjects::DeviceRestrictions &R);
|
||||
void Transfer(const std::string &UUID, uint64_t RPC, std::chrono::milliseconds timeout,
|
||||
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);
|
||||
void PackageInstall(const std::string &UUID, uint64_t RPC, std::chrono::milliseconds timeout,
|
||||
const GWObjects::DeviceRestrictions &R);
|
||||
|
||||
static auto PathName() {
|
||||
return std::list<std::string>{"/api/v1/device/{serialNumber}/{command}"};
|
||||
|
||||
@@ -17,6 +17,8 @@
|
||||
|
||||
#include "RESTAPI_device_helper.h"
|
||||
|
||||
#include "AP_WS_Server.h"
|
||||
|
||||
namespace OpenWifi {
|
||||
void RESTAPI_device_handler::DoGet() {
|
||||
std::string SerialNumber = GetBinding(RESTAPI::Protocol::SERIALNUMBER, "");
|
||||
@@ -80,6 +82,9 @@ namespace OpenWifi {
|
||||
return OK();
|
||||
|
||||
} else if (StorageService()->DeleteDevice(SerialNumber)) {
|
||||
if(AP_WS_Server()->Connected(Utils::SerialNumberToInt(SerialNumber))) {
|
||||
AP_WS_Server()->Disconnect(Utils::SerialNumberToInt(SerialNumber));
|
||||
}
|
||||
return OK();
|
||||
}
|
||||
|
||||
@@ -101,9 +106,10 @@ namespace OpenWifi {
|
||||
}
|
||||
auto Config = Obj->get("configuration").toString();
|
||||
Poco::JSON::Object Answer;
|
||||
std::vector<std::string> Error;
|
||||
std::string Error;
|
||||
auto DeviceType = Poco::toLower(GetParameter("deviceType", Platforms::AP));
|
||||
auto Res =
|
||||
ValidateUCentralConfiguration(Config, Error, GetBoolParameter("strict", false));
|
||||
ValidateUCentralConfiguration(ConfigurationValidator::GetType(DeviceType),Config, Error, GetBoolParameter("strict", false));
|
||||
Answer.set("valid", Res);
|
||||
if (!Error.empty())
|
||||
Answer.set("error", Error);
|
||||
@@ -123,12 +129,13 @@ namespace OpenWifi {
|
||||
return BadRequest(RESTAPI::Errors::SerialNumberMismatch);
|
||||
}
|
||||
|
||||
std::vector<std::string> Error;
|
||||
std::string Error;
|
||||
if (Device.Configuration.empty() ||
|
||||
(!Device.Configuration.empty() &&
|
||||
!ValidateUCentralConfiguration(Device.Configuration, Error,
|
||||
!ValidateUCentralConfiguration(ConfigurationValidator::GetType(Device.DeviceType),
|
||||
Device.Configuration, Error,
|
||||
GetBoolParameter("strict", false)))) {
|
||||
return BadRequest(RESTAPI::Errors::ConfigBlockInvalid);
|
||||
return BadRequest(RESTAPI::Errors::ConfigBlockInvalid, Error);
|
||||
}
|
||||
|
||||
for (auto &i : Device.Notes) {
|
||||
@@ -169,10 +176,11 @@ namespace OpenWifi {
|
||||
}
|
||||
|
||||
if (!NewDevice.Configuration.empty()) {
|
||||
std::vector<std::string> Error;
|
||||
if (!ValidateUCentralConfiguration(NewDevice.Configuration, Error,
|
||||
std::string Error;
|
||||
if (!ValidateUCentralConfiguration(ConfigurationValidator::GetType(Existing.DeviceType),
|
||||
NewDevice.Configuration, Error,
|
||||
GetBoolParameter("strict", false))) {
|
||||
return BadRequest(RESTAPI::Errors::ConfigBlockInvalid);
|
||||
return BadRequest(RESTAPI::Errors::ConfigBlockInvalid, Error);
|
||||
}
|
||||
Config::Config NewConfig(NewDevice.Configuration);
|
||||
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 deviceWithStatus = GetBoolParameter(RESTAPI::Protocol::DEVICEWITHSTATUS, 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;
|
||||
if (!QB_.Select.empty()) {
|
||||
Poco::JSON::Array Objects;
|
||||
for (auto &i : SelectedRecords()) {
|
||||
auto SerialNumber = i;
|
||||
auto &SerialNumber = i;
|
||||
if (!Utils::ValidSerialNumber(i))
|
||||
continue;
|
||||
GWObjects::Device D;
|
||||
@@ -116,14 +125,14 @@ namespace OpenWifi {
|
||||
else
|
||||
RetObj.set(RESTAPI::Protocol::DEVICES, Objects);
|
||||
|
||||
} else if (QB_.CountOnly == true) {
|
||||
} else if (QB_.CountOnly) {
|
||||
uint64_t Count = 0;
|
||||
if (StorageService()->GetDeviceCount(Count)) {
|
||||
if (StorageService()->GetDeviceCount(Count, platform)) {
|
||||
return ReturnCountOnly(Count);
|
||||
}
|
||||
} else if (serialOnly) {
|
||||
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;
|
||||
for (const auto &i : SerialNumbers) {
|
||||
Objects.add(i);
|
||||
@@ -141,7 +150,7 @@ namespace OpenWifi {
|
||||
RetObj.set("serialNumbers", Objects);
|
||||
} else {
|
||||
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;
|
||||
for (const auto &i : Devices) {
|
||||
Poco::JSON::Object Obj;
|
||||
@@ -175,10 +184,12 @@ namespace OpenWifi {
|
||||
}
|
||||
|
||||
if(GetBoolParameter("simulatedDevices",false)) {
|
||||
if(StorageService()->DeleteSimulatedDevice("")) {
|
||||
return OK();
|
||||
}
|
||||
return NotFound();
|
||||
auto F = []() ->void {
|
||||
StorageService()->DeleteSimulatedDevice("");
|
||||
};
|
||||
std::thread T(F);
|
||||
T.detach();
|
||||
return OK();
|
||||
}
|
||||
|
||||
if(!QB_.Select.empty() && !Utils::ValidSerialNumbers(QB_.Select)) {
|
||||
|
||||
@@ -22,9 +22,15 @@ namespace OpenWifi {
|
||||
|
||||
std::string FileType;
|
||||
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();
|
||||
}
|
||||
else if (WaitingForFile) {
|
||||
// waiting for file to be uploaded, return Accepted
|
||||
return Accepted();
|
||||
}
|
||||
|
||||
if (FileType == "pcap") {
|
||||
SendFileContent(FileContent, "application/vnd.tcpdump.pcap", UUID + ".pcap");
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "framework/RESTAPI_Handler.h"
|
||||
#include <framework/RESTAPI_Handler.h>
|
||||
|
||||
namespace OpenWifi {
|
||||
class RESTAPI_file : public RESTAPIHandler {
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include "RESTAPI_ProvObjects.h"
|
||||
#include "framework/utils.h"
|
||||
#include <vector>
|
||||
#include "framework/ow_constants.h"
|
||||
|
||||
namespace OpenWifi {
|
||||
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#include "AP_WS_Server.h"
|
||||
#include "CapabilitiesCache.h"
|
||||
#include "RADIUSSessionTracker.h"
|
||||
#include "StorageService.h"
|
||||
#endif
|
||||
|
||||
#include "RESTAPI_GWobjects.h"
|
||||
@@ -29,8 +30,9 @@ namespace OpenWifi::GWObjects {
|
||||
void Device::to_json(Poco::JSON::Object &Obj) const {
|
||||
field_to_json(Obj, "serialNumber", SerialNumber);
|
||||
#ifdef TIP_GATEWAY_SERVICE
|
||||
field_to_json(Obj, "deviceType", CapabilitiesCache::instance()->GetPlatform(Compatible));
|
||||
field_to_json(Obj, "hasRADIUSSessions", RADIUSSessionTracker()->HasSessions(SerialNumber));
|
||||
field_to_json(Obj, "deviceType", StorageService()->GetPlatform(SerialNumber));
|
||||
field_to_json(Obj, "blackListed",
|
||||
StorageService()->IsBlackListed(Utils::MACToInt(SerialNumber)));
|
||||
#endif
|
||||
field_to_json(Obj, "macAddress", MACAddress);
|
||||
field_to_json(Obj, "manufacturer", Manufacturer);
|
||||
@@ -68,9 +70,14 @@ namespace OpenWifi::GWObjects {
|
||||
|
||||
#ifdef TIP_GATEWAY_SERVICE
|
||||
ConnectionState ConState;
|
||||
|
||||
#ifdef USE_MEDUSA_CLIENT
|
||||
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 {
|
||||
field_to_json(Obj, "ipAddress", "");
|
||||
field_to_json(Obj, "txBytes", (uint64_t)0);
|
||||
@@ -166,13 +173,15 @@ namespace OpenWifi::GWObjects {
|
||||
field_to_json(Obj, "recorded", Recorded);
|
||||
}
|
||||
|
||||
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);
|
||||
bool HealthCheck::from_json(const Poco::JSON::Object::Ptr &Obj) {
|
||||
try {
|
||||
field_from_json(Obj, "UUID", UUID);
|
||||
field_from_json(Obj, "sanity", Sanity);
|
||||
field_from_json(Obj, "recorded", Recorded);
|
||||
return true;
|
||||
} catch (...) {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void DefaultFirmware::to_json(Poco::JSON::Object &Obj) const {
|
||||
@@ -222,12 +231,25 @@ namespace OpenWifi::GWObjects {
|
||||
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) {
|
||||
try {
|
||||
field_from_json(Obj, "name", Name);
|
||||
field_from_json(Obj, "configuration", Configuration);
|
||||
field_from_json(Obj, "modelIds", Models);
|
||||
field_from_json(Obj, "description", Description);
|
||||
field_from_json(Obj, "configuration", configuration);
|
||||
field_from_json(Obj, "name", name);
|
||||
field_from_json(Obj, "modelIds", models);
|
||||
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;
|
||||
} catch (const Poco::Exception &E) {
|
||||
}
|
||||
@@ -253,7 +275,8 @@ namespace OpenWifi::GWObjects {
|
||||
return false;
|
||||
}
|
||||
|
||||
void ConnectionState::to_json([[maybe_unused]] const std::string &SerialNumber, Poco::JSON::Object &Obj) {
|
||||
void ConnectionState::to_json([[maybe_unused]] const std::string &SerialNumber,
|
||||
Poco::JSON::Object &Obj) {
|
||||
field_to_json(Obj, "ipAddress", Address);
|
||||
field_to_json(Obj, "txBytes", TX);
|
||||
field_to_json(Obj, "rxBytes", RX);
|
||||
@@ -275,16 +298,15 @@ namespace OpenWifi::GWObjects {
|
||||
field_to_json(Obj, "connectionCompletionTime", connectionCompletionTime);
|
||||
field_to_json(Obj, "totalConnectionTime", Utils::Now() - started);
|
||||
field_to_json(Obj, "certificateExpiryDate", certificateExpiryDate);
|
||||
field_to_json(Obj, "certificateIssuerName", certificateIssuerName);
|
||||
field_to_json(Obj, "connectReason", connectReason);
|
||||
field_to_json(Obj, "uptime", uptime);
|
||||
field_to_json(Obj, "compatible", Compatible);
|
||||
|
||||
#ifdef TIP_GATEWAY_SERVICE
|
||||
hasRADIUSSessions = RADIUSSessionTracker()->HasSessions(SerialNumber);
|
||||
AP_WS_Server()->ExtendedAttributes(SerialNumber, hasGPS, sanity,
|
||||
memoryUsed,
|
||||
load,
|
||||
temperature);
|
||||
#endif
|
||||
field_to_json(Obj, "hasRADIUSSessions", hasRADIUSSessions );
|
||||
field_to_json(Obj, "hasRADIUSSessions", hasRADIUSSessions);
|
||||
field_to_json(Obj, "hasGPS", hasGPS);
|
||||
field_to_json(Obj, "sanity", sanity);
|
||||
field_to_json(Obj, "memoryUsed", memoryUsed);
|
||||
@@ -314,6 +336,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 {
|
||||
field_to_json(Obj, "averageConnectionTime", averageConnectionTime);
|
||||
field_to_json(Obj, "connectedDevices", connectedDevices);
|
||||
@@ -711,7 +773,7 @@ namespace OpenWifi::GWObjects {
|
||||
|
||||
bool DeviceCertificateUpdateRequest::from_json(const Poco::JSON::Object::Ptr &Obj) {
|
||||
try {
|
||||
field_from_json(Obj, "serialNumber", serialNumber);
|
||||
field_from_json(Obj, "serial", serialNumber);
|
||||
field_from_json(Obj, "encodedCertificate", encodedCertificate);
|
||||
return true;
|
||||
} catch (const Poco::Exception &E) {
|
||||
@@ -719,4 +781,144 @@ namespace OpenWifi::GWObjects {
|
||||
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;
|
||||
}
|
||||
|
||||
bool PackageInfo::from_json(const Poco::JSON::Object::Ptr &Obj) {
|
||||
try {
|
||||
field_from_json(Obj, "name", name);
|
||||
field_from_json(Obj, "version", version);
|
||||
return true;
|
||||
} catch (const Poco::Exception &E) {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void PackageInfo::to_json(Poco::JSON::Object &Obj) const {
|
||||
field_to_json(Obj, "name", name);
|
||||
field_to_json(Obj, "version", version);
|
||||
}
|
||||
|
||||
void PackageList::to_json(Poco::JSON::Object &Obj) const {
|
||||
Obj.set("serialNumber", serialNumber);
|
||||
|
||||
Poco::JSON::Array packageJsonArray;
|
||||
for (const auto &pkg : packageArray) {
|
||||
Poco::JSON::Object pkgObj;
|
||||
pkg.to_json(pkgObj);
|
||||
packageJsonArray.add(pkgObj);
|
||||
}
|
||||
Obj.set("packageArray", packageJsonArray);
|
||||
|
||||
Obj.set("FirstUpdate", Poco::UInt64(FirstUpdate));
|
||||
Obj.set("LastUpdate", Poco::UInt64(LastUpdate));
|
||||
}
|
||||
|
||||
bool ToBeInstalled::from_json(const Poco::JSON::Object::Ptr &Obj) {
|
||||
try {
|
||||
field_from_json(Obj, "name", name);
|
||||
field_from_json(Obj, "url", url);
|
||||
|
||||
Poco::URI uri(url);
|
||||
std::string scheme = uri.getScheme();
|
||||
if (scheme != "http" && scheme != "https") {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
} catch (const Poco::Exception &E) {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void ToBeInstalled::to_json(Poco::JSON::Object &Obj) const {
|
||||
Obj.set("name", name);
|
||||
Obj.set("url", url);
|
||||
}
|
||||
|
||||
bool PackageInstall::from_json(const Poco::JSON::Object::Ptr &Obj) {
|
||||
try {
|
||||
field_from_json(Obj, "serialNumber", serialNumber);
|
||||
field_from_json(Obj, "when", when);
|
||||
field_from_json(Obj, "packages", pkgs);
|
||||
|
||||
return true;
|
||||
} catch (const Poco::Exception &E) {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ToBeRemoved::from_json(const Poco::JSON::Object::Ptr &Obj) {
|
||||
try {
|
||||
field_from_json(Obj, "name", name);
|
||||
|
||||
return true;
|
||||
} catch (const Poco::Exception &E) {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void ToBeRemoved::to_json(Poco::JSON::Object &Obj) const {
|
||||
Obj.set("name", name);
|
||||
}
|
||||
|
||||
bool PackageRemove::from_json(const Poco::JSON::Object::Ptr &Obj) {
|
||||
try {
|
||||
field_from_json(Obj, "serialNumber", serialNumber);
|
||||
field_from_json(Obj, "packages", pkgs);
|
||||
|
||||
return true;
|
||||
} catch (const Poco::Exception &E) {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
} // namespace OpenWifi::GWObjects
|
||||
|
||||
@@ -42,6 +42,7 @@ namespace OpenWifi::GWObjects {
|
||||
uint64_t sessionId = 0;
|
||||
double connectionCompletionTime = 0.0;
|
||||
std::uint64_t certificateExpiryDate = 0;
|
||||
std::string certificateIssuerName;
|
||||
std::uint64_t hasRADIUSSessions = 0;
|
||||
bool hasGPS = false;
|
||||
std::uint64_t sanity=0;
|
||||
@@ -49,8 +50,11 @@ namespace OpenWifi::GWObjects {
|
||||
std::double_t load=0.0;
|
||||
std::double_t temperature=0.0;
|
||||
std::string connectReason;
|
||||
std::uint64_t uptime=0;
|
||||
std::uint64_t totalConnectionTime=0;
|
||||
|
||||
void to_json(const std::string &SerialNumber, Poco::JSON::Object &Obj) ;
|
||||
bool from_json(const Poco::JSON::Object::Ptr &Obj);
|
||||
};
|
||||
|
||||
struct DeviceRestrictionsKeyInfo {
|
||||
@@ -112,6 +116,7 @@ namespace OpenWifi::GWObjects {
|
||||
std::uint64_t lastRecordedContact=0;
|
||||
std::uint64_t certificateExpiryDate = 0;
|
||||
std::string connectReason;
|
||||
bool blackListed=false;
|
||||
|
||||
void to_json(Poco::JSON::Object &Obj) const;
|
||||
void to_json_with_status(Poco::JSON::Object &Obj) const;
|
||||
@@ -137,13 +142,15 @@ namespace OpenWifi::GWObjects {
|
||||
};
|
||||
|
||||
struct HealthCheck {
|
||||
std::string SerialNumber;
|
||||
uint64_t UUID = 0;
|
||||
std::string Data;
|
||||
uint64_t Recorded = 0;
|
||||
uint64_t Sanity = 0;
|
||||
void to_json(Poco::JSON::Object &Obj) const;
|
||||
};
|
||||
std::string SerialNumber;
|
||||
uint64_t UUID = 0;
|
||||
std::string Data;
|
||||
uint64_t Recorded = 0;
|
||||
uint64_t Sanity = 0;
|
||||
|
||||
void to_json(Poco::JSON::Object &Obj) const;
|
||||
bool from_json(const Poco::JSON::Object::Ptr &Obj);
|
||||
};
|
||||
|
||||
struct Capabilities {
|
||||
std::string Capabilities;
|
||||
@@ -174,12 +181,13 @@ namespace OpenWifi::GWObjects {
|
||||
};
|
||||
|
||||
struct DefaultConfiguration {
|
||||
std::string Name;
|
||||
std::string Configuration;
|
||||
Types::StringVec Models;
|
||||
std::string Description;
|
||||
uint64_t Created;
|
||||
uint64_t LastModified;
|
||||
std::string name;
|
||||
std::string configuration;
|
||||
Types::StringVec models;
|
||||
std::string description;
|
||||
uint64_t created;
|
||||
uint64_t lastModified;
|
||||
std::string platform;
|
||||
void to_json(Poco::JSON::Object &Obj) const;
|
||||
bool from_json(const Poco::JSON::Object::Ptr &Obj);
|
||||
};
|
||||
@@ -513,4 +521,82 @@ namespace OpenWifi::GWObjects {
|
||||
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);
|
||||
};
|
||||
struct PackageInfo {
|
||||
std::string name;
|
||||
std::string version;
|
||||
|
||||
bool from_json(const Poco::JSON::Object::Ptr &Obj);
|
||||
void to_json(Poco::JSON::Object &Obj) const;
|
||||
};
|
||||
struct PackageList {
|
||||
std::string serialNumber;
|
||||
std::vector<PackageInfo> packageArray;
|
||||
uint64_t FirstUpdate = 0;
|
||||
uint64_t LastUpdate = 0;
|
||||
std::string packageStringArray;
|
||||
|
||||
bool from_json(const Poco::JSON::Array::Ptr &Obj);
|
||||
void to_json(Poco::JSON::Object &Obj) const;
|
||||
};
|
||||
struct ToBeInstalled {
|
||||
std::string name;
|
||||
std::string url;
|
||||
|
||||
bool from_json(const Poco::JSON::Object::Ptr &Obj);
|
||||
void to_json(Poco::JSON::Object &Obj) const;
|
||||
};
|
||||
struct PackageInstall {
|
||||
std::string serialNumber;
|
||||
std::uint64_t when;
|
||||
std::vector<ToBeInstalled> pkgs;
|
||||
|
||||
bool from_json(const Poco::JSON::Object::Ptr &Obj);
|
||||
void to_json(Poco::JSON::Object &Obj) const;
|
||||
};
|
||||
struct ToBeRemoved {
|
||||
std::string name;
|
||||
|
||||
bool from_json(const Poco::JSON::Object::Ptr &Obj);
|
||||
void to_json(Poco::JSON::Object &Obj) const;
|
||||
};
|
||||
struct PackageRemove {
|
||||
std::string serialNumber;
|
||||
std::uint64_t when;
|
||||
std::vector<ToBeRemoved> pkgs;
|
||||
|
||||
bool from_json(const Poco::JSON::Object::Ptr &Obj);
|
||||
};
|
||||
} // namespace OpenWifi::GWObjects
|
||||
|
||||
@@ -587,6 +587,9 @@ namespace OpenWifi::ProvObjects {
|
||||
field_to_json(Obj, "locale", locale);
|
||||
field_to_json(Obj, "realMacAddress", realMacAddress);
|
||||
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) {
|
||||
@@ -609,6 +612,9 @@ namespace OpenWifi::ProvObjects {
|
||||
field_from_json(Obj, "locale", locale);
|
||||
field_from_json(Obj, "realMacAddress", realMacAddress);
|
||||
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;
|
||||
} catch (...) {
|
||||
}
|
||||
|
||||
@@ -490,9 +490,11 @@ namespace OpenWifi::ProvObjects {
|
||||
std::string locale;
|
||||
std::string realMacAddress;
|
||||
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;
|
||||
|
||||
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,
|
||||
uint64_t &Radios_5G, uint64_t &Radios_6G) {
|
||||
uint64_t &Radios_5G, uint64_t &Radios_6G, uint64_t &UpTime ) {
|
||||
Radios_2G = 0;
|
||||
Radios_5G = 0;
|
||||
Radios_6G = 0;
|
||||
@@ -90,9 +90,15 @@ namespace OpenWifi::StateUtils {
|
||||
}
|
||||
}
|
||||
}
|
||||
// std::cout << Radios_2G << " " << Radios_5G << " " << Radios_6G << std::endl;
|
||||
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;
|
||||
}
|
||||
} // namespace OpenWifi::StateUtils
|
||||
@@ -8,5 +8,5 @@
|
||||
|
||||
namespace OpenWifi::StateUtils {
|
||||
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_->Initialize();
|
||||
|
||||
FixDeviceTypeBug();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -16,6 +16,22 @@
|
||||
|
||||
namespace OpenWifi {
|
||||
|
||||
class LockedDbSession {
|
||||
public:
|
||||
explicit LockedDbSession();
|
||||
~LockedDbSession() = default;
|
||||
inline std::mutex &Mutex() { return *Mutex_; };
|
||||
inline Poco::Data::Session &Session() {
|
||||
if(!Session_->isConnected()) {
|
||||
Session_->reconnect();
|
||||
}
|
||||
return *Session_;
|
||||
};
|
||||
private:
|
||||
std::shared_ptr<Poco::Data::Session> Session_;
|
||||
std::shared_ptr<std::mutex> Mutex_;
|
||||
};
|
||||
|
||||
class Storage : public StorageClass {
|
||||
|
||||
public:
|
||||
@@ -90,7 +106,8 @@ namespace OpenWifi {
|
||||
|
||||
// typedef std::map<std::string,std::string> DeviceCapabilitiesCache;
|
||||
|
||||
bool AddLog(const GWObjects::DeviceLog &Log);
|
||||
bool AddLog(LockedDbSession &Session, const GWObjects::DeviceLog &Log);
|
||||
bool AddStatisticsData(Poco::Data::Session &Session, const GWObjects::Statistics &Stats);
|
||||
bool AddStatisticsData(const GWObjects::Statistics &Stats);
|
||||
bool GetStatisticsData(std::string &SerialNumber, uint64_t FromDate, uint64_t ToDate,
|
||||
uint64_t Offset, uint64_t HowMany,
|
||||
@@ -102,6 +119,7 @@ namespace OpenWifi {
|
||||
std::vector<GWObjects::Statistics> &Stats);
|
||||
|
||||
bool AddHealthCheckData(const GWObjects::HealthCheck &Check);
|
||||
bool AddHealthCheckData(LockedDbSession &Session, const GWObjects::HealthCheck &Check);
|
||||
bool GetHealthCheckData(std::string &SerialNumber, uint64_t FromDate, uint64_t ToDate,
|
||||
uint64_t Offset, uint64_t HowMany,
|
||||
std::vector<GWObjects::HealthCheck> &Checks);
|
||||
@@ -115,31 +133,43 @@ namespace OpenWifi {
|
||||
uint64_t &NewUUID);
|
||||
|
||||
bool RollbackDeviceConfigurationChange(std::string & SerialNumber);
|
||||
bool CompleteDeviceConfigurationChange(Poco::Data::Session &Session, std::string & SerialNumber);
|
||||
bool CompleteDeviceConfigurationChange(std::string & SerialNumber);
|
||||
|
||||
bool CreateDevice(LockedDbSession &Session, GWObjects::Device &);
|
||||
bool CreateDevice(GWObjects::Device &);
|
||||
bool CreateDefaultDevice(std::string &SerialNumber, const Config::Capabilities &Caps,
|
||||
bool CreateDefaultDevice(Poco::Data::Session &Session,std::string &SerialNumber,
|
||||
const Config::Capabilities &Caps,
|
||||
std::string &Firmware, const Poco::Net::IPAddress &IPAddress,
|
||||
bool simulated);
|
||||
bool CreateDevice(Poco::Data::Session &Sess, GWObjects::Device &DeviceDetails);
|
||||
|
||||
bool GetDevice(std::string &SerialNumber, GWObjects::Device &);
|
||||
bool GetDevice(LockedDbSession &Session, const std::string &SerialNumber, GWObjects::Device &);
|
||||
bool GetDevice(Poco::Data::Session &Session, const std::string &SerialNumber, GWObjects::Device &DeviceDetails);
|
||||
bool GetDevice(const std::string &SerialNumber, GWObjects::Device &);
|
||||
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,
|
||||
// std::vector<GWObjects::Device> &Devices, const std::string & orderBy="");
|
||||
bool DeleteDevice(std::string &SerialNumber);
|
||||
bool DeleteDevices(std::string &SerialPattern, bool SimulatedOnly);
|
||||
bool DeleteDevices(std::uint64_t OlderContact, bool SimulatedOnly);
|
||||
std::string GetPlatform(const std::string &SerialNumber);
|
||||
|
||||
bool UpdateDevice(GWObjects::Device &);
|
||||
bool UpdateDevice(LockedDbSession &Session, GWObjects::Device &);
|
||||
bool UpdateDevice(Poco::Data::Session &Sess, GWObjects::Device &NewDeviceDetails);
|
||||
bool DeviceExists(std::string &SerialNumber);
|
||||
bool 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,
|
||||
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 SetDevicePassword(std::string &SerialNumber, std::string &Password);
|
||||
bool SetDevicePassword(LockedDbSession &Session, std::string &SerialNumber, std::string &Password);
|
||||
bool UpdateSerialNumberCache();
|
||||
static void GetDeviceDbFieldList(Types::StringVec &Fields);
|
||||
|
||||
@@ -148,9 +178,11 @@ namespace OpenWifi {
|
||||
|
||||
bool UpdateDeviceCapabilities(std::string &SerialNumber,
|
||||
const Config::Capabilities &Capabilities);
|
||||
bool UpdateDeviceCapabilities(Poco::Data::Session &Session, std::string &SerialNumber,
|
||||
const Config::Capabilities &Capabilities);
|
||||
bool GetDeviceCapabilities(std::string &SerialNumber, GWObjects::Capabilities &);
|
||||
bool DeleteDeviceCapabilities(std::string &SerialNumber);
|
||||
bool CreateDeviceCapabilities(std::string &SerialNumber,
|
||||
bool CreateDeviceCapabilities(Poco::Data::Session &Session, std::string &SerialNumber,
|
||||
const Config::Capabilities &Capabilities);
|
||||
bool InitCapabilitiesCache();
|
||||
|
||||
@@ -171,6 +203,7 @@ namespace OpenWifi {
|
||||
bool GetDefaultConfigurations(uint64_t From, uint64_t HowMany,
|
||||
std::vector<GWObjects::DefaultConfiguration> &Devices);
|
||||
bool FindDefaultConfigurationForModel(const std::string &Model,
|
||||
const std::string &Platform,
|
||||
GWObjects::DefaultConfiguration &DefConfig);
|
||||
uint64_t GetDefaultConfigurationsCount();
|
||||
bool DefaultConfigurationAlreadyExists(std::string &Name);
|
||||
@@ -210,7 +243,7 @@ namespace OpenWifi {
|
||||
const std::string &Type);
|
||||
bool CancelWaitFile(std::string &UUID, std::string &ErrorText);
|
||||
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 SetCommandResult(std::string &UUID, std::string &Result);
|
||||
bool GetNewestCommands(std::string &SerialNumber, uint64_t HowMany,
|
||||
@@ -222,15 +255,15 @@ namespace OpenWifi {
|
||||
void RemovedExpiredCommands();
|
||||
void RemoveTimedOutCommands();
|
||||
|
||||
bool RemoveOldCommands(std::string &SerilNumber, std::string &Command);
|
||||
bool RemoveOldCommands(std::string &SerialNumber, std::string &Command);
|
||||
|
||||
bool AddBlackListDevices(std::vector<GWObjects::BlackListedDevice> &Devices);
|
||||
bool AddBlackListDevice(GWObjects::BlackListedDevice &Device);
|
||||
bool GetBlackListDevice(std::string &SerialNumber, GWObjects::BlackListedDevice &Device);
|
||||
bool DeleteBlackListDevice(std::string &SerialNumber);
|
||||
bool IsBlackListed(const std::string &SerialNumber, std::string &reason,
|
||||
bool IsBlackListed(std::uint64_t SerialNumber, std::string &reason,
|
||||
std::string &author, std::uint64_t &created);
|
||||
bool IsBlackListed(const std::string &SerialNumber);
|
||||
bool IsBlackListed(std::uint64_t SerialNumber);
|
||||
bool InitializeBlackListCache();
|
||||
bool GetBlackListDevices(uint64_t Offset, uint64_t HowMany,
|
||||
std::vector<GWObjects::BlackListedDevice> &Devices);
|
||||
@@ -245,7 +278,9 @@ namespace OpenWifi {
|
||||
bool RemoveCommandListRecordsOlderThan(uint64_t Date);
|
||||
bool RemoveUploadedFilesRecordsOlderThan(uint64_t Date);
|
||||
|
||||
bool SetDeviceLastRecordedContact(std::string & SeialNumber, std::uint64_t lastRecordedContact);
|
||||
bool SetDeviceLastRecordedContact(LockedDbSession &Session, std::string & SerialNumber, std::uint64_t lastRecordedContact);
|
||||
bool SetDeviceLastRecordedContact(std::string & SerialNumber, std::uint64_t lastRecordedContact);
|
||||
bool SetDeviceLastRecordedContact(Poco::Data::Session & Session, std::string & SerialNumber, std::uint64_t lastRecordedContact);
|
||||
|
||||
int Create_Tables();
|
||||
int Create_Statistics();
|
||||
@@ -262,13 +297,24 @@ namespace OpenWifi {
|
||||
bool AnalyzeCommands(Types::CountedMap &R);
|
||||
bool AnalyzeDevices(GWObjects::Dashboard &D);
|
||||
|
||||
void FixDeviceTypeBug();
|
||||
|
||||
int Start() override;
|
||||
void Stop() override;
|
||||
|
||||
inline Poco::Data::Session StartSession() {
|
||||
return Pool_->get();
|
||||
}
|
||||
|
||||
private:
|
||||
std::unique_ptr<OpenWifi::ScriptDB> ScriptDB_;
|
||||
};
|
||||
|
||||
inline auto StorageService() { return Storage::instance(); }
|
||||
|
||||
inline LockedDbSession::LockedDbSession() {
|
||||
Session_ = std::make_shared<Poco::Data::Session>(Poco::Data::Session(StorageService()->StartSession()));
|
||||
Mutex_ = std::make_shared<std::mutex>();
|
||||
}
|
||||
|
||||
} // namespace OpenWifi
|
||||
|
||||
@@ -120,14 +120,16 @@ namespace OpenWifi {
|
||||
Poco::Buffer<char> IncomingFrame(0);
|
||||
|
||||
try {
|
||||
int Op, flags;
|
||||
int IncomingSize;
|
||||
int Op, flags, IncomingSize;
|
||||
|
||||
IncomingSize = WS_->receiveFrame(IncomingFrame, flags);
|
||||
Op = flags & Poco::Net::WebSocket::FRAME_OP_BITMASK;
|
||||
|
||||
if (IncomingSize == 0 && flags == 0 && Op == 0) {
|
||||
poco_information(
|
||||
Logger(),
|
||||
if (IncomingSize == -1) {
|
||||
poco_trace(Logger(),
|
||||
fmt::format("TELEMETRY-EMPTY({}): Empty frame, non-blocking try-again.", CId_));
|
||||
} else if (IncomingSize == 0 && flags == 0 && Op == 0) {
|
||||
poco_information(Logger(),
|
||||
fmt::format("TELEMETRY-DISCONNECT({}): device has disconnected.", CId_));
|
||||
MustDisconnect = true;
|
||||
} else {
|
||||
@@ -136,12 +138,14 @@ namespace OpenWifi {
|
||||
fmt::format("TELEMETRY-WS-PING({}): received. PONG sent back.", CId_));
|
||||
WS_->sendFrame("", 0,
|
||||
(int)Poco::Net::WebSocket::FRAME_OP_PONG |
|
||||
(int)Poco::Net::WebSocket::FRAME_FLAG_FIN);
|
||||
(int)Poco::Net::WebSocket::FRAME_FLAG_FIN);
|
||||
} else if (Op == Poco::Net::WebSocket::FRAME_OP_CLOSE) {
|
||||
poco_information(
|
||||
Logger(),
|
||||
poco_information(Logger(),
|
||||
fmt::format("TELEMETRY-DISCONNECT({}): device wants to disconnect.", CId_));
|
||||
MustDisconnect = true;
|
||||
} else if (Op == Poco::Net::WebSocket::FRAME_OP_CONT) {
|
||||
poco_information(Logger(),
|
||||
fmt::format("TELEMETRY-CONT({}): rx {} bytes.", CId_, IncomingSize));
|
||||
}
|
||||
}
|
||||
} catch (...) {
|
||||
@@ -154,4 +158,4 @@ namespace OpenWifi {
|
||||
SendTelemetryShutdown();
|
||||
}
|
||||
|
||||
} // namespace OpenWifi
|
||||
} // namespace OpenWifi
|
||||
|
||||
@@ -111,7 +111,6 @@ namespace OpenWifi {
|
||||
}
|
||||
} break;
|
||||
case TelemetryNotification::NotificationType::unregister: {
|
||||
std::lock_guard G(Mutex_);
|
||||
|
||||
auto client = Clients_.find(Notification->Data_);
|
||||
if (client != Clients_.end()) {
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
|
||||
#include "framework/SubSystemServer.h"
|
||||
|
||||
#include "AP_WS_ReactorPool.h"
|
||||
#include "AP_WS_Reactor_Pool.h"
|
||||
#include "TelemetryClient.h"
|
||||
|
||||
namespace OpenWifi {
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -5,7 +5,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "framework/SubSystemServer.h"
|
||||
|
||||
#include "framework/ow_constants.h"
|
||||
#include <valijson/adapters/poco_json_adapter.hpp>
|
||||
#include <valijson/constraints/constraint.hpp>
|
||||
#include <valijson/constraints/constraint_visitor.hpp>
|
||||
@@ -17,33 +17,42 @@
|
||||
namespace OpenWifi {
|
||||
class ConfigurationValidator : public SubSystemServer {
|
||||
public:
|
||||
|
||||
enum class ConfigurationType { AP = 0 , SWITCH = 1};
|
||||
|
||||
static auto instance() {
|
||||
static auto instance_ = new ConfigurationValidator;
|
||||
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;
|
||||
void Stop() 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:
|
||||
bool Initialized_ = false;
|
||||
bool Working_ = false;
|
||||
void Init();
|
||||
std::unique_ptr<valijson::Schema> RootSchema_;
|
||||
std::unique_ptr<valijson::SchemaParser> SchemaParser_;
|
||||
std::unique_ptr<valijson::adapters::PocoJsonAdapter> PocoJsonAdapter_;
|
||||
Poco::JSON::Object::Ptr SchemaDocPtr_;
|
||||
bool SetSchema(const std::string &SchemaStr);
|
||||
std::array<valijson::Schema,2> RootSchema_;
|
||||
bool SetSchema(ConfigurationType Type, const std::string &SchemaStr);
|
||||
|
||||
ConfigurationValidator()
|
||||
: SubSystemServer("ConfigValidator", "CFG-VALIDATOR", "config.validator") {}
|
||||
};
|
||||
|
||||
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) {
|
||||
return ConfigurationValidator::instance()->Validate(C, Error, strict);
|
||||
return ConfigurationValidator::instance()->Validate(Type, C, Errors, strict);
|
||||
}
|
||||
} // namespace OpenWifi
|
||||
|
||||
@@ -9,8 +9,6 @@
|
||||
|
||||
namespace OpenWifi {
|
||||
|
||||
EventBusManager::EventBusManager(Poco::Logger &L) : Logger_(L) {}
|
||||
|
||||
void EventBusManager::run() {
|
||||
Running_ = true;
|
||||
Utils::SetThreadName("fmwk:EventMgr");
|
||||
@@ -18,9 +16,9 @@ namespace OpenWifi {
|
||||
KafkaManager()->PostMessage(KafkaTopics::SERVICE_EVENTS, MicroServicePrivateEndPoint(), Msg,
|
||||
false);
|
||||
while (Running_) {
|
||||
Poco::Thread::trySleep((unsigned long)MicroServiceDaemonBusTimer());
|
||||
if (!Running_)
|
||||
break;
|
||||
if(!Poco::Thread::trySleep((unsigned long)MicroServiceDaemonBusTimer())) {
|
||||
break;
|
||||
}
|
||||
Msg = (MicroServiceMakeSystemEventMessage(KafkaTopics::ServiceEvents::EVENT_KEEP_ALIVE));
|
||||
KafkaManager()->PostMessage(KafkaTopics::SERVICE_EVENTS, MicroServicePrivateEndPoint(),
|
||||
Msg, false);
|
||||
@@ -31,7 +29,7 @@ namespace OpenWifi {
|
||||
};
|
||||
|
||||
void EventBusManager::Start() {
|
||||
poco_information(Logger(), "Starting...");
|
||||
poco_information(Logger_, "Starting...");
|
||||
if (KafkaManager()->Enabled()) {
|
||||
Thread_.start(*this);
|
||||
}
|
||||
@@ -39,11 +37,11 @@ namespace OpenWifi {
|
||||
|
||||
void EventBusManager::Stop() {
|
||||
if (KafkaManager()->Enabled()) {
|
||||
poco_information(Logger(), "Stopping...");
|
||||
poco_information(Logger_, "Stopping...");
|
||||
Running_ = false;
|
||||
Thread_.wakeUp();
|
||||
Thread_.join();
|
||||
poco_information(Logger(), "Stopped...");
|
||||
poco_information(Logger_, "Stopped...");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -12,7 +12,16 @@ namespace OpenWifi {
|
||||
|
||||
class EventBusManager : public Poco::Runnable {
|
||||
public:
|
||||
explicit EventBusManager(Poco::Logger &L);
|
||||
EventBusManager() :
|
||||
Logger_(Poco::Logger::create(
|
||||
"EventBusManager", Poco::Logger::root().getChannel(), Poco::Logger::root().getLevel())) {
|
||||
}
|
||||
|
||||
static auto instance() {
|
||||
static auto instance_ = new EventBusManager;
|
||||
return instance_;
|
||||
}
|
||||
|
||||
void run() final;
|
||||
void Start();
|
||||
void Stop();
|
||||
@@ -24,4 +33,6 @@ namespace OpenWifi {
|
||||
Poco::Logger &Logger_;
|
||||
};
|
||||
|
||||
inline auto EventBusManager() { return EventBusManager::instance(); }
|
||||
|
||||
} // namespace OpenWifi
|
||||
|
||||
@@ -79,8 +79,10 @@ namespace OpenWifi {
|
||||
Utils::SetThreadName("Kafka:Prod");
|
||||
cppkafka::Configuration Config(
|
||||
{{"client.id", MicroServiceConfigGetString("openwifi.kafka.client.id", "")},
|
||||
{"metadata.broker.list",
|
||||
MicroServiceConfigGetString("openwifi.kafka.brokerlist", "")}});
|
||||
{"metadata.broker.list",MicroServiceConfigGetString("openwifi.kafka.brokerlist", "")} // ,
|
||||
// {"send.buffer.bytes", KafkaManager()->KafkaManagerMaximumPayloadSize() }
|
||||
}
|
||||
);
|
||||
|
||||
AddKafkaSecurity(Config);
|
||||
|
||||
@@ -105,6 +107,19 @@ namespace OpenWifi {
|
||||
NewMessage.partition(0);
|
||||
NewMessage.payload(Msg->Payload());
|
||||
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();
|
||||
}
|
||||
} catch (const cppkafka::HandleException &E) {
|
||||
@@ -117,6 +132,7 @@ namespace OpenWifi {
|
||||
}
|
||||
Note = Queue_.waitDequeueNotification();
|
||||
}
|
||||
Producer.flush();
|
||||
poco_information(Logger_, "Stopped...");
|
||||
}
|
||||
|
||||
@@ -275,6 +291,7 @@ namespace OpenWifi {
|
||||
int KafkaManager::Start() {
|
||||
if (!KafkaEnabled_)
|
||||
return 0;
|
||||
MaxPayloadSize_ = MicroServiceConfigGetInt("openwifi.kafka.max.payload", 250000);
|
||||
ConsumerThr_.Start();
|
||||
ProducerThr_.Start();
|
||||
return 0;
|
||||
@@ -321,4 +338,4 @@ namespace OpenWifi {
|
||||
partitions.front().get_partition()));
|
||||
}
|
||||
|
||||
} // namespace OpenWifi
|
||||
} // namespace OpenWifi
|
||||
|
||||
@@ -94,11 +94,14 @@ namespace OpenWifi {
|
||||
return ConsumerThr_.UnregisterTopicWatcher(Topic,Id);
|
||||
}
|
||||
|
||||
std::uint64_t KafkaManagerMaximumPayloadSize() const { return MaxPayloadSize_; }
|
||||
|
||||
private:
|
||||
bool KafkaEnabled_ = false;
|
||||
std::string SystemInfoWrapper_;
|
||||
KafkaProducer ProducerThr_;
|
||||
KafkaConsumer ConsumerThr_;
|
||||
std::uint64_t MaxPayloadSize_ = 250000;
|
||||
|
||||
void PartitionAssignment(const cppkafka::TopicPartitionList &partitions);
|
||||
void PartitionRevocation(const cppkafka::TopicPartitionList &partitions);
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
//
|
||||
//
|
||||
// Created by stephane bourque on 2022-10-26.
|
||||
//
|
||||
|
||||
@@ -29,13 +30,29 @@
|
||||
#include "framework/WebSocketLogger.h"
|
||||
#include "framework/utils.h"
|
||||
|
||||
#ifdef USE_MEDUSA_CLIENT
|
||||
#include <medusa/MedusaClient.h>
|
||||
#endif
|
||||
|
||||
namespace OpenWifi {
|
||||
|
||||
void MicroService::Exit(int Reason) { std::exit(Reason); }
|
||||
static std::string MakeServiceListString(const Types::MicroServiceMetaMap &Services) {
|
||||
std::string SvcList;
|
||||
for (const auto &Svc : Services) {
|
||||
if (SvcList.empty())
|
||||
SvcList = Svc.second.Type;
|
||||
else
|
||||
SvcList += ", " + Svc.second.Type;
|
||||
}
|
||||
return SvcList;
|
||||
}
|
||||
|
||||
void MicroService::BusMessageReceived([[maybe_unused]] const std::string &Key,
|
||||
const std::string &Payload) {
|
||||
std::lock_guard G(InfraMutex_);
|
||||
|
||||
Poco::Logger &BusLogger = EventBusManager()->Logger();
|
||||
|
||||
try {
|
||||
Poco::JSON::Parser P;
|
||||
auto Object = P.parse(Payload).extract<Poco::JSON::Object::Ptr>();
|
||||
@@ -55,13 +72,10 @@ namespace OpenWifi {
|
||||
Object->has(KafkaTopics::ServiceEvents::Fields::KEY)) {
|
||||
auto PrivateEndPoint =
|
||||
Object->get(KafkaTopics::ServiceEvents::Fields::PRIVATE).toString();
|
||||
if (Event == KafkaTopics::ServiceEvents::EVENT_KEEP_ALIVE &&
|
||||
Services_.find(PrivateEndPoint) != Services_.end()) {
|
||||
Services_[PrivateEndPoint].LastUpdate = Utils::Now();
|
||||
} else if (Event == KafkaTopics::ServiceEvents::EVENT_LEAVE) {
|
||||
if (Event == KafkaTopics::ServiceEvents::EVENT_LEAVE) {
|
||||
Services_.erase(PrivateEndPoint);
|
||||
poco_debug(
|
||||
logger(),
|
||||
poco_information(
|
||||
BusLogger,
|
||||
fmt::format(
|
||||
"Service {} ID={} leaving system.",
|
||||
Object->get(KafkaTopics::ServiceEvents::Fields::PRIVATE)
|
||||
@@ -69,14 +83,7 @@ namespace OpenWifi {
|
||||
ID));
|
||||
} else if (Event == KafkaTopics::ServiceEvents::EVENT_JOIN ||
|
||||
Event == KafkaTopics::ServiceEvents::EVENT_KEEP_ALIVE) {
|
||||
poco_debug(
|
||||
logger(),
|
||||
fmt::format(
|
||||
"Service {} ID={} joining system.",
|
||||
Object->get(KafkaTopics::ServiceEvents::Fields::PRIVATE)
|
||||
.toString(),
|
||||
ID));
|
||||
Services_[PrivateEndPoint] = Types::MicroServiceMeta{
|
||||
auto ServiceInfo = Types::MicroServiceMeta{
|
||||
.Id = ID,
|
||||
.Type = Poco::toLower(
|
||||
Object->get(KafkaTopics::ServiceEvents::Fields::TYPE)
|
||||
@@ -94,20 +101,46 @@ namespace OpenWifi {
|
||||
.toString(),
|
||||
.LastUpdate = Utils::Now()};
|
||||
|
||||
std::string SvcList;
|
||||
for (const auto &Svc : Services_) {
|
||||
if (SvcList.empty())
|
||||
SvcList = Svc.second.Type;
|
||||
else
|
||||
SvcList += ", " + Svc.second.Type;
|
||||
auto s1 = MakeServiceListString(Services_);
|
||||
auto PreviousSize = Services_.size();
|
||||
Services_[PrivateEndPoint] = ServiceInfo;
|
||||
auto CurrentSize = Services_.size();
|
||||
if(Event == KafkaTopics::ServiceEvents::EVENT_JOIN) {
|
||||
if(!s1.empty()) {
|
||||
poco_information(
|
||||
BusLogger,
|
||||
fmt::format(
|
||||
"Service {} ID={} is joining the system.",
|
||||
Object
|
||||
->get(
|
||||
KafkaTopics::ServiceEvents::Fields::PRIVATE)
|
||||
.toString(),
|
||||
ID));
|
||||
}
|
||||
std::string SvcList;
|
||||
for (const auto &Svc : Services_) {
|
||||
if (SvcList.empty())
|
||||
SvcList = Svc.second.Type;
|
||||
else
|
||||
SvcList += ", " + Svc.second.Type;
|
||||
}
|
||||
poco_information(
|
||||
BusLogger,
|
||||
fmt::format("Current list of microservices: {}", SvcList));
|
||||
} else if(CurrentSize!=PreviousSize) {
|
||||
poco_information(
|
||||
BusLogger,
|
||||
fmt::format(
|
||||
"Service {} ID={} is being added back in.",
|
||||
Object
|
||||
->get(KafkaTopics::ServiceEvents::Fields::PRIVATE)
|
||||
.toString(),
|
||||
ID));
|
||||
}
|
||||
poco_information(
|
||||
logger(),
|
||||
fmt::format("Current list of microservices: {}", SvcList));
|
||||
}
|
||||
} else {
|
||||
poco_error(
|
||||
logger(),
|
||||
poco_information(
|
||||
BusLogger,
|
||||
fmt::format("KAFKA-MSG: invalid event '{}', missing a field.",
|
||||
Event));
|
||||
}
|
||||
@@ -118,32 +151,39 @@ namespace OpenWifi {
|
||||
Object->get(KafkaTopics::ServiceEvents::Fields::TOKEN).toString());
|
||||
#endif
|
||||
} else {
|
||||
poco_error(
|
||||
logger(),
|
||||
poco_information(
|
||||
BusLogger,
|
||||
fmt::format("KAFKA-MSG: invalid event '{}', missing token", Event));
|
||||
}
|
||||
} else {
|
||||
poco_error(logger(),
|
||||
poco_information(BusLogger,
|
||||
fmt::format("Unknown Event: {} Source: {}", Event, ID));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
poco_error(logger(), "Bad bus message.");
|
||||
std::ostringstream os;
|
||||
Object->stringify(std::cout);
|
||||
std::ostringstream os;
|
||||
Object->stringify(std::cout);
|
||||
poco_error(BusLogger, fmt::format("Bad bus message: {}", os.str()));
|
||||
}
|
||||
|
||||
auto i = Services_.begin();
|
||||
auto ServiceHint = Services_.begin();
|
||||
auto now = Utils::Now();
|
||||
for (; i != Services_.end();) {
|
||||
if ((now - i->second.LastUpdate) > 60) {
|
||||
i = Services_.erase(i);
|
||||
auto si1 = Services_.size();
|
||||
auto ss1 = MakeServiceListString(Services_);
|
||||
while(ServiceHint!=Services_.end()) {
|
||||
if ((now - ServiceHint->second.LastUpdate) > 120) {
|
||||
poco_information(BusLogger, fmt::format("ZombieService: Removing service {}, ", ServiceHint->second.PublicEndPoint));
|
||||
ServiceHint = Services_.erase(ServiceHint);
|
||||
} else
|
||||
++i;
|
||||
++ServiceHint;
|
||||
}
|
||||
if(Services_.size() != si1) {
|
||||
auto ss2 = MakeServiceListString(Services_);
|
||||
poco_information(BusLogger, fmt::format("Current list of microservices: {} -> {}", ss1, ss2));
|
||||
}
|
||||
|
||||
} catch (const Poco::Exception &E) {
|
||||
logger().log(E);
|
||||
BusLogger.log(E);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -167,25 +207,29 @@ namespace OpenWifi {
|
||||
Res.push_back(ServiceRec);
|
||||
}
|
||||
return Res;
|
||||
|
||||
}
|
||||
|
||||
void MicroService::LoadConfigurationFile() {
|
||||
std::string Location = Poco::Environment::get(DAEMON_CONFIG_ENV_VAR, ".");
|
||||
ConfigFileName_ =
|
||||
ConfigFileName_.empty() ? Location + "/" + DAEMON_PROPERTIES_FILENAME : ConfigFileName_;
|
||||
Poco::Path ConfigFile(ConfigFileName_);
|
||||
if(ConfigContent_.empty()) {
|
||||
std::string Location = Poco::Environment::get(DAEMON_CONFIG_ENV_VAR, ".");
|
||||
ConfigFileName_ =
|
||||
ConfigFileName_.empty() ? Location + "/" + DAEMON_PROPERTIES_FILENAME : ConfigFileName_;
|
||||
Poco::Path ConfigFile(ConfigFileName_);
|
||||
|
||||
if (!ConfigFile.isFile()) {
|
||||
std::cerr << DAEMON_APP_NAME << ": Configuration " << ConfigFile.toString()
|
||||
<< " does not seem to exist. Please set " + DAEMON_CONFIG_ENV_VAR +
|
||||
" env variable the path of the " + DAEMON_PROPERTIES_FILENAME +
|
||||
" file."
|
||||
<< std::endl;
|
||||
std::exit(Poco::Util::Application::EXIT_CONFIG);
|
||||
}
|
||||
|
||||
// loadConfiguration(ConfigFile.toString());
|
||||
PropConfigurationFile_ = new Poco::Util::PropertyFileConfiguration(ConfigFile.toString());
|
||||
if (!ConfigFile.isFile()) {
|
||||
std::cerr << DAEMON_APP_NAME << ": Configuration " << ConfigFile.toString()
|
||||
<< " does not seem to exist. Please set " + DAEMON_CONFIG_ENV_VAR +
|
||||
" env variable the path of the " + DAEMON_PROPERTIES_FILENAME +
|
||||
" file."
|
||||
<< std::endl;
|
||||
std::exit(Poco::Util::Application::EXIT_CONFIG);
|
||||
}
|
||||
PropConfigurationFile_ = new Poco::Util::PropertyFileConfiguration(ConfigFile.toString());
|
||||
} else {
|
||||
std::istringstream is(ConfigContent_);
|
||||
PropConfigurationFile_ = new Poco::Util::PropertyFileConfiguration(is);
|
||||
}
|
||||
configPtr()->addWriteable(PropConfigurationFile_, PRIO_DEFAULT);
|
||||
}
|
||||
|
||||
@@ -388,49 +432,69 @@ namespace OpenWifi {
|
||||
|
||||
void DaemonPostInitialization(Poco::Util::Application &self);
|
||||
|
||||
void MicroService::initialize(Poco::Util::Application &self) {
|
||||
// add the default services
|
||||
LoadConfigurationFile();
|
||||
InitializeLoggingSystem();
|
||||
void MicroService::StartEverything(Poco::Util::Application &self) {
|
||||
LoadConfigurationFile();
|
||||
InitializeLoggingSystem();
|
||||
|
||||
SubSystems_.push_back(KafkaManager());
|
||||
SubSystems_.push_back(ALBHealthCheckServer());
|
||||
SubSystems_.push_back(RESTAPI_ExtServer());
|
||||
SubSystems_.push_back(RESTAPI_IntServer());
|
||||
static bool InitializedBaseService=false;
|
||||
if(!InitializedBaseService) {
|
||||
InitializedBaseService = true;
|
||||
SubSystems_.push_back(KafkaManager());
|
||||
SubSystems_.push_back(ALBHealthCheckServer());
|
||||
SubSystems_.push_back(RESTAPI_ExtServer());
|
||||
SubSystems_.push_back(RESTAPI_IntServer());
|
||||
#ifndef TIP_SECURITY_SERVICE
|
||||
SubSystems_.push_back(AuthClient());
|
||||
SubSystems_.push_back(AuthClient());
|
||||
#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"));
|
||||
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_;
|
||||
Poco::Net::initializeSSL();
|
||||
Poco::Net::HTTPStreamFactory::registerFactory();
|
||||
Poco::Net::HTTPSStreamFactory::registerFactory();
|
||||
Poco::Net::FTPStreamFactory::registerFactory();
|
||||
Poco::Net::FTPSStreamFactory::registerFactory();
|
||||
}
|
||||
|
||||
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();
|
||||
ServerApplication::initialize(self);
|
||||
DaemonPostInitialization(self);
|
||||
AllowExternalMicroServices_ = ConfigGetBool("allowexternalmicroservices", true);
|
||||
|
||||
Types::TopicNotifyFunction F = [this](const std::string &Key, const std::string &Payload) {
|
||||
this->BusMessageReceived(Key, Payload);
|
||||
};
|
||||
KafkaManager()->RegisterTopicWatcher(KafkaTopics::SERVICE_EVENTS, F);
|
||||
InitializeSubSystemServers();
|
||||
ServerApplication::initialize(self);
|
||||
DaemonPostInitialization(self);
|
||||
|
||||
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() {
|
||||
@@ -530,14 +594,12 @@ namespace OpenWifi {
|
||||
for (auto i : SubSystems_) {
|
||||
i->Start();
|
||||
}
|
||||
EventBusManager_ = std::make_unique<EventBusManager>(Poco::Logger::create(
|
||||
"EventBusManager", Poco::Logger::root().getChannel(), Poco::Logger::root().getLevel()));
|
||||
EventBusManager_->Start();
|
||||
EventBusManager()->Start();
|
||||
}
|
||||
|
||||
void MicroService::StopSubSystemServers() {
|
||||
AddActivity("Stopping");
|
||||
EventBusManager_->Stop();
|
||||
EventBusManager()->Stop();
|
||||
for (auto i = SubSystems_.rbegin(); i != SubSystems_.rend(); ++i) {
|
||||
(*i)->Stop();
|
||||
}
|
||||
@@ -697,7 +759,7 @@ namespace OpenWifi {
|
||||
auto APIKEY = Request.get("X-API-KEY");
|
||||
return APIKEY == MyHash_;
|
||||
} catch (const Poco::Exception &E) {
|
||||
logger().log(E);
|
||||
Logger_.log(E);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -718,6 +780,8 @@ namespace OpenWifi {
|
||||
MicroServiceErrorHandler ErrorHandler(*this);
|
||||
Poco::ErrorHandler::set(&ErrorHandler);
|
||||
|
||||
Args_ = args;
|
||||
|
||||
if (!HelpRequested_) {
|
||||
SavePID();
|
||||
|
||||
@@ -733,11 +797,18 @@ namespace OpenWifi {
|
||||
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_));
|
||||
StartSubSystemServers();
|
||||
waitForTerminationRequest();
|
||||
StopSubSystemServers();
|
||||
logger.notice(fmt::format("Stopped {}...", DAEMON_APP_NAME));
|
||||
#endif
|
||||
}
|
||||
|
||||
return Application::EXIT_OK;
|
||||
@@ -774,4 +845,4 @@ namespace OpenWifi {
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace OpenWifi
|
||||
} // namespace OpenWifi
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#include <iostream>
|
||||
#include <random>
|
||||
#include <vector>
|
||||
#include <optional>
|
||||
|
||||
// This must be defined for poco_debug and poco_trace macros to function.
|
||||
|
||||
@@ -40,6 +41,7 @@ namespace OpenWifi {
|
||||
#include "Poco/Util/OptionSet.h"
|
||||
#include "Poco/Util/PropertyFileConfiguration.h"
|
||||
#include "Poco/Util/ServerApplication.h"
|
||||
#include "Poco/ThreadPool.h"
|
||||
|
||||
#include "framework/OpenWifiTypes.h"
|
||||
|
||||
@@ -55,9 +57,6 @@ namespace OpenWifi {
|
||||
#include "nlohmann/json.hpp"
|
||||
#include "ow_version.h"
|
||||
|
||||
#define _OWDEBUG_ std::cout << __FILE__ << ":" << __LINE__ << std::endl;
|
||||
// #define _OWDEBUG_ Logger().debug(Poco::format("%s: %lu",__FILE__,__LINE__));
|
||||
|
||||
namespace OpenWifi {
|
||||
|
||||
class MicroService : public Poco::Util::ServerApplication {
|
||||
@@ -70,7 +69,6 @@ namespace OpenWifi {
|
||||
SubSystems_(std::move(Subsystems)), Logger_(Poco::Logger::get("FRAMEWORK")) {
|
||||
instance_ = this;
|
||||
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";
|
||||
@@ -92,7 +90,7 @@ namespace OpenWifi {
|
||||
inline uint64_t DaemonBusTimer() const { return DAEMON_BUS_TIMER; };
|
||||
[[nodiscard]] const std::string &AppName() { return DAEMON_APP_NAME; }
|
||||
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";
|
||||
};
|
||||
[[nodiscard]] inline const std::string &GetUIURI() const { return UIURI_; };
|
||||
@@ -107,7 +105,8 @@ namespace OpenWifi {
|
||||
}
|
||||
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);
|
||||
Types::MicroServiceMetaVec GetServices(const std::string &Type);
|
||||
Types::MicroServiceMetaVec GetServices();
|
||||
@@ -115,7 +114,9 @@ namespace OpenWifi {
|
||||
void Reload();
|
||||
void LoadMyConfig();
|
||||
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 defineOptions(Poco::Util::OptionSet &options) override;
|
||||
void handleHelp(const std::string &name, const std::string &value);
|
||||
@@ -132,7 +133,7 @@ namespace OpenWifi {
|
||||
void Reload(const std::string &Sub);
|
||||
Types::StringVec GetSubSystems() const;
|
||||
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 ConfigGetBool(const std::string &Key, bool Default);
|
||||
@@ -166,12 +167,25 @@ namespace OpenWifi {
|
||||
const std::string &FormatterPattern,
|
||||
const std::string &root_env_var);
|
||||
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:
|
||||
static MicroService *instance_;
|
||||
bool HelpRequested_ = false;
|
||||
std::string LogDir_;
|
||||
std::string ConfigFileName_;
|
||||
std::string ConfigContent_;
|
||||
uint64_t ID_ = 1;
|
||||
Poco::SharedPtr<Poco::Crypto::RSAKey> AppKey_;
|
||||
bool DebugMode_ = false;
|
||||
@@ -201,7 +215,7 @@ namespace OpenWifi {
|
||||
Poco::JWT::Signer Signer_;
|
||||
Poco::Logger &Logger_;
|
||||
Poco::ThreadPool TimerPool_{"timer:pool", 2, 32};
|
||||
std::unique_ptr<EventBusManager> EventBusManager_;
|
||||
ArgVec Args_;
|
||||
};
|
||||
|
||||
inline MicroService *MicroService::instance_ = nullptr;
|
||||
|
||||
@@ -133,4 +133,8 @@ namespace OpenWifi {
|
||||
return MicroService::instance().Hash();
|
||||
}
|
||||
|
||||
std::optional<OpenWifi::Types::MicroServiceMeta> MicroServicePrivateAccessKey(const std::string &servicePrivateEndPoint) {
|
||||
return MicroService::instance().GetPrivateEndPointServiceKey(servicePrivateEndPoint);
|
||||
}
|
||||
|
||||
} // namespace OpenWifi
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <optional>
|
||||
|
||||
#include "framework/OpenWifiTypes.h"
|
||||
|
||||
@@ -23,7 +24,9 @@ namespace OpenWifi {
|
||||
std::string MicroServiceConfigGetString(const std::string &Key,
|
||||
const std::string &DefaultValue);
|
||||
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::string MicroServicePrivateEndPoint();
|
||||
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) {
|
||||
Response->setStatus(Poco::Net::HTTPResponse::HTTPStatus::HTTP_OK);
|
||||
SetCommonHeaders();
|
||||
@@ -552,8 +557,8 @@ namespace OpenWifi {
|
||||
|
||||
inline bool IsAuthorized(bool &Expired, bool &Contacted, bool SubOnly = false);
|
||||
|
||||
inline void ReturnObject(Poco::JSON::Object &Object) {
|
||||
PrepareResponse();
|
||||
inline void ReturnObject(Poco::JSON::Object &Object, Poco::Net::HTTPResponse::HTTPStatus Status = Poco::Net::HTTPResponse::HTTP_OK) {
|
||||
PrepareResponse(Status);
|
||||
if (Request != nullptr) {
|
||||
// can we compress ???
|
||||
auto AcceptedEncoding = Request->find("Accept-Encoding");
|
||||
|
||||
@@ -47,6 +47,8 @@ namespace OpenWifi {
|
||||
|
||||
}
|
||||
|
||||
Poco::Data::SessionPool &Pool() { return *Pool_; }
|
||||
|
||||
private:
|
||||
inline int Setup_SQLite();
|
||||
inline int Setup_MySQL();
|
||||
|
||||
@@ -35,7 +35,6 @@ namespace OpenWifi {
|
||||
P.verificationDepth = 9;
|
||||
P.loadDefaultCAs = root_ca_.empty();
|
||||
P.cipherList = "ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH";
|
||||
P.dhUse2048Bits = true;
|
||||
P.caLocation = cas_;
|
||||
// P.securityLevel =
|
||||
|
||||
@@ -68,6 +67,16 @@ namespace OpenWifi {
|
||||
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_);
|
||||
Context->usePrivateKey(Key);
|
||||
|
||||
@@ -334,4 +343,4 @@ namespace OpenWifi {
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace OpenWifi
|
||||
} // namespace OpenWifi
|
||||
|
||||
@@ -45,6 +45,7 @@ namespace OpenWifi {
|
||||
[[nodiscard]] inline auto KeyFile() const { return key_file_; };
|
||||
[[nodiscard]] inline auto CertFile() const { return cert_file_; };
|
||||
[[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 IssuerCertFile() const { return issuer_cert_file_; };
|
||||
[[nodiscard]] inline auto Name() const { return name_; };
|
||||
|
||||
@@ -58,11 +58,9 @@ namespace OpenWifi {
|
||||
void UI_WebSocketClientServer::run() {
|
||||
Running_ = true;
|
||||
while (Running_) {
|
||||
Poco::Thread::trySleep(2000);
|
||||
|
||||
if (!Running_)
|
||||
break;
|
||||
|
||||
if(!Poco::Thread::trySleep(2000)) {
|
||||
break;
|
||||
}
|
||||
std::lock_guard G(LocalMutex_);
|
||||
for (const auto i : ToBeRemoved_) {
|
||||
// std::cout << "Erasing old WS UI connection..." << std::endl;
|
||||
@@ -212,10 +210,16 @@ namespace OpenWifi {
|
||||
n = Client->second->WS_->receiveFrame(IncomingFrame, flags);
|
||||
auto Op = flags & Poco::Net::WebSocket::FRAME_OP_BITMASK;
|
||||
|
||||
if (n == -1) {
|
||||
poco_warning(Logger(),
|
||||
fmt::format("UI-EMPTY({}): {} Empty Frame flags {}.",
|
||||
Client->second->Id_, Client->second->UserName_, flags));
|
||||
return;
|
||||
}
|
||||
if (n == 0) {
|
||||
poco_debug(Logger(),
|
||||
fmt::format("CLOSE({}): {} UI Client is closing WS connection.",
|
||||
Client->second->Id_, Client->second->UserName_));
|
||||
fmt::format("CLOSE({}): {} UI Client is closing WS connection.",
|
||||
Client->second->Id_, Client->second->UserName_));
|
||||
return EndConnection(Client);
|
||||
}
|
||||
|
||||
@@ -223,7 +227,7 @@ namespace OpenWifi {
|
||||
case Poco::Net::WebSocket::FRAME_OP_PING: {
|
||||
Client->second->WS_->sendFrame("", 0,
|
||||
(int)Poco::Net::WebSocket::FRAME_OP_PONG |
|
||||
(int)Poco::Net::WebSocket::FRAME_FLAG_FIN);
|
||||
(int)Poco::Net::WebSocket::FRAME_FLAG_FIN);
|
||||
} break;
|
||||
case Poco::Net::WebSocket::FRAME_OP_PONG: {
|
||||
} break;
|
||||
@@ -233,6 +237,11 @@ namespace OpenWifi {
|
||||
Client->second->Id_, Client->second->UserName_));
|
||||
return EndConnection(Client);
|
||||
} break;
|
||||
case Poco::Net::WebSocket::FRAME_OP_CONT: {
|
||||
poco_warning(Logger(),
|
||||
fmt::format("CONT({}): {} Unexpected CONT Frame - Ignoring.",
|
||||
Client->second->Id_, Client->second->UserName_));
|
||||
} break;
|
||||
case Poco::Net::WebSocket::FRAME_OP_TEXT: {
|
||||
constexpr const char *DropMessagesCommand = "drop-notifications";
|
||||
IncomingFrame.append(0);
|
||||
@@ -321,4 +330,4 @@ namespace OpenWifi {
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace OpenWifi
|
||||
} // namespace OpenWifi
|
||||
|
||||
@@ -7,57 +7,59 @@
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
#include "ow_constants.h"
|
||||
|
||||
namespace OpenWifi {
|
||||
inline const std::vector<std::pair<std::string, std::string>> DefaultDeviceTypeList{
|
||||
{"actiontec_web7200", "AP"},
|
||||
{"cig_wf186w", "AP"},
|
||||
{"cig_wf188n", "AP"},
|
||||
{"cig_wf194c4", "AP"},
|
||||
{"cig_wf196", "AP"},
|
||||
{"cig_wf196-ca", "AP"},
|
||||
{"cig_wf196-ca-ath12", "AP"},
|
||||
{"cig_wf196-us", "AP"},
|
||||
{"cig_wf610d", "AP"},
|
||||
{"cig_wf660a", "AP"},
|
||||
{"cig_wf808", "AP"},
|
||||
{"cybertan_eww622-a1", "AP"},
|
||||
{"edgecore_eap101", "AP"},
|
||||
{"edgecore_eap101-ath12", "AP"},
|
||||
{"edgecore_eap102", "AP"},
|
||||
{"edgecore_eap104", "AP"},
|
||||
{"edgecore_eap104-ath12", "AP"},
|
||||
{"edgecore_ecs4100-12ph", "AP"},
|
||||
{"edgecore_ecw5211", "AP"},
|
||||
{"edgecore_ecw5410", "AP"},
|
||||
{"edgecore_oap100", "AP"},
|
||||
{"edgecore_spw2ac1200", "SWITCH"},
|
||||
{"edgecore_spw2ac1200-lan-poe", "SWITCH"},
|
||||
{"edgecore_ssw2ac2600", "SWITCH"},
|
||||
{"hfcl_ion4", "AP"},
|
||||
{"hfcl_ion4x", "AP"},
|
||||
{"hfcl_ion4x_2", "AP"},
|
||||
{"hfcl_ion4xe", "AP"},
|
||||
{"hfcl_ion4xi", "AP"},
|
||||
{"indio_um-305ac", "AP"},
|
||||
{"indio_um-305ax", "AP"},
|
||||
{"indio_um-310ax-v1", "AP"},
|
||||
{"indio_um-325ac", "AP"},
|
||||
{"indio_um-510ac-v3", "AP"},
|
||||
{"indio_um-510axm-v1", "AP"},
|
||||
{"indio_um-510axp-v1", "AP"},
|
||||
{"indio_um-550ac", "AP"},
|
||||
{"linksys_e8450-ubi", "AP"},
|
||||
{"linksys_ea6350-v4", "AP"},
|
||||
{"linksys_ea8300", "AP"},
|
||||
{"liteon_wpx8324", "AP"},
|
||||
{"meshpp_s618_cp01", "AP"},
|
||||
{"meshpp_s618_cp03", "AP"},
|
||||
{"udaya_a5-id2", "AP"},
|
||||
{"wallys_dr40x9", "AP"},
|
||||
{"wallys_dr6018", "AP"},
|
||||
{"wallys_dr6018_v4", "AP"},
|
||||
{"x64_vm", "AP"},
|
||||
{"yuncore_ax840", "AP"},
|
||||
{"yuncore_fap640", "AP"},
|
||||
{"yuncore_fap650", "AP"}};
|
||||
{"actiontec_web7200", Platforms::AP},
|
||||
{"cig_wf186w", Platforms::AP},
|
||||
{"cig_wf188n", Platforms::AP},
|
||||
{"cig_wf194c4", Platforms::AP},
|
||||
{"cig_wf196", Platforms::AP},
|
||||
{"cig_wf196-ca", Platforms::AP},
|
||||
{"cig_wf196-ca-ath12", Platforms::AP},
|
||||
{"cig_wf196-us", Platforms::AP},
|
||||
{"cig_wf610d", Platforms::AP},
|
||||
{"cig_wf660a", Platforms::AP},
|
||||
{"cig_wf808", Platforms::AP},
|
||||
{"cybertan_eww622-a1", Platforms::AP},
|
||||
{"edgecore_eap101", Platforms::AP},
|
||||
{"edgecore_eap101-ath12", Platforms::AP},
|
||||
{"edgecore_eap102", Platforms::AP},
|
||||
{"edgecore_eap104", Platforms::AP},
|
||||
{"edgecore_eap104-ath12", Platforms::AP},
|
||||
{"edgecore_ecs4100-12ph", Platforms::AP},
|
||||
{"edgecore_ecw5211", Platforms::AP},
|
||||
{"edgecore_ecw5410", Platforms::AP},
|
||||
{"edgecore_oap100", Platforms::AP},
|
||||
{"edgecore_spw2ac1200", Platforms::SWITCH},
|
||||
{"edgecore_spw2ac1200-lan-poe", Platforms::SWITCH},
|
||||
{"edgecore_ssw2ac2600", Platforms::SWITCH},
|
||||
{"hfcl_ion4", Platforms::AP},
|
||||
{"hfcl_ion4x", Platforms::AP},
|
||||
{"hfcl_ion4x_2", Platforms::AP},
|
||||
{"hfcl_ion4xe", Platforms::AP},
|
||||
{"hfcl_ion4xi", Platforms::AP},
|
||||
{"indio_um-305ac", Platforms::AP},
|
||||
{"indio_um-305ax", Platforms::AP},
|
||||
{"indio_um-310ax-v1", Platforms::AP},
|
||||
{"indio_um-325ac", Platforms::AP},
|
||||
{"indio_um-510ac-v3", Platforms::AP},
|
||||
{"indio_um-510axm-v1", Platforms::AP},
|
||||
{"indio_um-510axp-v1", Platforms::AP},
|
||||
{"indio_um-550ac", Platforms::AP},
|
||||
{"linksys_e8450-ubi", Platforms::AP},
|
||||
{"linksys_ea6350-v4", Platforms::AP},
|
||||
{"linksys_ea8300", Platforms::AP},
|
||||
{"liteon_wpx8324", Platforms::AP},
|
||||
{"meshpp_s618_cp01", Platforms::AP},
|
||||
{"meshpp_s618_cp03", Platforms::AP},
|
||||
{"udaya_a5-id2", Platforms::AP},
|
||||
{"wallys_dr40x9", Platforms::AP},
|
||||
{"wallys_dr6018", Platforms::AP},
|
||||
{"wallys_dr6018_v4", Platforms::AP},
|
||||
{"x64_vm", Platforms::AP},
|
||||
{"yuncore_ax840", Platforms::AP},
|
||||
{"yuncore_fap640", Platforms::AP},
|
||||
{"yuncore_fap650", Platforms::AP}};
|
||||
}
|
||||
|
||||
@@ -576,8 +576,8 @@ namespace ORM {
|
||||
bool UpdateRecord(field_name_t FieldName, const T &Value, const RecordType &R) {
|
||||
try {
|
||||
assert(ValidFieldName(FieldName));
|
||||
|
||||
Poco::Data::Session Session = Pool_.get();
|
||||
Session.begin();
|
||||
Poco::Data::Statement Update(Session);
|
||||
|
||||
RecordTuple RT;
|
||||
@@ -593,6 +593,7 @@ namespace ORM {
|
||||
Update.execute();
|
||||
if (Cache_)
|
||||
Cache_->UpdateCache(R);
|
||||
Session.commit();
|
||||
return true;
|
||||
} catch (const Poco::Exception &E) {
|
||||
Logger_.log(E);
|
||||
@@ -662,6 +663,7 @@ namespace ORM {
|
||||
assert(ValidFieldName(FieldName));
|
||||
|
||||
Poco::Data::Session Session = Pool_.get();
|
||||
Session.begin();
|
||||
Poco::Data::Statement Delete(Session);
|
||||
|
||||
std::string St = "delete from " + TableName_ + " where " + FieldName + "=?";
|
||||
@@ -671,6 +673,7 @@ namespace ORM {
|
||||
Delete.execute();
|
||||
if (Cache_)
|
||||
Cache_->Delete(FieldName, Value);
|
||||
Session.commit();
|
||||
return true;
|
||||
} catch (const Poco::Exception &E) {
|
||||
Logger_.log(E);
|
||||
@@ -682,11 +685,13 @@ namespace ORM {
|
||||
try {
|
||||
assert(!WhereClause.empty());
|
||||
Poco::Data::Session Session = Pool_.get();
|
||||
Session.begin();
|
||||
Poco::Data::Statement Delete(Session);
|
||||
|
||||
std::string St = "delete from " + TableName_ + " where " + WhereClause;
|
||||
Delete << St;
|
||||
Delete.execute();
|
||||
Session.commit();
|
||||
return true;
|
||||
} catch (const Poco::Exception &E) {
|
||||
Logger_.log(E);
|
||||
|
||||
@@ -433,6 +433,10 @@ namespace OpenWifi::RESTAPI::Errors {
|
||||
|
||||
static const struct msg InvalidRRMAction { 1192, "Invalid RRM Action." };
|
||||
|
||||
static const struct msg InvalidPackageURL { 1193, "Invalid URL, must start with http:// or https://." };
|
||||
static const struct msg FailedToDownload { 1194, "Failed to download package." };
|
||||
static const struct msg FailedToDecompress { 1195, "Failed to decompress package data."};
|
||||
|
||||
static const struct msg SimulationDoesNotExist {
|
||||
7000, "Simulation Instance ID does not exist."
|
||||
};
|
||||
@@ -550,6 +554,10 @@ namespace OpenWifi::RESTAPI::Protocol {
|
||||
static const char *DEBUG = "debug";
|
||||
static const char *SCRIPT = "script";
|
||||
static const char *TIMEOUT = "timeout";
|
||||
static const char *PACKAGE = "package";
|
||||
static const char *PACKAGES = "packages";
|
||||
static const char *PACKAGEINST = "packageInstall";
|
||||
static const char *PACKAGEDEL = "packageDelete";
|
||||
|
||||
static const char *NEWPASSWORD = "newPassword";
|
||||
static const char *USERS = "users";
|
||||
@@ -565,6 +573,7 @@ namespace OpenWifi::RESTAPI::Protocol {
|
||||
|
||||
static const char *TRANSFER = "transfer";
|
||||
static const char *CERTUPDATE = "certupdate";
|
||||
static const char *POWERCYCLE = "powercycle";
|
||||
static const char *RRM = "rrm";
|
||||
|
||||
static const char *REQUIREMENTS = "requirements";
|
||||
@@ -579,6 +588,10 @@ namespace OpenWifi::RESTAPI::Protocol {
|
||||
static const char *INTERVAL = "interval";
|
||||
static const char *UI = "UI";
|
||||
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::uCentralProtocol {
|
||||
@@ -607,6 +620,7 @@ namespace OpenWifi::uCentralProtocol {
|
||||
static const char *CFGPENDING = "cfgpending";
|
||||
static const char *RECOVERY = "recovery";
|
||||
static const char *COMPRESS_64 = "compress_64";
|
||||
static const char *COMPRESS_SZ = "compress_sz";
|
||||
static const char *CAPABILITIES = "capabilities";
|
||||
static const char *REQUEST_UUID = "request_uuid";
|
||||
static const char *SANITY = "sanity";
|
||||
@@ -663,6 +677,9 @@ namespace OpenWifi::uCentralProtocol {
|
||||
static const char *SIGNATURE = "signature";
|
||||
static const char *INFO = "info";
|
||||
static const char *DATE = "date";
|
||||
static const char *PACKAGE = "package";
|
||||
static const char *PACKAGES = "packages";
|
||||
static const char *CATEGORY = "category";
|
||||
|
||||
static const char *SERIALNUMBER = "serialNumber";
|
||||
static const char *COMPATIBLE = "compatible";
|
||||
@@ -687,9 +704,15 @@ namespace OpenWifi::uCentralProtocol {
|
||||
|
||||
static const char *TRANSFER = "transfer";
|
||||
static const char *CERTUPDATE = "certupdate";
|
||||
static const char *POWERCYCLE = "powercycle";
|
||||
static const char *RRM = "rrm";
|
||||
static const char *ACTIONS = "actions";
|
||||
|
||||
static const char *FIXEDCONFIG = "fixedconfig";
|
||||
static const char *CABLEDIAGNOSTICS = "cable-diagnostics";
|
||||
static const char *REENROLL = "reenroll";
|
||||
|
||||
static const char *OPERATION = "op";
|
||||
} // namespace OpenWifi::uCentralProtocol
|
||||
|
||||
namespace OpenWifi::uCentralProtocol::Events {
|
||||
@@ -724,7 +747,7 @@ namespace OpenWifi::uCentralProtocol::Events {
|
||||
ET_EVENT,
|
||||
ET_WIFISCAN,
|
||||
ET_ALARM,
|
||||
ET_REBOOTLOG
|
||||
ET_REBOOTLOG,
|
||||
};
|
||||
|
||||
inline EVENT_MSG EventFromString(const std::string &Method) {
|
||||
@@ -785,6 +808,11 @@ namespace OpenWifi::APCommands {
|
||||
rrm,
|
||||
certupdate,
|
||||
transfer,
|
||||
powercycle,
|
||||
fixedconfig,
|
||||
cablediagnostics,
|
||||
reenroll,
|
||||
package,
|
||||
unknown
|
||||
};
|
||||
|
||||
@@ -799,7 +827,9 @@ namespace OpenWifi::APCommands {
|
||||
RESTAPI::Protocol::EVENTQUEUE, RESTAPI::Protocol::TELEMETRY,
|
||||
RESTAPI::Protocol::PING, RESTAPI::Protocol::SCRIPT,
|
||||
RESTAPI::Protocol::RRM, RESTAPI::Protocol::CERTUPDATE,
|
||||
RESTAPI::Protocol::TRANSFER
|
||||
RESTAPI::Protocol::TRANSFER, RESTAPI::Protocol::POWERCYCLE,
|
||||
RESTAPI::Protocol::FIXEDCONFIG, RESTAPI::Protocol::CABLEDIAGNOSTICS,
|
||||
RESTAPI::Protocol::REENROLL, RESTAPI::Protocol::PACKAGE
|
||||
};
|
||||
|
||||
inline const char *to_string(Commands Cmd) { return uCentralAPCommands[(uint8_t)Cmd]; }
|
||||
@@ -828,6 +858,11 @@ 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__)
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
@@ -590,6 +590,26 @@ namespace OpenWifi::Utils {
|
||||
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) {
|
||||
return std::all_of(s.begin(), s.end(), [](char c) -> bool { return isalnum(c); });
|
||||
}
|
||||
@@ -868,78 +888,15 @@ namespace OpenWifi::Utils {
|
||||
return password;
|
||||
}
|
||||
|
||||
// Function to query NAPTR records for a domain and return them in a vector
|
||||
std::vector<NAPTRRecord> getNAPTRRecords(const std::string& domain) {
|
||||
std::vector<NAPTRRecord> naptrRecords;
|
||||
|
||||
unsigned char buf[4096];
|
||||
ns_msg handle;
|
||||
ns_initparse(buf, NS_PACKETSZ, &handle);
|
||||
|
||||
// Query NAPTR records for the given domain
|
||||
int response = res_query(domain.c_str(), ns_c_in, ns_t_naptr, buf, sizeof(buf));
|
||||
if (response < 0) {
|
||||
return naptrRecords;
|
||||
}
|
||||
|
||||
if(ns_initparse(buf, response, &handle) < 0) {
|
||||
return naptrRecords;
|
||||
}
|
||||
|
||||
// Iterate through the DNS response and extract NAPTR records
|
||||
int count = ns_msg_count(handle, ns_s_an);
|
||||
for (int i = 0; i < count; ++i) {
|
||||
ns_rr rr;
|
||||
if (ns_parserr(&handle, ns_s_an, i, &rr) == 0) {
|
||||
char rdata[256];
|
||||
ns_sprintrr(&handle, &rr, nullptr, nullptr, rdata, sizeof(rdata));
|
||||
NAPTRRecord record;
|
||||
std::istringstream os(rdata);
|
||||
os >> record.name >> record.ttl >> record.rclass >> record.rtype >> record.order >> record.preference >> record.flags
|
||||
>> record.service >> record.regexp >> record.replacement;
|
||||
naptrRecords.push_back(record);
|
||||
}
|
||||
}
|
||||
|
||||
return naptrRecords;
|
||||
}
|
||||
/*
|
||||
Note that these 2 functions aren't used. They have been removed due to this deprecation warning:
|
||||
// Function to query NAPTR records for a domain and return them in a vector
|
||||
#47 3.825 /owgw/src/framework/utils.cpp: In function 'std::vector<OpenWifi::Utils::NAPTRRecord> OpenWifi::Utils::getNAPTRRecords(const std::string&)':
|
||||
#47 3.825 /owgw/src/framework/utils.cpp:915:28: warning: 'int ns_sprintrr(const ns_msg*, const ns_rr*, const char*, const char*, char*, size_t)' is deprecated [-Wdeprecated-declarations]
|
||||
|
||||
std::vector<SrvRecord> getSRVRecords(const std::string& domain) {
|
||||
std::vector<SrvRecord> srvRecords;
|
||||
|
||||
// Buffer to hold the DNS response
|
||||
unsigned char buf[4096];
|
||||
ns_msg handle;
|
||||
ns_initparse(buf, NS_PACKETSZ, &handle);
|
||||
|
||||
// Query NAPTR records for the given domain
|
||||
int response = res_query(domain.c_str(), ns_c_in, ns_t_srv, buf, sizeof(buf));
|
||||
if (response < 0) {
|
||||
std::cerr << "DNS query failed for " << domain << ": " << hstrerror(h_errno) << std::endl;
|
||||
return srvRecords;
|
||||
}
|
||||
|
||||
if(ns_initparse(buf, response, &handle) < 0) {
|
||||
return srvRecords;
|
||||
}
|
||||
|
||||
// Iterate through the DNS response and extract NAPTR records
|
||||
int count = ns_msg_count(handle, ns_s_an);
|
||||
for (int i = 0; i < count; ++i) {
|
||||
ns_rr rr;
|
||||
if (ns_parserr(&handle, ns_s_an, i, &rr) == 0) {
|
||||
char rdata[256];
|
||||
ns_sprintrr(&handle, &rr, nullptr, nullptr, rdata, sizeof(rdata));
|
||||
SrvRecord record;
|
||||
std::istringstream os(rdata);
|
||||
os >> record.name >> record.ttl >> record.rclass >> record.rtype >> record.pref >> record.weight >>
|
||||
record.port >> record.srvname ;
|
||||
srvRecords.push_back(record);
|
||||
}
|
||||
}
|
||||
|
||||
return srvRecords;
|
||||
}
|
||||
|
||||
#47 3.833 /owgw/src/framework/utils.cpp: In function 'std::vector<OpenWifi::Utils::SrvRecord> OpenWifi::Utils::getSRVRecords(const std::string&)':
|
||||
#47 3.833 /owgw/src/framework/utils.cpp:952:28: warning: 'int ns_sprintrr(const ns_msg*, const ns_rr*, const char*, const char*, char*, size_t)' is deprecated [-Wdeprecated-declarations]
|
||||
*/
|
||||
|
||||
} // namespace OpenWifi::Utils
|
||||
|
||||
@@ -126,20 +126,6 @@ namespace OpenWifi::Utils {
|
||||
|
||||
[[nodiscard]] std::uint64_t ConvertDate(const std::string &d);
|
||||
|
||||
[[nodiscard]] inline uint8_t CalculateMacAddressHash(std::uint64_t value) {
|
||||
uint8_t hash = 0, i=6;
|
||||
while(i) {
|
||||
hash ^= (value & 0xFF) + 1;
|
||||
value >>= 8;
|
||||
--i;
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
|
||||
[[nodiscard]] inline uint8_t CalculateMacAddressHash(const std::string & value) {
|
||||
return CalculateMacAddressHash(MACToInt(value));
|
||||
}
|
||||
|
||||
template <typename T> std::string int_to_hex(T i) {
|
||||
std::stringstream stream;
|
||||
stream << std::setfill('0') << std::setw(12) << std::hex << i;
|
||||
@@ -165,6 +151,8 @@ namespace OpenWifi::Utils {
|
||||
bool ExtractBase64CompressedData(const std::string &CompressedData,
|
||||
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)
|
||||
{
|
||||
// If we reach at the end of both strings, we are done
|
||||
@@ -310,8 +298,10 @@ namespace OpenWifi::Utils {
|
||||
std::string replacement;
|
||||
};
|
||||
|
||||
// Function to query NAPTR records for a domain and return them in a vector
|
||||
std::vector<NAPTRRecord> getNAPTRRecords(const std::string& domain);
|
||||
// removed due to deprecation: see utils.cpp
|
||||
// Function to query NAPTR records for a domain and return them in a vector
|
||||
//std::vector<NAPTRRecord> getNAPTRRecords(const std::string& domain);
|
||||
|
||||
struct SrvRecord {
|
||||
std::string name;
|
||||
std::string ttl;
|
||||
@@ -323,12 +313,98 @@ namespace OpenWifi::Utils {
|
||||
std::string srvname;
|
||||
};
|
||||
|
||||
std::vector<SrvRecord> getSRVRecords(const std::string& domain);
|
||||
// removed due to deprecation: see utils.cpp
|
||||
// std::vector<SrvRecord> getSRVRecords(const std::string& domain);
|
||||
|
||||
struct HostNameServerResult{
|
||||
std::string Hostname;
|
||||
uint32_t Port;
|
||||
};
|
||||
|
||||
class CompressedString {
|
||||
public:
|
||||
CompressedString() {
|
||||
DecompressedSize_ = 0;
|
||||
};
|
||||
|
||||
explicit CompressedString(const std::string &Data) : DecompressedSize_(Data.size()) {
|
||||
CompressIt(Data);
|
||||
}
|
||||
|
||||
CompressedString(const CompressedString &Data) {
|
||||
this->DecompressedSize_ = Data.DecompressedSize_;
|
||||
this->CompressedData_ = Data.CompressedData_;
|
||||
}
|
||||
|
||||
CompressedString& operator=(const CompressedString& rhs) {
|
||||
if (this != &rhs) {
|
||||
this->DecompressedSize_ = rhs.DecompressedSize_;
|
||||
this->CompressedData_ = rhs.CompressedData_;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
CompressedString& operator=(CompressedString&& rhs) {
|
||||
if (this != &rhs) {
|
||||
this->DecompressedSize_ = rhs.DecompressedSize_;
|
||||
this->CompressedData_ = rhs.CompressedData_;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
~CompressedString() = default;
|
||||
|
||||
operator std::string() const {
|
||||
return DecompressIt();
|
||||
}
|
||||
|
||||
CompressedString &operator=(const std::string &Data) {
|
||||
DecompressedSize_ = Data.size();
|
||||
CompressIt(Data);
|
||||
return *this;
|
||||
}
|
||||
|
||||
auto CompressedSize() const { return CompressedData_.size(); }
|
||||
auto DecompressedSize() const { return DecompressedSize_; }
|
||||
|
||||
private:
|
||||
std::string CompressedData_;
|
||||
std::size_t DecompressedSize_;
|
||||
|
||||
inline void CompressIt(const std::string &Data) {
|
||||
z_stream strm; // = {0};
|
||||
CompressedData_.resize(Data.size());
|
||||
strm.next_in = (Bytef *)Data.data();
|
||||
strm.avail_in = Data.size();
|
||||
strm.next_out = (Bytef *)CompressedData_.data();
|
||||
strm.avail_out = Data.size();
|
||||
strm.zalloc = Z_NULL;
|
||||
strm.zfree = Z_NULL;
|
||||
strm.opaque = Z_NULL;
|
||||
deflateInit2(&strm, Z_DEFAULT_COMPRESSION, Z_DEFLATED, 15 + 16, 8, Z_DEFAULT_STRATEGY);
|
||||
deflate(&strm, Z_FINISH);
|
||||
deflateEnd(&strm);
|
||||
CompressedData_.resize(strm.total_out);
|
||||
}
|
||||
|
||||
[[nodiscard]] std::string DecompressIt() const {
|
||||
std::string Result;
|
||||
if(DecompressedSize_!=0) {
|
||||
Result.resize(DecompressedSize_);
|
||||
z_stream strm ; //= {0};
|
||||
strm.next_in = (Bytef *)CompressedData_.data();
|
||||
strm.avail_in = CompressedData_.size();
|
||||
strm.next_out = (Bytef *)Result.data();
|
||||
strm.avail_out = Result.size();
|
||||
strm.zalloc = Z_NULL;
|
||||
strm.zfree = Z_NULL;
|
||||
strm.opaque = Z_NULL;
|
||||
inflateInit2(&strm, 15 + 32);
|
||||
inflate(&strm, Z_FINISH);
|
||||
inflateEnd(&strm);
|
||||
}
|
||||
return Result;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace OpenWifi::Utils
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#include "nlohmann/json.hpp"
|
||||
|
||||
#include "Poco/NObserver.h"
|
||||
#include <Poco/Net/Context.h>
|
||||
#include "Poco/Net/SocketNotification.h"
|
||||
#include "Poco/Net/NetException.h"
|
||||
#include "Poco/Net/WebSocketImpl.h"
|
||||
@@ -71,6 +72,7 @@ namespace OpenWifi {
|
||||
const auto &RootCas =
|
||||
MicroServiceConfigPath("ucentral.websocket.host.0.rootca", "");
|
||||
const auto &Cas = MicroServiceConfigPath("ucentral.websocket.host.0.cas", "");
|
||||
const auto &ClientCasFile = MicroServiceConfigPath("ucentral.websocket.host.0.clientcas", "");
|
||||
|
||||
Poco::Net::Context::Params P;
|
||||
|
||||
@@ -86,6 +88,7 @@ namespace OpenWifi {
|
||||
Poco::Crypto::X509Certificate Cert(CertFileName);
|
||||
Poco::Crypto::X509Certificate Root(RootCaFileName);
|
||||
Poco::Crypto::X509Certificate Issuing(IssuerFileName);
|
||||
std::vector<Poco::Crypto::X509Certificate> ClientCasCerts;
|
||||
Poco::Crypto::RSAKey Key("", KeyFileName, KeyPassword);
|
||||
|
||||
DeviceSecureContext->useCertificate(Cert);
|
||||
@@ -93,7 +96,11 @@ namespace OpenWifi {
|
||||
DeviceSecureContext->addCertificateAuthority(Root);
|
||||
DeviceSecureContext->addChainCertificate(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->setSessionCacheSize(0);
|
||||
DeviceSecureContext->setSessionTimeout(120);
|
||||
@@ -146,7 +153,7 @@ namespace OpenWifi {
|
||||
|
||||
auto WebClientSecureContext =
|
||||
new Poco::Net::Context(Poco::Net::Context::SERVER_USE, KeyFileName,
|
||||
CertFileName, "", Poco::Net::Context::VERIFY_RELAXED);
|
||||
CertFileName, "", Poco::Net::Context::VERIFY_NONE);
|
||||
Poco::Crypto::X509Certificate WebRoot(RootCaFileName);
|
||||
WebClientSecureContext->addCertificateAuthority(WebRoot);
|
||||
WebClientSecureContext->disableStatelessSessionResumption();
|
||||
@@ -573,14 +580,16 @@ namespace OpenWifi {
|
||||
try {
|
||||
Client = Clients_.find(pNf->socket().impl()->sockfd());
|
||||
if (Client == end(Clients_)) {
|
||||
poco_warning(Logger(), fmt::format("Cannot find client socket: {}",
|
||||
pNf->socket().impl()->sockfd()));
|
||||
poco_warning(Logger(),
|
||||
fmt::format("Cannot find client socket: {}",
|
||||
pNf->socket().impl()->sockfd()));
|
||||
return;
|
||||
}
|
||||
Connection = Client->second;
|
||||
if(Connection->WSSocket_==nullptr || Connection->WSSocket_->impl()==nullptr) {
|
||||
poco_warning(Logger(), fmt::format("WebSocket is no valid: {}",
|
||||
Connection->SerialNumber_));
|
||||
poco_warning(Logger(),
|
||||
fmt::format("WebSocket is not valid: {}",
|
||||
Connection->SerialNumber_));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -589,15 +598,25 @@ namespace OpenWifi {
|
||||
|
||||
auto ReceivedBytes = Connection->WSSocket_->receiveFrame(FrameBuffer, sizeof(FrameBuffer), flags);
|
||||
auto Op = flags & Poco::Net::WebSocket::FRAME_OP_BITMASK;
|
||||
|
||||
if (ReceivedBytes == -1) {
|
||||
poco_trace(Logger(),
|
||||
fmt::format("WS-EMPTY{}: Non-blocking try-again empty Frame: flags {}",
|
||||
Connection->SerialNumber_, flags));
|
||||
return;
|
||||
}
|
||||
|
||||
switch (Op) {
|
||||
|
||||
case Poco::Net::WebSocket::FRAME_OP_PING: {
|
||||
Connection->WSSocket_->sendFrame("", 0,
|
||||
(int)Poco::Net::WebSocket::FRAME_OP_PONG |
|
||||
(int)Poco::Net::WebSocket::FRAME_FLAG_FIN);
|
||||
(int)Poco::Net::WebSocket::FRAME_OP_PONG |
|
||||
(int)Poco::Net::WebSocket::FRAME_FLAG_FIN);
|
||||
} break;
|
||||
|
||||
case Poco::Net::WebSocket::FRAME_OP_PONG: {
|
||||
} break;
|
||||
|
||||
case Poco::Net::WebSocket::FRAME_OP_TEXT: {
|
||||
if (ReceivedBytes == 0) {
|
||||
EndConnection(Connection,__func__,__LINE__);
|
||||
@@ -624,19 +643,29 @@ namespace OpenWifi {
|
||||
}
|
||||
}
|
||||
} break;
|
||||
|
||||
case Poco::Net::WebSocket::FRAME_OP_BINARY: {
|
||||
if (ReceivedBytes == 0) {
|
||||
EndConnection(Connection,__func__,__LINE__);
|
||||
return;
|
||||
} else {
|
||||
poco_trace(Logger(),
|
||||
fmt::format("Sending {} key strokes to device.", ReceivedBytes));
|
||||
fmt::format("Sending {} key strokes to device.", ReceivedBytes));
|
||||
if (!RTTYS_server().KeyStrokes(Connection, FrameBuffer, ReceivedBytes)) {
|
||||
EndConnection(Connection,__func__,__LINE__);
|
||||
return;
|
||||
}
|
||||
}
|
||||
} break;
|
||||
|
||||
case Poco::Net::WebSocket::FRAME_OP_CONT: {
|
||||
// may have to handle this, but not sure whether it's a continuation for text or
|
||||
// binary, seems to be a hole in the protocol.
|
||||
poco_warning(Logger(),
|
||||
fmt::format("CONT Frame {} received, ignoring for now.",
|
||||
ReceivedBytes));
|
||||
}
|
||||
|
||||
case Poco::Net::WebSocket::FRAME_OP_CLOSE: {
|
||||
EndConnection(Connection,__func__,__LINE__);
|
||||
return;
|
||||
@@ -682,8 +711,8 @@ namespace OpenWifi {
|
||||
if (Connection->WSSocket_ != nullptr && Connection->WSSocket_->impl()!= nullptr) {
|
||||
try {
|
||||
Connection->WSSocket_->sendFrame(Buf, len,
|
||||
Poco::Net::WebSocket::FRAME_FLAG_FIN |
|
||||
Poco::Net::WebSocket::FRAME_OP_BINARY);
|
||||
(int) Poco::Net::WebSocket::FRAME_FLAG_FIN |
|
||||
(int) Poco::Net::WebSocket::FRAME_OP_BINARY);
|
||||
return;
|
||||
} catch (...) {
|
||||
poco_error(Logger(), "SendData shutdown.");
|
||||
@@ -985,8 +1014,9 @@ namespace OpenWifi {
|
||||
}
|
||||
|
||||
bool RTTYS_server::SendToClient(Poco::Net::WebSocket &WebSocket, const u_char *Buf, int len) {
|
||||
WebSocket.sendFrame(
|
||||
Buf, len, Poco::Net::WebSocket::FRAME_FLAG_FIN | Poco::Net::WebSocket::FRAME_OP_BINARY);
|
||||
WebSocket.sendFrame(Buf, len,
|
||||
(int) Poco::Net::WebSocket::FRAME_FLAG_FIN |
|
||||
(int) Poco::Net::WebSocket::FRAME_OP_BINARY);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1117,4 +1147,4 @@ namespace OpenWifi {
|
||||
RTTYS_EndPoint::~RTTYS_EndPoint() {
|
||||
}
|
||||
|
||||
} // namespace OpenWifi
|
||||
} // namespace OpenWifi
|
||||
|
||||
@@ -56,10 +56,10 @@ namespace OpenWifi {
|
||||
struct DeviceDetails {
|
||||
std::string reason;
|
||||
std::string author;
|
||||
std::uint64_t created;
|
||||
std::uint64_t created=Utils::Now();
|
||||
};
|
||||
|
||||
static std::map<std::string, DeviceDetails> BlackListDevices;
|
||||
static std::map<std::uint64_t , DeviceDetails> BlackListDevices;
|
||||
static std::recursive_mutex BlackListMutex;
|
||||
|
||||
bool Storage::InitializeBlackListCache() {
|
||||
@@ -78,7 +78,7 @@ namespace OpenWifi {
|
||||
auto Reason = RSet[1].convert<std::string>();
|
||||
auto Author = RSet[2].convert<std::string>();
|
||||
auto Created = RSet[3].convert<std::uint64_t>();
|
||||
BlackListDevices[SerialNumber] =
|
||||
BlackListDevices[Utils::MACToInt(SerialNumber)] =
|
||||
DeviceDetails{.reason = Reason, .author = Author, .created = Created};
|
||||
More = RSet.moveNext();
|
||||
}
|
||||
@@ -93,6 +93,7 @@ namespace OpenWifi {
|
||||
bool Storage::AddBlackListDevice(GWObjects::BlackListedDevice &Device) {
|
||||
try {
|
||||
Poco::Data::Session Sess = Pool_->get();
|
||||
Sess.begin();
|
||||
Poco::Data::Statement Insert(Sess);
|
||||
|
||||
std::string St{"INSERT INTO BlackList (" + DB_BlackListDeviceSelectFields + ") " +
|
||||
@@ -102,9 +103,9 @@ namespace OpenWifi {
|
||||
ConvertBlackListDeviceRecord(Device, T);
|
||||
Insert << ConvertParams(St), Poco::Data::Keywords::use(T);
|
||||
Insert.execute();
|
||||
|
||||
Sess.commit();
|
||||
std::lock_guard G(BlackListMutex);
|
||||
BlackListDevices[Device.serialNumber] = DeviceDetails{
|
||||
BlackListDevices[Utils::MACToInt(Device.serialNumber)] = DeviceDetails{
|
||||
.reason = Device.reason, .author = Device.author, .created = Device.created};
|
||||
return true;
|
||||
} catch (const Poco::Exception &E) {
|
||||
@@ -130,6 +131,7 @@ namespace OpenWifi {
|
||||
bool Storage::DeleteBlackListDevice(std::string &SerialNumber) {
|
||||
try {
|
||||
Poco::Data::Session Sess = Pool_->get();
|
||||
Sess.begin();
|
||||
Poco::Data::Statement Delete(Sess);
|
||||
|
||||
std::string St{"DELETE FROM BlackList WHERE SerialNumber=?"};
|
||||
@@ -137,9 +139,9 @@ namespace OpenWifi {
|
||||
Poco::toLowerInPlace(SerialNumber);
|
||||
Delete << ConvertParams(St), Poco::Data::Keywords::use(SerialNumber);
|
||||
Delete.execute();
|
||||
|
||||
Sess.commit();
|
||||
std::lock_guard G(BlackListMutex);
|
||||
BlackListDevices.erase(SerialNumber);
|
||||
BlackListDevices.erase(Utils::MACToInt(SerialNumber));
|
||||
return true;
|
||||
} catch (const Poco::Exception &E) {
|
||||
poco_warning(Logger(), fmt::format("{}: Failed with: {}", std::string(__func__),
|
||||
@@ -177,6 +179,7 @@ namespace OpenWifi {
|
||||
GWObjects::BlackListedDevice &Device) {
|
||||
try {
|
||||
Poco::Data::Session Sess = Pool_->get();
|
||||
Sess.begin();
|
||||
Poco::Data::Statement Update(Sess);
|
||||
|
||||
std::string St{"UPDATE BlackList SET " + DB_BlackListDeviceUpdateFields +
|
||||
@@ -187,9 +190,9 @@ namespace OpenWifi {
|
||||
Update << ConvertParams(St), Poco::Data::Keywords::use(T),
|
||||
Poco::Data::Keywords::use(SerialNumber);
|
||||
Update.execute();
|
||||
|
||||
Sess.commit();
|
||||
std::lock_guard G(BlackListMutex);
|
||||
BlackListDevices[Device.serialNumber] = DeviceDetails{
|
||||
BlackListDevices[Utils::MACToInt(Device.serialNumber)] = DeviceDetails{
|
||||
.reason = Device.reason, .author = Device.author, .created = Device.created};
|
||||
|
||||
return true;
|
||||
@@ -233,10 +236,10 @@ namespace OpenWifi {
|
||||
return BlackListDevices.size();
|
||||
}
|
||||
|
||||
bool Storage::IsBlackListed(const std::string &SerialNumber, std::string &reason,
|
||||
bool Storage::IsBlackListed(std::uint64_t SerialNumber, std::string &reason,
|
||||
std::string &author, std::uint64_t &created) {
|
||||
std::lock_guard G(BlackListMutex);
|
||||
auto DeviceHint = BlackListDevices.find(Poco::toLower(SerialNumber));
|
||||
auto DeviceHint = BlackListDevices.find(SerialNumber);
|
||||
if (DeviceHint == end(BlackListDevices))
|
||||
return false;
|
||||
reason = DeviceHint->second.reason;
|
||||
@@ -245,9 +248,9 @@ namespace OpenWifi {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Storage::IsBlackListed(const std::string &SerialNumber) {
|
||||
bool Storage::IsBlackListed(std::uint64_t SerialNumber) {
|
||||
std::lock_guard G(BlackListMutex);
|
||||
auto DeviceHint = BlackListDevices.find(Poco::toLower(SerialNumber));
|
||||
auto DeviceHint = BlackListDevices.find(SerialNumber);
|
||||
return DeviceHint != end(BlackListDevices);
|
||||
}
|
||||
} // namespace OpenWifi
|
||||
@@ -17,11 +17,11 @@
|
||||
|
||||
namespace OpenWifi {
|
||||
|
||||
bool Storage::CreateDeviceCapabilities(std::string &SerialNumber,
|
||||
bool Storage::CreateDeviceCapabilities(Poco::Data::Session &Session, std::string &SerialNumber,
|
||||
const Config::Capabilities &Capabilities) {
|
||||
try {
|
||||
Poco::Data::Session Sess = Pool_->get();
|
||||
Poco::Data::Statement UpSert(Sess);
|
||||
Session.begin();
|
||||
Poco::Data::Statement UpSert(Session);
|
||||
|
||||
std::string TCaps{Capabilities.AsString()};
|
||||
uint64_t Now = Utils::Now();
|
||||
@@ -33,6 +33,7 @@ namespace OpenWifi {
|
||||
Poco::Data::Keywords::use(Now), Poco::Data::Keywords::use(TCaps),
|
||||
Poco::Data::Keywords::use(Now);
|
||||
UpSert.execute();
|
||||
Session.commit();
|
||||
return true;
|
||||
} catch (const Poco::Exception &E) {
|
||||
poco_warning(Logger(), fmt::format("{}: Failed with: {}", std::string(__func__),
|
||||
@@ -41,11 +42,11 @@ namespace OpenWifi {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Storage::UpdateDeviceCapabilities(std::string &SerialNumber,
|
||||
bool Storage::UpdateDeviceCapabilities(Poco::Data::Session &Session, std::string &SerialNumber,
|
||||
const Config::Capabilities &Caps) {
|
||||
try {
|
||||
Poco::Data::Session Sess = Pool_->get();
|
||||
Poco::Data::Statement UpSert(Sess);
|
||||
Session.begin();
|
||||
Poco::Data::Statement UpSert(Session);
|
||||
|
||||
uint64_t Now = Utils::Now();
|
||||
if (!Caps.Compatible().empty() && !Caps.Platform().empty())
|
||||
@@ -61,6 +62,7 @@ namespace OpenWifi {
|
||||
Poco::Data::Keywords::use(Now), Poco::Data::Keywords::use(TCaps),
|
||||
Poco::Data::Keywords::use(Now);
|
||||
UpSert.execute();
|
||||
Session.commit();
|
||||
return true;
|
||||
} catch (const Poco::Exception &E) {
|
||||
poco_warning(Logger(), fmt::format("{}: Failed with: {}", std::string(__func__),
|
||||
@@ -99,13 +101,14 @@ namespace OpenWifi {
|
||||
bool Storage::DeleteDeviceCapabilities(std::string &SerialNumber) {
|
||||
try {
|
||||
Poco::Data::Session Sess = Pool_->get();
|
||||
Sess.begin();
|
||||
Poco::Data::Statement Delete(Sess);
|
||||
|
||||
std::string St{"DELETE FROM Capabilities WHERE SerialNumber=?"};
|
||||
|
||||
Delete << ConvertParams(St), Poco::Data::Keywords::use(SerialNumber);
|
||||
Delete.execute();
|
||||
|
||||
Sess.commit();
|
||||
return true;
|
||||
} catch (const Poco::Exception &E) {
|
||||
poco_warning(Logger(), fmt::format("{}: Failed with: {}", std::string(__func__),
|
||||
|
||||
@@ -105,6 +105,7 @@ namespace OpenWifi {
|
||||
bool Storage::RemoveOldCommands(std::string &SerialNumber, std::string &Command) {
|
||||
try {
|
||||
Poco::Data::Session Sess = Pool_->get();
|
||||
Sess.begin();
|
||||
Poco::Data::Statement Delete(Sess);
|
||||
|
||||
std::string St{
|
||||
@@ -112,8 +113,7 @@ namespace OpenWifi {
|
||||
Delete << ConvertParams(St), Poco::Data::Keywords::use(SerialNumber),
|
||||
Poco::Data::Keywords::use(Command);
|
||||
Delete.execute();
|
||||
Delete.reset(Sess);
|
||||
|
||||
Sess.commit();
|
||||
return true;
|
||||
} catch (const Poco::Exception &E) {
|
||||
Logger().log(E);
|
||||
@@ -146,6 +146,7 @@ namespace OpenWifi {
|
||||
RemoveOldCommands(SerialNumber, Command.Command);
|
||||
|
||||
Poco::Data::Session Sess = Pool_->get();
|
||||
Sess.begin();
|
||||
Poco::Data::Statement Insert(Sess);
|
||||
|
||||
std::string St{"INSERT INTO CommandList ( " + DB_Command_SelectFields + " ) VALUES( " +
|
||||
@@ -156,7 +157,7 @@ namespace OpenWifi {
|
||||
|
||||
Insert << ConvertParams(St), Poco::Data::Keywords::use(R);
|
||||
Insert.execute();
|
||||
|
||||
Sess.commit();
|
||||
return true;
|
||||
|
||||
} catch (const Poco::Exception &E) {
|
||||
@@ -215,6 +216,7 @@ namespace OpenWifi {
|
||||
bool Storage::DeleteCommands(std::string &SerialNumber, uint64_t FromDate, uint64_t ToDate) {
|
||||
try {
|
||||
Poco::Data::Session Sess = Pool_->get();
|
||||
Sess.begin();
|
||||
Poco::Data::Statement Delete(Sess);
|
||||
|
||||
bool DatesIncluded = (FromDate != 0 || ToDate != 0);
|
||||
@@ -237,8 +239,7 @@ namespace OpenWifi {
|
||||
|
||||
Delete << IntroStatement + DateSelector;
|
||||
Delete.execute();
|
||||
Delete.reset(Sess);
|
||||
|
||||
Sess.commit();
|
||||
return true;
|
||||
} catch (const Poco::Exception &E) {
|
||||
Logger().log(E);
|
||||
@@ -274,7 +275,6 @@ namespace OpenWifi {
|
||||
if (Records.size() < HowMany)
|
||||
Done = true;
|
||||
}
|
||||
Select.reset(Sess);
|
||||
return true;
|
||||
} catch (const Poco::Exception &E) {
|
||||
Logger().log(E);
|
||||
@@ -286,6 +286,7 @@ namespace OpenWifi {
|
||||
|
||||
try {
|
||||
Poco::Data::Session Sess = Pool_->get();
|
||||
Sess.begin();
|
||||
Poco::Data::Statement Update(Sess);
|
||||
|
||||
std::string St{"UPDATE CommandList SET Status=?, Executed=?, Completed=?, "
|
||||
@@ -299,7 +300,7 @@ namespace OpenWifi {
|
||||
Poco::Data::Keywords::use(Command.ErrorCode), Poco::Data::Keywords::use(UUID);
|
||||
|
||||
Update.execute();
|
||||
|
||||
Sess.commit();
|
||||
return true;
|
||||
|
||||
} catch (const Poco::Exception &E) {
|
||||
@@ -311,6 +312,7 @@ namespace OpenWifi {
|
||||
bool Storage::SetCommandExecuted(std::string &CommandUUID) {
|
||||
try {
|
||||
Poco::Data::Session Sess = Pool_->get();
|
||||
Sess.begin();
|
||||
Poco::Data::Statement Update(Sess);
|
||||
|
||||
auto Now = Utils::Now();
|
||||
@@ -321,6 +323,7 @@ namespace OpenWifi {
|
||||
Update << ConvertParams(St), Poco::Data::Keywords::use(Now),
|
||||
Poco::Data::Keywords::use(Status), Poco::Data::Keywords::use(CommandUUID);
|
||||
Update.execute();
|
||||
Sess.commit();
|
||||
return true;
|
||||
} catch (const Poco::Exception &E) {
|
||||
Logger().log(E);
|
||||
@@ -331,6 +334,7 @@ namespace OpenWifi {
|
||||
void Storage::RemovedExpiredCommands() {
|
||||
try {
|
||||
Poco::Data::Session Sess = Pool_->get();
|
||||
Sess.begin();
|
||||
Poco::Data::Statement Update(Sess);
|
||||
|
||||
auto Now = Utils::Now(), Window = Now - CommandManager()->CommandTimeout();
|
||||
@@ -341,8 +345,7 @@ namespace OpenWifi {
|
||||
Update << ConvertParams(St), Poco::Data::Keywords::use(Now),
|
||||
Poco::Data::Keywords::use(Status), Poco::Data::Keywords::use(Window);
|
||||
Update.execute();
|
||||
Update.reset(Sess);
|
||||
|
||||
Sess.commit();
|
||||
} catch (const Poco::Exception &E) {
|
||||
Logger().log(E);
|
||||
}
|
||||
@@ -351,6 +354,7 @@ namespace OpenWifi {
|
||||
bool Storage::SetCommandLastTry(std::string &CommandUUID) {
|
||||
try {
|
||||
Poco::Data::Session Sess = Pool_->get();
|
||||
Sess.begin();
|
||||
Poco::Data::Statement Update(Sess);
|
||||
|
||||
auto Now = Utils::Now();
|
||||
@@ -359,6 +363,7 @@ namespace OpenWifi {
|
||||
Update << ConvertParams(St), Poco::Data::Keywords::use(Now),
|
||||
Poco::Data::Keywords::use(CommandUUID);
|
||||
Update.execute();
|
||||
Sess.commit();
|
||||
return true;
|
||||
} catch (const Poco::Exception &E) {
|
||||
Logger().log(E);
|
||||
@@ -369,6 +374,7 @@ namespace OpenWifi {
|
||||
void Storage::RemoveTimedOutCommands() {
|
||||
try {
|
||||
Poco::Data::Session Sess = Pool_->get();
|
||||
Sess.begin();
|
||||
Poco::Data::Statement Update(Sess);
|
||||
|
||||
auto Now = Utils::Now(), Window = Now - CommandManager()->CommandTimeout();
|
||||
@@ -377,7 +383,7 @@ namespace OpenWifi {
|
||||
Update << ConvertParams(St), Poco::Data::Keywords::use(Now),
|
||||
Poco::Data::Keywords::use(Window);
|
||||
Update.execute();
|
||||
Update.reset(Sess);
|
||||
Sess.commit();
|
||||
} catch (const Poco::Exception &E) {
|
||||
Logger().log(E);
|
||||
}
|
||||
@@ -386,6 +392,7 @@ namespace OpenWifi {
|
||||
bool Storage::SetCommandTimedOut(std::string &CommandUUID) {
|
||||
try {
|
||||
Poco::Data::Session Sess = Pool_->get();
|
||||
Sess.begin();
|
||||
Poco::Data::Statement Update(Sess);
|
||||
|
||||
auto Now = Utils::Now();
|
||||
@@ -395,6 +402,7 @@ namespace OpenWifi {
|
||||
Update << ConvertParams(St), Poco::Data::Keywords::use(Now),
|
||||
Poco::Data::Keywords::use(Status), Poco::Data::Keywords::use(CommandUUID);
|
||||
Update.execute();
|
||||
Sess.commit();
|
||||
return true;
|
||||
} catch (const Poco::Exception &E) {
|
||||
Logger().log(E);
|
||||
@@ -425,6 +433,7 @@ namespace OpenWifi {
|
||||
bool Storage::DeleteCommand(std::string &UUID) {
|
||||
try {
|
||||
Poco::Data::Session Sess = Pool_->get();
|
||||
Sess.begin();
|
||||
Poco::Data::Statement Delete(Sess);
|
||||
|
||||
std::string St{"DELETE FROM CommandList WHERE UUID=?"};
|
||||
@@ -435,8 +444,7 @@ namespace OpenWifi {
|
||||
St = "DELETE FROM FileUploads WHERE UUID=?";
|
||||
Delete << ConvertParams(St), Poco::Data::Keywords::use(UUID);
|
||||
Delete.execute();
|
||||
Delete.reset(Sess);
|
||||
|
||||
Sess.commit();
|
||||
return true;
|
||||
} catch (const Poco::Exception &E) {
|
||||
Logger().log(E);
|
||||
@@ -510,6 +518,7 @@ namespace OpenWifi {
|
||||
auto Now = Utils::Now();
|
||||
|
||||
Poco::Data::Session Sess = Pool_->get();
|
||||
Sess.begin();
|
||||
Poco::Data::Statement Update(Sess);
|
||||
|
||||
std::string St{"UPDATE CommandList SET Executed=? WHERE UUID=?"};
|
||||
@@ -518,7 +527,7 @@ namespace OpenWifi {
|
||||
Poco::Data::Keywords::use(UUID);
|
||||
|
||||
Update.execute();
|
||||
|
||||
Sess.commit();
|
||||
return true;
|
||||
} catch (const Poco::Exception &E) {
|
||||
Logger().log(E);
|
||||
@@ -555,6 +564,7 @@ namespace OpenWifi {
|
||||
}
|
||||
|
||||
Poco::Data::Session Sess = Pool_->get();
|
||||
Sess.begin();
|
||||
Poco::Data::Statement Update(Sess);
|
||||
|
||||
auto Status = to_string(Storage::CommandExecutionType::COMMAND_COMPLETED);
|
||||
@@ -566,6 +576,7 @@ namespace OpenWifi {
|
||||
Poco::Data::Keywords::use(ResultStr), Poco::Data::Keywords::use(Status),
|
||||
Poco::Data::Keywords::use(tET), Poco::Data::Keywords::use(UUID);
|
||||
Update.execute();
|
||||
Sess.commit();
|
||||
return true;
|
||||
} catch (const Poco::Exception &E) {
|
||||
Logger().log(E);
|
||||
@@ -603,6 +614,7 @@ namespace OpenWifi {
|
||||
bool Storage::CancelWaitFile(std::string &UUID, std::string &ErrorText) {
|
||||
try {
|
||||
Poco::Data::Session Sess = Pool_->get();
|
||||
Sess.begin();
|
||||
auto Now = Utils::Now();
|
||||
uint64_t Size = 0, WaitForFile = 0;
|
||||
|
||||
@@ -616,6 +628,7 @@ namespace OpenWifi {
|
||||
Poco::Data::Keywords::use(ErrorText), Poco::Data::Keywords::use(Now),
|
||||
Poco::Data::Keywords::use(UUID);
|
||||
Update.execute();
|
||||
Sess.commit();
|
||||
return true;
|
||||
} catch (const Poco::Exception &E) {
|
||||
Logger().log(E);
|
||||
@@ -631,19 +644,6 @@ namespace OpenWifi {
|
||||
uint64_t Size = FileContent.str().size();
|
||||
|
||||
Poco::Data::Session Sess = Pool_->get();
|
||||
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();
|
||||
|
||||
if (Size < FileUploader()->MaxSize()) {
|
||||
|
||||
@@ -651,7 +651,7 @@ namespace OpenWifi {
|
||||
|
||||
TheBlob.appendRaw((const unsigned char *)FileContent.str().c_str(),
|
||||
FileContent.str().size());
|
||||
|
||||
Sess.begin();
|
||||
Poco::Data::Statement Insert(Sess);
|
||||
std::string FileType{Type};
|
||||
|
||||
@@ -662,10 +662,27 @@ namespace OpenWifi {
|
||||
Poco::Data::Keywords::use(FileType), Poco::Data::Keywords::use(Now),
|
||||
Poco::Data::Keywords::use(TheBlob);
|
||||
Insert.execute();
|
||||
return true;
|
||||
Sess.commit();
|
||||
} else {
|
||||
poco_warning(Logger(), fmt::format("File {} is too large.", UUID));
|
||||
poco_warning(Logger(),
|
||||
fmt::format("File {} is too large ({} >= {} max bytes).",
|
||||
UUID, Size, FileUploader()->MaxSize()));
|
||||
}
|
||||
|
||||
// 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();
|
||||
|
||||
return true;
|
||||
} catch (const Poco::Exception &E) {
|
||||
Logger().log(E);
|
||||
}
|
||||
@@ -673,7 +690,7 @@ namespace OpenWifi {
|
||||
}
|
||||
|
||||
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 {
|
||||
Poco::Data::BLOB L;
|
||||
/*
|
||||
@@ -686,10 +703,10 @@ namespace OpenWifi {
|
||||
Poco::Data::Statement Select1(Sess);
|
||||
|
||||
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;
|
||||
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();
|
||||
|
||||
if (TmpSerialNumber != SerialNumber) {
|
||||
@@ -712,6 +729,7 @@ namespace OpenWifi {
|
||||
bool Storage::SetCommandResult(std::string &UUID, std::string &Result) {
|
||||
try {
|
||||
Poco::Data::Session Sess = Pool_->get();
|
||||
Sess.begin();
|
||||
Poco::Data::Statement Update(Sess);
|
||||
|
||||
auto Now = Utils::Now();
|
||||
@@ -722,6 +740,7 @@ namespace OpenWifi {
|
||||
Poco::Data::Keywords::use(Result), Poco::Data::Keywords::use(Status),
|
||||
Poco::Data::Keywords::use(UUID);
|
||||
Update.execute();
|
||||
Sess.commit();
|
||||
return true;
|
||||
|
||||
} catch (const Poco::Exception &E) {
|
||||
@@ -733,13 +752,14 @@ namespace OpenWifi {
|
||||
bool Storage::RemoveAttachedFile(std::string &UUID) {
|
||||
try {
|
||||
Poco::Data::Session Sess = Pool_->get();
|
||||
Sess.begin();
|
||||
Poco::Data::Statement Delete(Sess);
|
||||
|
||||
std::string St{"DELETE FROM FileUploads WHERE UUID=?"};
|
||||
|
||||
Delete << ConvertParams(St), Poco::Data::Keywords::use(UUID);
|
||||
Delete.execute();
|
||||
|
||||
Sess.commit();
|
||||
return true;
|
||||
|
||||
} catch (const Poco::Exception &E) {
|
||||
@@ -751,11 +771,13 @@ namespace OpenWifi {
|
||||
bool Storage::RemoveUploadedFilesRecordsOlderThan(uint64_t Date) {
|
||||
try {
|
||||
Poco::Data::Session Sess = Pool_->get();
|
||||
Sess.begin();
|
||||
Poco::Data::Statement Delete(Sess);
|
||||
|
||||
std::string St1{"delete from FileUploads where Created<?"};
|
||||
Delete << ConvertParams(St1), Poco::Data::Keywords::use(Date);
|
||||
Delete.execute();
|
||||
Sess.commit();
|
||||
return true;
|
||||
} catch (const Poco::Exception &E) {
|
||||
Logger().log(E);
|
||||
@@ -766,11 +788,13 @@ namespace OpenWifi {
|
||||
bool Storage::RemoveCommandListRecordsOlderThan(uint64_t Date) {
|
||||
try {
|
||||
Poco::Data::Session Sess = Pool_->get();
|
||||
Sess.begin();
|
||||
Poco::Data::Statement Delete(Sess);
|
||||
|
||||
std::string St1{"delete from CommandList where Submitted<?"};
|
||||
Delete << ConvertParams(St1), Poco::Data::Keywords::use(Date);
|
||||
Delete.execute();
|
||||
Sess.commit();
|
||||
return true;
|
||||
} catch (const Poco::Exception &E) {
|
||||
Logger().log(E);
|
||||
@@ -802,4 +826,4 @@ namespace OpenWifi {
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace OpenWifi
|
||||
} // namespace OpenWifi
|
||||
|
||||
@@ -82,6 +82,7 @@ namespace OpenWifi {
|
||||
if (!TmpName.empty())
|
||||
return false;
|
||||
|
||||
Sess.begin();
|
||||
Poco::Data::Statement Insert(Sess);
|
||||
|
||||
std::string St2{"INSERT INTO DefaultFirmwares ( " + DB_DefFirmware_SelectFields +
|
||||
@@ -94,6 +95,7 @@ namespace OpenWifi {
|
||||
Insert << ConvertParams(St2),
|
||||
Poco::Data::Keywords::use(R);
|
||||
Insert.execute();
|
||||
Sess.commit();
|
||||
return true;
|
||||
|
||||
} catch (const Poco::Exception &E) {
|
||||
@@ -107,6 +109,7 @@ namespace OpenWifi {
|
||||
try {
|
||||
|
||||
Poco::Data::Session Sess = Pool_->get();
|
||||
Sess.begin();
|
||||
Poco::Data::Statement Delete(Sess);
|
||||
Poco::toLowerInPlace(deviceType);
|
||||
|
||||
@@ -114,7 +117,7 @@ namespace OpenWifi {
|
||||
|
||||
Delete << ConvertParams(St), Poco::Data::Keywords::use(deviceType);
|
||||
Delete.execute();
|
||||
|
||||
Sess.commit();
|
||||
return true;
|
||||
} catch (const Poco::Exception &E) {
|
||||
poco_warning(Logger(), fmt::format("{}: Failed with: {}", std::string(__func__),
|
||||
@@ -125,9 +128,9 @@ namespace OpenWifi {
|
||||
|
||||
bool Storage::UpdateDefaultFirmware(GWObjects::DefaultFirmware &DefFirmware) {
|
||||
try {
|
||||
uint64_t Now = Utils::Now();
|
||||
Poco::Data::Session Sess = Pool_->get();
|
||||
|
||||
uint64_t Now = time(nullptr);
|
||||
Sess.begin();
|
||||
Poco::Data::Statement Update(Sess);
|
||||
DefFirmware.LastModified = Now;
|
||||
Poco::toLowerInPlace(DefFirmware.deviceType);
|
||||
@@ -143,7 +146,7 @@ namespace OpenWifi {
|
||||
Poco::Data::Keywords::use(R),
|
||||
Poco::Data::Keywords::use(DefFirmware.deviceType);
|
||||
Update.execute();
|
||||
|
||||
Sess.commit();
|
||||
return true;
|
||||
} catch (const Poco::Exception &E) {
|
||||
poco_warning(Logger(), fmt::format("{}: Failed with: {}", std::string(__func__),
|
||||
|
||||
@@ -19,37 +19,39 @@ namespace OpenWifi {
|
||||
"Models TEXT, "
|
||||
"Description TEXT, "
|
||||
"Created BIGINT , "
|
||||
"LastModified BIGINT)"};
|
||||
"LastModified BIGINT, Platform TEXT )"};
|
||||
|
||||
const static std::string DB_DefConfig_SelectFields{"Name, "
|
||||
"Configuration, "
|
||||
"Models, "
|
||||
"Description, "
|
||||
"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;
|
||||
typedef std::vector<DefConfigRecordTuple> DefConfigRecordList;
|
||||
|
||||
void Convert(const DefConfigRecordTuple &R, GWObjects::DefaultConfiguration &T) {
|
||||
T.Name = R.get<0>();
|
||||
T.Configuration = R.get<1>();
|
||||
T.Models = RESTAPI_utils::to_object_array(R.get<2>());
|
||||
T.Description = R.get<3>();
|
||||
T.Created = R.get<4>();
|
||||
T.LastModified = R.get<5>();
|
||||
T.name = R.get<0>();
|
||||
T.configuration = R.get<1>();
|
||||
T.models = RESTAPI_utils::to_object_array(R.get<2>());
|
||||
T.description = R.get<3>();
|
||||
T.created = R.get<4>();
|
||||
T.lastModified = R.get<5>();
|
||||
T.platform = R.get<6>();
|
||||
}
|
||||
|
||||
void Convert(const GWObjects::DefaultConfiguration &R, DefConfigRecordTuple &T) {
|
||||
T.set<0>(R.Name);
|
||||
T.set<1>(R.Configuration);
|
||||
T.set<2>(RESTAPI_utils::to_string(R.Models));
|
||||
T.set<3>(R.Description);
|
||||
T.set<4>(R.Created);
|
||||
T.set<5>(R.LastModified);
|
||||
T.set<0>(R.name);
|
||||
T.set<1>(R.configuration);
|
||||
T.set<2>(RESTAPI_utils::to_string(R.models));
|
||||
T.set<3>(R.description);
|
||||
T.set<4>(R.created);
|
||||
T.set<5>(R.lastModified);
|
||||
T.set<6>(R.platform);
|
||||
}
|
||||
|
||||
bool Storage::CreateDefaultConfiguration(std::string &Name,
|
||||
@@ -69,9 +71,10 @@ namespace OpenWifi {
|
||||
if (!TmpName.empty())
|
||||
return false;
|
||||
|
||||
Config::Config Cfg(DefConfig.Configuration);
|
||||
Config::Config Cfg(DefConfig.configuration);
|
||||
|
||||
if (Cfg.Valid()) {
|
||||
Sess.begin();
|
||||
Poco::Data::Statement Insert(Sess);
|
||||
|
||||
std::string St{"INSERT INTO DefaultConfigs ( " + DB_DefConfig_SelectFields +
|
||||
@@ -83,6 +86,7 @@ namespace OpenWifi {
|
||||
Convert(DefConfig, R);
|
||||
Insert << ConvertParams(St), Poco::Data::Keywords::use(R);
|
||||
Insert.execute();
|
||||
Sess.commit();
|
||||
return true;
|
||||
} else {
|
||||
poco_warning(Logger(), "Cannot create device: invalid configuration.");
|
||||
@@ -99,13 +103,14 @@ namespace OpenWifi {
|
||||
try {
|
||||
|
||||
Poco::Data::Session Sess = Pool_->get();
|
||||
Sess.begin();
|
||||
Poco::Data::Statement Delete(Sess);
|
||||
|
||||
std::string St{"DELETE FROM DefaultConfigs WHERE Name=?"};
|
||||
|
||||
Delete << ConvertParams(St), Poco::Data::Keywords::use(Name);
|
||||
Delete.execute();
|
||||
|
||||
Sess.commit();
|
||||
return true;
|
||||
} catch (const Poco::Exception &E) {
|
||||
poco_warning(Logger(), fmt::format("{}: Failed with: {}", std::string(__func__),
|
||||
@@ -117,14 +122,14 @@ namespace OpenWifi {
|
||||
bool Storage::UpdateDefaultConfiguration(std::string &Name,
|
||||
GWObjects::DefaultConfiguration &DefConfig) {
|
||||
try {
|
||||
uint64_t Now = Utils::Now();
|
||||
Poco::Data::Session Sess = Pool_->get();
|
||||
|
||||
uint64_t Now = time(nullptr);
|
||||
Sess.begin();
|
||||
Poco::Data::Statement Update(Sess);
|
||||
DefConfig.LastModified = Now;
|
||||
DefConfig.lastModified = Now;
|
||||
|
||||
std::string St{"UPDATE DefaultConfigs SET Name=?, Configuration=?, Models=?, "
|
||||
"Description=?, Created=? , LastModified=? WHERE Name=?"};
|
||||
"Description=?, Created=? , LastModified=? , Platform=? WHERE Name=?"};
|
||||
|
||||
DefConfigRecordTuple R;
|
||||
Convert(DefConfig, R);
|
||||
@@ -132,6 +137,7 @@ namespace OpenWifi {
|
||||
Update << ConvertParams(St), Poco::Data::Keywords::use(R),
|
||||
Poco::Data::Keywords::use(Name);
|
||||
Update.execute();
|
||||
Sess.commit();
|
||||
return true;
|
||||
} catch (const Poco::Exception &E) {
|
||||
poco_warning(Logger(), fmt::format("{}: Failed with: {}", std::string(__func__),
|
||||
@@ -215,31 +221,30 @@ namespace OpenWifi {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Storage::FindDefaultConfigurationForModel(const std::string &Model,
|
||||
GWObjects::DefaultConfiguration &DefConfig) {
|
||||
bool Storage::FindDefaultConfigurationForModel(const std::string &DeviceModel, const std::string &Platform,
|
||||
GWObjects::DefaultConfiguration &Config) {
|
||||
try {
|
||||
DefConfigRecordList Records;
|
||||
DefConfigRecordList DefConfigs;
|
||||
|
||||
Poco::Data::Session Sess = Pool_->get();
|
||||
Poco::Data::Statement Select(Sess);
|
||||
|
||||
Select << "SELECT " + DB_DefConfig_SelectFields + " FROM DefaultConfigs",
|
||||
Poco::Data::Keywords::into(Records);
|
||||
Poco::Data::Keywords::into(DefConfigs);
|
||||
Select.execute();
|
||||
|
||||
for (const auto &i : Records) {
|
||||
GWObjects::DefaultConfiguration Config;
|
||||
Convert(i, Config);
|
||||
for (const auto &j : Config.Models) {
|
||||
if (j == "*" || j == Model) {
|
||||
DefConfig = Config;
|
||||
for (const auto &DefConfig : DefConfigs) {
|
||||
GWObjects::DefaultConfiguration C;
|
||||
Convert(DefConfig, C);
|
||||
for (const auto &Model : C.models) {
|
||||
if ((Model == "*" || Model == DeviceModel) && (Config.platform == Platform)){
|
||||
Config = C;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
Logger().information(
|
||||
fmt::format("AUTO-PROVISIONING: no default configuration for model:{}", Model));
|
||||
return false;
|
||||
fmt::format("AUTO-PROVISIONING: no default configuration for model:{}", DeviceModel));
|
||||
} catch (const Poco::Exception &E) {
|
||||
poco_warning(Logger(), fmt::format("{}: Failed with: {}", std::string(__func__),
|
||||
E.displayText()));
|
||||
|
||||
@@ -172,14 +172,18 @@ namespace OpenWifi {
|
||||
R.set<30>(D.connectReason);
|
||||
}
|
||||
|
||||
bool Storage::GetDeviceCount(uint64_t &Count) {
|
||||
bool Storage::GetDeviceCount(uint64_t &Count, const std::string &platform) {
|
||||
try {
|
||||
Poco::Data::Session Sess = Pool_->get();
|
||||
Poco::Data::Statement Select(Sess);
|
||||
|
||||
std::string st{"SELECT COUNT(*) FROM Devices"};
|
||||
|
||||
Select << st, Poco::Data::Keywords::into(Count);
|
||||
if(!platform.empty()) {
|
||||
std::string st{"SELECT COUNT(*) FROM Devices WHERE DeviceType='" + platform + "'"};
|
||||
Select << st, Poco::Data::Keywords::into(Count);
|
||||
} else {
|
||||
std::string st{"SELECT COUNT(*) FROM Devices"};
|
||||
Select << st, Poco::Data::Keywords::into(Count);
|
||||
}
|
||||
Select.execute();
|
||||
return true;
|
||||
} catch (const Poco::Exception &E) {
|
||||
@@ -190,16 +194,36 @@ namespace OpenWifi {
|
||||
|
||||
bool Storage::GetDeviceSerialNumbers(uint64_t From, uint64_t HowMany,
|
||||
std::vector<std::string> &SerialNumbers,
|
||||
const std::string &orderBy) {
|
||||
const std::string &orderBy,
|
||||
const std::string &platform, bool includeProvisioned) {
|
||||
try {
|
||||
Poco::Data::Session Sess = Pool_->get();
|
||||
Poco::Data::Statement Select(Sess);
|
||||
|
||||
std::string st;
|
||||
std::string whereClause = "";
|
||||
if (!platform.empty()) {
|
||||
if (includeProvisioned == false) {
|
||||
//whereClause = fmt::format("WHERE entity='' and venue='' and DeviceType='" + platform + "'");
|
||||
whereClause = fmt::format("WHERE entity='' and venue='' and DeviceType='{}'", platform);
|
||||
} else {
|
||||
//whereClause = fmt::format("WHERE DeviceType='" + platform + "'");
|
||||
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())
|
||||
st = "SELECT SerialNumber From Devices ORDER BY SerialNumber ASC ";
|
||||
st += " ORDER BY SerialNumber ASC ";
|
||||
else
|
||||
st = "SELECT SerialNumber From Devices " + orderBy;
|
||||
st += orderBy;
|
||||
|
||||
Select << st + ComputeRange(From, HowMany), Poco::Data::Keywords::into(SerialNumbers);
|
||||
Select.execute();
|
||||
@@ -210,7 +234,7 @@ namespace OpenWifi {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Storage::UpdateDeviceConfiguration(std::string &SerialNumber, std::string &Configuration,
|
||||
/* bool Storage::UpdateDeviceConfiguration(std::string &SerialNumber, std::string &Configuration,
|
||||
uint64_t &NewUUID) {
|
||||
try {
|
||||
|
||||
@@ -255,7 +279,7 @@ namespace OpenWifi {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
*/
|
||||
bool Storage::RollbackDeviceConfigurationChange(std::string & SerialNumber) {
|
||||
try {
|
||||
GWObjects::Device D;
|
||||
@@ -265,9 +289,10 @@ namespace OpenWifi {
|
||||
D.pendingUUID = 0;
|
||||
D.LastConfigurationChange = Utils::Now();
|
||||
|
||||
ConfigurationCache().Add(Utils::SerialNumberToInt(SerialNumber), D.UUID);
|
||||
SetCurrentConfigurationID(Utils::SerialNumberToInt(SerialNumber), D.UUID);
|
||||
|
||||
Poco::Data::Session Sess = Pool_->get();
|
||||
Sess.begin();
|
||||
Poco::Data::Statement Update(Sess);
|
||||
|
||||
DeviceRecordTuple R;
|
||||
@@ -277,6 +302,7 @@ namespace OpenWifi {
|
||||
Update << ConvertParams(St2), Poco::Data::Keywords::use(R),
|
||||
Poco::Data::Keywords::use(SerialNumber);
|
||||
Update.execute();
|
||||
Sess.commit();
|
||||
return true;
|
||||
} catch (const Poco::Exception &E) {
|
||||
Logger().log(E);
|
||||
@@ -286,22 +312,43 @@ namespace OpenWifi {
|
||||
|
||||
bool Storage::CompleteDeviceConfigurationChange(std::string & SerialNumber) {
|
||||
try {
|
||||
auto Session = Pool_->get();
|
||||
return CompleteDeviceConfigurationChange(Session, SerialNumber);
|
||||
} catch (const Poco::Exception &E) {
|
||||
Logger().log(E);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Storage::CompleteDeviceConfigurationChange(Poco::Data::Session & Session, std::string & SerialNumber) {
|
||||
try {
|
||||
|
||||
GWObjects::Device D;
|
||||
if (!GetDevice(SerialNumber, D))
|
||||
return false;
|
||||
|
||||
if(D.pendingConfiguration.empty())
|
||||
return true;
|
||||
D.Configuration = D.pendingConfiguration;
|
||||
D.pendingConfiguration.clear();
|
||||
D.UUID = D.pendingUUID;
|
||||
D.pendingUUID = 0;
|
||||
if(!D.pendingConfiguration.empty()) {
|
||||
D.Configuration = D.pendingConfiguration;
|
||||
D.pendingConfiguration.clear();
|
||||
}
|
||||
if(D.pendingUUID!=0) {
|
||||
D.UUID = D.pendingUUID;
|
||||
D.pendingUUID = 0;
|
||||
}
|
||||
|
||||
// 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);
|
||||
|
||||
ConfigurationCache().Add(Utils::SerialNumberToInt(SerialNumber), D.UUID);
|
||||
|
||||
Poco::Data::Session Sess = Pool_->get();
|
||||
Poco::Data::Statement Update(Sess);
|
||||
Session.begin();
|
||||
Poco::Data::Statement Update(Session);
|
||||
|
||||
DeviceRecordTuple R;
|
||||
ConvertDeviceRecord(D, R);
|
||||
@@ -310,6 +357,7 @@ namespace OpenWifi {
|
||||
Update << ConvertParams(St2), Poco::Data::Keywords::use(R),
|
||||
Poco::Data::Keywords::use(SerialNumber);
|
||||
Update.execute();
|
||||
Session.commit();
|
||||
return true;
|
||||
} catch (const Poco::Exception &E) {
|
||||
Logger().log(E);
|
||||
@@ -328,13 +376,12 @@ namespace OpenWifi {
|
||||
return false;
|
||||
}
|
||||
|
||||
Poco::Data::Session Sess = Pool_->get();
|
||||
Poco::Data::Statement Select(Sess);
|
||||
|
||||
GWObjects::Device D;
|
||||
if (!GetDevice(SerialNumber, D))
|
||||
return false;
|
||||
|
||||
|
||||
uint64_t Now = time(nullptr);
|
||||
if(NewUUID==0) {
|
||||
D.pendingUUID = NewUUID = (D.LastConfigurationChange == Now ? Now + 1 : Now);
|
||||
@@ -343,6 +390,8 @@ namespace OpenWifi {
|
||||
}
|
||||
|
||||
if (Cfg.SetUUID(NewUUID)) {
|
||||
Poco::Data::Session Sess = Pool_->get();
|
||||
Sess.begin();
|
||||
Poco::Data::Statement Update(Sess);
|
||||
D.pendingConfiguration = Cfg.get();
|
||||
|
||||
@@ -353,6 +402,7 @@ namespace OpenWifi {
|
||||
Update << ConvertParams(St2), Poco::Data::Keywords::use(R),
|
||||
Poco::Data::Keywords::use(SerialNumber);
|
||||
Update.execute();
|
||||
Sess.commit();
|
||||
poco_information(Logger(),
|
||||
fmt::format("DEVICE-PENDING-CONFIGURATION-UPDATED({}): New UUID is {}",
|
||||
SerialNumber, NewUUID));
|
||||
@@ -366,68 +416,74 @@ namespace OpenWifi {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Storage::SetDeviceLastRecordedContact(std::string &SerialNumber, std::uint64_t lastRecordedContact) {
|
||||
bool Storage::SetDeviceLastRecordedContact(LockedDbSession &Session, std::string &SerialNumber, std::uint64_t lastRecordedContact) {
|
||||
try {
|
||||
Poco::Data::Session Sess = Pool_->get();
|
||||
Poco::Data::Statement Update(Sess);
|
||||
std::string St{"UPDATE Devices SET lastRecordedContact=? WHERE SerialNumber=?"};
|
||||
|
||||
Update << ConvertParams(St), Poco::Data::Keywords::use(lastRecordedContact),
|
||||
Poco::Data::Keywords::use(SerialNumber);
|
||||
Update.execute();
|
||||
return true;
|
||||
|
||||
std::lock_guard Lock(Session.Mutex());
|
||||
return SetDeviceLastRecordedContact(Session.Session(), SerialNumber, lastRecordedContact);
|
||||
} catch (const Poco::Exception &E) {
|
||||
Logger().log(E);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Storage::CreateDevice(GWObjects::Device &DeviceDetails) {
|
||||
bool Storage::SetDeviceLastRecordedContact(Poco::Data::Session &Session, std::string &SerialNumber, std::uint64_t lastRecordedContact) {
|
||||
try {
|
||||
Session.begin();
|
||||
Poco::Data::Statement Update(Session);
|
||||
std::string St{"UPDATE Devices SET lastRecordedContact=? WHERE SerialNumber=?"};
|
||||
|
||||
Update << ConvertParams(St), Poco::Data::Keywords::use(lastRecordedContact),
|
||||
Poco::Data::Keywords::use(SerialNumber);
|
||||
Update.execute();
|
||||
Session.commit();
|
||||
return true;
|
||||
} catch (const Poco::Exception &E) {
|
||||
Logger().log(E);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Storage::SetDeviceLastRecordedContact(std::string &SerialNumber, std::uint64_t lastRecordedContact) {
|
||||
try {
|
||||
auto Session = Pool_->get();
|
||||
return SetDeviceLastRecordedContact(Session, SerialNumber, lastRecordedContact);
|
||||
} catch (const Poco::Exception &E) {
|
||||
Logger().log(E);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Storage::CreateDevice(Poco::Data::Session &Sess, GWObjects::Device &DeviceDetails) {
|
||||
std::string SerialNumber;
|
||||
try {
|
||||
Config::Config Cfg(DeviceDetails.Configuration);
|
||||
uint64_t Now = Utils::Now();
|
||||
|
||||
Poco::Data::Session Sess = Pool_->get();
|
||||
Poco::Data::Statement Select(Sess);
|
||||
DeviceDetails.modified = Utils::Now();
|
||||
DeviceDetails.CreationTimestamp = DeviceDetails.LastConfigurationDownload =
|
||||
DeviceDetails.UUID = DeviceDetails.LastConfigurationChange = Now;
|
||||
|
||||
std::string St{"SELECT SerialNumber FROM Devices WHERE SerialNumber=?"};
|
||||
if (Cfg.Valid() && Cfg.SetUUID(DeviceDetails.UUID)) {
|
||||
|
||||
// Select << ConvertParams(St), Poco::Data::Keywords::into(SerialNumber),
|
||||
// Poco::Data::Keywords::use(DeviceDetails.SerialNumber);
|
||||
// Select.execute();
|
||||
DeviceDetails.Configuration = Cfg.get();
|
||||
Sess.begin();
|
||||
Poco::Data::Statement Insert(Sess);
|
||||
|
||||
// if (Select.rowsExtracted() == 0) {
|
||||
Config::Config Cfg(DeviceDetails.Configuration);
|
||||
uint64_t Now = Utils::Now();
|
||||
std::string St2{"INSERT INTO Devices ( " + DB_DeviceSelectFields + " ) " +
|
||||
DB_DeviceInsertValues + " ON CONFLICT (SerialNumber) DO NOTHING"};
|
||||
|
||||
DeviceDetails.modified = Utils::Now();
|
||||
DeviceDetails.CreationTimestamp = DeviceDetails.LastConfigurationDownload =
|
||||
DeviceDetails.UUID = DeviceDetails.LastConfigurationChange = Now;
|
||||
|
||||
if (Cfg.Valid() && Cfg.SetUUID(DeviceDetails.UUID)) {
|
||||
|
||||
DeviceDetails.Configuration = Cfg.get();
|
||||
Poco::Data::Statement Insert(Sess);
|
||||
|
||||
std::string St2{"INSERT INTO Devices ( " + DB_DeviceSelectFields + " ) " +
|
||||
DB_DeviceInsertValues + " ON CONFLICT (SerialNumber) DO NOTHING"};
|
||||
|
||||
SetCurrentConfigurationID(DeviceDetails.SerialNumber, DeviceDetails.UUID);
|
||||
DeviceRecordTuple R;
|
||||
ConvertDeviceRecord(DeviceDetails, R);
|
||||
Insert << ConvertParams(St2), Poco::Data::Keywords::use(R);
|
||||
Insert.execute();
|
||||
SetCurrentConfigurationID(DeviceDetails.SerialNumber, DeviceDetails.UUID);
|
||||
SerialNumberCache()->AddSerialNumber(DeviceDetails.SerialNumber);
|
||||
return true;
|
||||
} else {
|
||||
poco_warning(Logger(), "Cannot create device: invalid configuration.");
|
||||
return false;
|
||||
}
|
||||
// } else {
|
||||
// poco_warning(Logger(), fmt::format("Device {} already exists.", SerialNumber));
|
||||
// return false;
|
||||
// }
|
||||
SetCurrentConfigurationID(DeviceDetails.SerialNumber, DeviceDetails.UUID);
|
||||
DeviceRecordTuple R;
|
||||
ConvertDeviceRecord(DeviceDetails, R);
|
||||
Insert << ConvertParams(St2), Poco::Data::Keywords::use(R);
|
||||
Insert.execute();
|
||||
Sess.commit();
|
||||
SetCurrentConfigurationID(DeviceDetails.SerialNumber, DeviceDetails.UUID);
|
||||
SerialNumberCache()->AddSerialNumber(DeviceDetails.SerialNumber);
|
||||
} else {
|
||||
poco_warning(Logger(), "Cannot create device: invalid configuration.");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
} catch (const Poco::Exception &E) {
|
||||
Logger().log(E);
|
||||
@@ -435,6 +491,26 @@ namespace OpenWifi {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Storage::CreateDevice(LockedDbSession &Session, GWObjects::Device &DeviceDetails) {
|
||||
try {
|
||||
std::lock_guard Lock(Session.Mutex());
|
||||
return CreateDevice(Session.Session(), DeviceDetails);
|
||||
} catch (const Poco::Exception &E) {
|
||||
Logger().log(E);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Storage::CreateDevice(GWObjects::Device &DeviceDetails) {
|
||||
try {
|
||||
auto Session = Pool_->get();
|
||||
return CreateDevice(Session, DeviceDetails);
|
||||
} catch (const Poco::Exception &E) {
|
||||
Logger().log(E);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static std::string InsertRadiosCountyRegulation(std::string &Config,
|
||||
const Poco::Net::IPAddress &IPAddress) {
|
||||
std::string FoundCountry;
|
||||
@@ -484,19 +560,18 @@ namespace OpenWifi {
|
||||
} catch (const Poco::Exception &E) {
|
||||
Logger().log(E);
|
||||
}
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
#define __DBGLOG__ std::cout << __LINE__ << std::endl;
|
||||
|
||||
bool Storage::CreateDefaultDevice(std::string &SerialNumber, const Config::Capabilities &Caps,
|
||||
bool Storage::CreateDefaultDevice(Poco::Data::Session &Session, std::string &SerialNumber, const Config::Capabilities &Caps,
|
||||
std::string &Firmware,
|
||||
const Poco::Net::IPAddress &IPAddress,
|
||||
bool simulated) {
|
||||
|
||||
GWObjects::Device D;
|
||||
poco_information(Logger(), fmt::format("AUTO-CREATION({})", SerialNumber));
|
||||
uint64_t Now = time(nullptr);
|
||||
|
||||
// poco_information(Logger(), fmt::format("AUTO-CREATION({}): Start.", SerialNumber));
|
||||
uint64_t Now = Utils::Now();
|
||||
GWObjects::DefaultConfiguration DefConfig;
|
||||
|
||||
if (!Caps.Platform().empty() && !Caps.Compatible().empty()) {
|
||||
@@ -517,21 +592,31 @@ namespace OpenWifi {
|
||||
}
|
||||
|
||||
if (!Found && AP_WS_Server()->UseDefaults() &&
|
||||
FindDefaultConfigurationForModel(Caps.Compatible(), DefConfig)) {
|
||||
Config::Config NewConfig(DefConfig.Configuration);
|
||||
FindDefaultConfigurationForModel(Caps.Compatible(), Caps.Platform(), DefConfig)) {
|
||||
Config::Config NewConfig(DefConfig.configuration);
|
||||
NewConfig.SetUUID(Now);
|
||||
D.Configuration = NewConfig.get();
|
||||
} else if (!Found) {
|
||||
Config::Config NewConfig;
|
||||
NewConfig.SetUUID(Now);
|
||||
D.Configuration = NewConfig.get();
|
||||
if(Caps.Platform()==Platforms::AP) {
|
||||
Config::Config NewConfig;
|
||||
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...
|
||||
D.locale = InsertRadiosCountyRegulation(D.Configuration, IPAddress);
|
||||
D.SerialNumber = Poco::toLower(SerialNumber);
|
||||
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.Manufacturer = Caps.Model();
|
||||
D.Firmware = Firmware;
|
||||
@@ -539,12 +624,13 @@ namespace OpenWifi {
|
||||
D.Notes = SecurityObjects::NoteInfoVec{
|
||||
SecurityObjects::NoteInfo{(uint64_t)Utils::Now(), "", "Auto-provisioned."}};
|
||||
|
||||
CreateDeviceCapabilities(SerialNumber, Caps);
|
||||
|
||||
return CreateDevice(D);
|
||||
CreateDeviceCapabilities(Session, SerialNumber, Caps);
|
||||
auto Result = CreateDevice(Session, D);
|
||||
poco_information(Logger(), fmt::format("AUTO-CREATION({}): Done, Result={}", SerialNumber, Result));
|
||||
return Result;
|
||||
}
|
||||
|
||||
bool Storage::GetDeviceFWUpdatePolicy(std::string &SerialNumber, std::string &Policy) {
|
||||
/* bool Storage::GetDeviceFWUpdatePolicy(std::string &SerialNumber, std::string &Policy) {
|
||||
try {
|
||||
Poco::Data::Session Sess = Pool_->get();
|
||||
Poco::Data::Statement Select(Sess);
|
||||
@@ -559,16 +645,19 @@ namespace OpenWifi {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Storage::SetDevicePassword(std::string &SerialNumber, std::string &Password) {
|
||||
*/
|
||||
bool Storage::SetDevicePassword(LockedDbSession &Sess, std::string &SerialNumber, std::string &Password) {
|
||||
try {
|
||||
Poco::Data::Session Sess = Pool_->get();
|
||||
Poco::Data::Statement Update(Sess);
|
||||
std::lock_guard Lock(Sess.Mutex());
|
||||
Sess.Session().begin();
|
||||
|
||||
Poco::Data::Statement Update(Sess.Session());
|
||||
std::string St{"UPDATE Devices SET DevicePassword=? WHERE SerialNumber=?"};
|
||||
|
||||
Update << ConvertParams(St), Poco::Data::Keywords::use(Password),
|
||||
Poco::Data::Keywords::use(SerialNumber);
|
||||
Update.execute();
|
||||
Sess.Session().commit();
|
||||
return true;
|
||||
} catch (const Poco::Exception &E) {
|
||||
Logger().log(E);
|
||||
@@ -576,34 +665,20 @@ namespace OpenWifi {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Storage::SetConnectInfo(std::string &SerialNumber, std::string &Firmware) {
|
||||
std::string Storage::GetPlatform(const std::string &SerialNumber) {
|
||||
try {
|
||||
Poco::Data::Session Sess = Pool_->get();
|
||||
Poco::Data::Statement Select(Sess);
|
||||
|
||||
// Get the old version and if they do not match, set the last date
|
||||
std::string St{"SELECT Firmware FROM Devices WHERE SerialNumber=?"};
|
||||
std::string TmpFirmware;
|
||||
Select << ConvertParams(St), Poco::Data::Keywords::into(TmpFirmware),
|
||||
Poco::Data::Keywords::use(SerialNumber);
|
||||
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();
|
||||
|
||||
if (TmpFirmware != Firmware) {
|
||||
Poco::Data::Statement Update(Sess);
|
||||
std::string St2{
|
||||
"UPDATE Devices SET Firmware=?, LastFWUpdate=? WHERE SerialNumber=?"};
|
||||
uint64_t Now = Utils::Now();
|
||||
|
||||
Update << ConvertParams(St2), Poco::Data::Keywords::use(Firmware),
|
||||
Poco::Data::Keywords::use(Now), Poco::Data::Keywords::use(SerialNumber);
|
||||
Update.execute();
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
return Platform;
|
||||
} catch (const Poco::Exception &E) {
|
||||
Logger().log(E);
|
||||
}
|
||||
return false;
|
||||
return "";
|
||||
}
|
||||
|
||||
bool Storage::DeleteDevice(std::string &SerialNumber) {
|
||||
@@ -614,12 +689,14 @@ namespace OpenWifi {
|
||||
for (const auto &tableName : TableNames) {
|
||||
|
||||
Poco::Data::Session Sess = Pool_->get();
|
||||
Sess.begin();
|
||||
Poco::Data::Statement Delete(Sess);
|
||||
|
||||
std::string St = fmt::format("DELETE FROM {} WHERE SerialNumber='{}'", tableName, SerialNumber);
|
||||
try {
|
||||
Delete << St;
|
||||
Delete.execute();
|
||||
Sess.commit();
|
||||
} catch (...) {
|
||||
}
|
||||
}
|
||||
@@ -692,19 +769,14 @@ namespace OpenWifi {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Storage::GetDevice(std::string &SerialNumber, GWObjects::Device &DeviceDetails) {
|
||||
bool Storage::GetDevice(Poco::Data::Session &Session, const std::string &SerialNumber, GWObjects::Device &DeviceDetails) {
|
||||
try {
|
||||
Poco::Data::Session Sess = Pool_->get();
|
||||
Poco::Data::Statement Select(Sess);
|
||||
|
||||
std::string St{"SELECT " + DB_DeviceSelectFields +
|
||||
" FROM Devices WHERE SerialNumber=?"};
|
||||
Poco::Data::Statement Select(Session);
|
||||
std::string St = fmt::format("SELECT {} FROM Devices WHERE SerialNumber='{}'", DB_DeviceSelectFields, SerialNumber);
|
||||
|
||||
DeviceRecordTuple R;
|
||||
Select << ConvertParams(St), Poco::Data::Keywords::into(R),
|
||||
Poco::Data::Keywords::use(SerialNumber);
|
||||
Select << St, Poco::Data::Keywords::into(R);
|
||||
Select.execute();
|
||||
|
||||
if (Select.rowsExtracted() == 0)
|
||||
return false;
|
||||
ConvertDeviceRecord(R, DeviceDetails);
|
||||
@@ -715,6 +787,26 @@ namespace OpenWifi {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Storage::GetDevice(const std::string &SerialNumber, GWObjects::Device &DeviceDetails) {
|
||||
try {
|
||||
auto Sess = Pool_->get();
|
||||
return GetDevice(Sess, SerialNumber, DeviceDetails);
|
||||
} catch (const Poco::Exception &E) {
|
||||
Logger().log(E);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Storage::GetDevice(LockedDbSession &Session, const std::string &SerialNumber, GWObjects::Device &DeviceDetails) {
|
||||
try {
|
||||
std::lock_guard Lock(Session.Mutex());
|
||||
return GetDevice(Session.Session(), SerialNumber, DeviceDetails);
|
||||
} catch (const Poco::Exception &E) {
|
||||
Logger().log(E);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Storage::DeviceExists(std::string &SerialNumber) {
|
||||
try {
|
||||
Poco::Data::Session Sess = Pool_->get();
|
||||
@@ -741,6 +833,26 @@ namespace OpenWifi {
|
||||
bool Storage::UpdateDevice(GWObjects::Device &NewDeviceDetails) {
|
||||
try {
|
||||
Poco::Data::Session Sess = Pool_->get();
|
||||
return UpdateDevice(Sess, NewDeviceDetails);
|
||||
} catch (const Poco::Exception &E) {
|
||||
Logger().log(E);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Storage::UpdateDevice(LockedDbSession &Session, GWObjects::Device &NewDeviceDetails) {
|
||||
try {
|
||||
std::lock_guard Lock(Session.Mutex());
|
||||
return UpdateDevice(Session.Session(), NewDeviceDetails);
|
||||
} catch (const Poco::Exception &E) {
|
||||
Logger().log(E);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Storage::UpdateDevice(Poco::Data::Session &Sess, GWObjects::Device &NewDeviceDetails) {
|
||||
try {
|
||||
Sess.begin();
|
||||
Poco::Data::Statement Update(Sess);
|
||||
|
||||
DeviceRecordTuple R;
|
||||
@@ -753,6 +865,7 @@ namespace OpenWifi {
|
||||
Update << ConvertParams(St2), Poco::Data::Keywords::use(R),
|
||||
Poco::Data::Keywords::use(NewDeviceDetails.SerialNumber);
|
||||
Update.execute();
|
||||
Sess.commit();
|
||||
// GetDevice(NewDeviceDetails.SerialNumber,NewDeviceDetails);
|
||||
return true;
|
||||
} catch (const Poco::Exception &E) {
|
||||
@@ -762,17 +875,37 @@ namespace OpenWifi {
|
||||
}
|
||||
|
||||
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;
|
||||
try {
|
||||
Poco::Data::Session Sess = Pool_->get();
|
||||
Poco::Data::Statement Select(Sess);
|
||||
|
||||
// std::string st{"SELECT " + DB_DeviceSelectFields + " FROM Devices " + orderBy.empty()
|
||||
// ? " ORDER BY SerialNumber ASC " + ComputeRange(From, HowMany)};
|
||||
std::string st = fmt::format("SELECT {} FROM Devices {} {}", DB_DeviceSelectFields,
|
||||
orderBy.empty() ? " ORDER BY SerialNumber ASC " : orderBy,
|
||||
ComputeRange(From, HowMany));
|
||||
std::string st;
|
||||
std::string whereClause = "";
|
||||
if(platform.empty()) {
|
||||
|
||||
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.execute();
|
||||
@@ -1001,9 +1134,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,
|
||||
Associations_6G);
|
||||
Associations_6G, uptime);
|
||||
UpdateCountedMap(Dashboard.associations, "2G", Associations_2G);
|
||||
UpdateCountedMap(Dashboard.associations, "5G", Associations_5G);
|
||||
UpdateCountedMap(Dashboard.associations, "6G", Associations_6G);
|
||||
@@ -1027,4 +1160,25 @@ namespace OpenWifi {
|
||||
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
|
||||
|
||||
@@ -35,10 +35,11 @@ namespace OpenWifi {
|
||||
R.set<4>(H.Recorded);
|
||||
}
|
||||
|
||||
bool Storage::AddHealthCheckData(const GWObjects::HealthCheck &Check) {
|
||||
bool Storage::AddHealthCheckData(LockedDbSession &Session, const GWObjects::HealthCheck &Check) {
|
||||
try {
|
||||
Poco::Data::Session Sess = Pool_->get();
|
||||
Poco::Data::Statement Insert(Sess);
|
||||
std::lock_guard Guard(Session.Mutex());
|
||||
Session.Session().begin();
|
||||
Poco::Data::Statement Insert(Session.Session());
|
||||
|
||||
std::string St{"INSERT INTO HealthChecks ( " + DB_HealthCheckSelectFields +
|
||||
" ) VALUES( " + DB_HealthCheckInsertValues + " )"};
|
||||
@@ -47,6 +48,7 @@ namespace OpenWifi {
|
||||
ConvertHealthCheckRecord(Check, R);
|
||||
Insert << ConvertParams(St), Poco::Data::Keywords::use(R);
|
||||
Insert.execute();
|
||||
Session.Session().commit();
|
||||
return true;
|
||||
} catch (const Poco::Exception &E) {
|
||||
poco_warning(Logger(), fmt::format("{}: Failed with: {}", std::string(__func__),
|
||||
@@ -134,7 +136,7 @@ namespace OpenWifi {
|
||||
uint64_t ToDate) {
|
||||
try {
|
||||
Poco::Data::Session Sess = Pool_->get();
|
||||
|
||||
Sess.begin();
|
||||
bool DatesIncluded = (FromDate != 0 || ToDate != 0);
|
||||
|
||||
std::string Prefix{"DELETE FROM HealthChecks "};
|
||||
@@ -158,7 +160,7 @@ namespace OpenWifi {
|
||||
Delete << Statement + DateSelector;
|
||||
|
||||
Delete.execute();
|
||||
|
||||
Sess.commit();
|
||||
return true;
|
||||
} catch (const Poco::Exception &E) {
|
||||
poco_warning(Logger(), fmt::format("{}: Failed with: {}", std::string(__func__),
|
||||
@@ -170,11 +172,13 @@ namespace OpenWifi {
|
||||
bool Storage::RemoveHealthChecksRecordsOlderThan(uint64_t Date) {
|
||||
try {
|
||||
Poco::Data::Session Sess = Pool_->get();
|
||||
Sess.begin();
|
||||
Poco::Data::Statement Delete(Sess);
|
||||
|
||||
std::string St1{"delete from HealthChecks where recorded<?"};
|
||||
Delete << ConvertParams(St1), Poco::Data::Keywords::use(Date);
|
||||
Delete.execute();
|
||||
Sess.commit();
|
||||
return true;
|
||||
} catch (const Poco::Exception &E) {
|
||||
poco_warning(Logger(), fmt::format("{}: Failed with: {}", std::string(__func__),
|
||||
|
||||
@@ -39,11 +39,11 @@ namespace OpenWifi {
|
||||
R.set<6>(Log.UUID);
|
||||
}
|
||||
|
||||
bool Storage::AddLog(const GWObjects::DeviceLog &Log) {
|
||||
bool Storage::AddLog(LockedDbSession &Session, const GWObjects::DeviceLog &Log) {
|
||||
try {
|
||||
|
||||
Poco::Data::Session Sess = Pool_->get();
|
||||
Poco::Data::Statement Insert(Sess);
|
||||
std::lock_guard Guard(Session.Mutex());
|
||||
Session.Session().begin();
|
||||
Poco::Data::Statement Insert(Session.Session());
|
||||
|
||||
std::string St{"INSERT INTO DeviceLogs (" + DB_LogsSelectFields + ") values( " +
|
||||
DB_LogsInsertValues + " )"};
|
||||
@@ -53,6 +53,7 @@ namespace OpenWifi {
|
||||
|
||||
Insert << ConvertParams(St), Poco::Data::Keywords::use(R);
|
||||
Insert.execute();
|
||||
Session.Session().commit();
|
||||
return true;
|
||||
} catch (const Poco::Exception &E) {
|
||||
poco_warning(Logger(), fmt::format("{}: Failed with: {}", std::string(__func__),
|
||||
@@ -114,7 +115,7 @@ namespace OpenWifi {
|
||||
uint64_t Type) {
|
||||
try {
|
||||
Poco::Data::Session Sess = Pool_->get();
|
||||
|
||||
Sess.begin();
|
||||
bool DatesIncluded = (FromDate != 0 || ToDate != 0);
|
||||
bool HasWhere = DatesIncluded || !SerialNumber.empty();
|
||||
|
||||
@@ -141,7 +142,7 @@ namespace OpenWifi {
|
||||
Delete << StatementStr + DateSelector + TypeSelector;
|
||||
|
||||
Delete.execute();
|
||||
Delete.reset(Sess);
|
||||
Sess.commit();
|
||||
|
||||
return true;
|
||||
} catch (const Poco::Exception &E) {
|
||||
@@ -183,11 +184,13 @@ namespace OpenWifi {
|
||||
bool Storage::RemoveDeviceLogsRecordsOlderThan(uint64_t Date) {
|
||||
try {
|
||||
Poco::Data::Session Sess = Pool_->get();
|
||||
Sess.begin();
|
||||
Poco::Data::Statement Delete(Sess);
|
||||
|
||||
std::string St1{"delete from DeviceLogs where recorded<?"};
|
||||
Delete << ConvertParams(St1), Poco::Data::Keywords::use(Date);
|
||||
Delete.execute();
|
||||
Sess.commit();
|
||||
return true;
|
||||
} catch (const Poco::Exception &E) {
|
||||
poco_warning(Logger(), fmt::format("{}: Failed with: {}", std::string(__func__),
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
|
||||
#include "AP_WS_Server.h"
|
||||
#include "StorageService.h"
|
||||
|
||||
#include "fmt/format.h"
|
||||
|
||||
namespace OpenWifi {
|
||||
@@ -33,10 +32,10 @@ namespace OpenWifi {
|
||||
R.set<3>(Stats.Recorded);
|
||||
}
|
||||
|
||||
bool Storage::AddStatisticsData(const GWObjects::Statistics &Stats) {
|
||||
bool Storage::AddStatisticsData(Poco::Data::Session &Session, const GWObjects::Statistics &Stats) {
|
||||
try {
|
||||
Poco::Data::Session Sess(Pool_->get());
|
||||
Poco::Data::Statement Insert(Sess);
|
||||
Session.begin();
|
||||
Poco::Data::Statement Insert(Session);
|
||||
|
||||
poco_trace(Logger(), fmt::format("{}: Adding stats. Size={}", Stats.SerialNumber,
|
||||
std::to_string(Stats.Data.size())));
|
||||
@@ -46,6 +45,7 @@ namespace OpenWifi {
|
||||
ConvertStatsRecord(Stats, R);
|
||||
Insert << ConvertParams(St), Poco::Data::Keywords::use(R);
|
||||
Insert.execute();
|
||||
Session.commit();
|
||||
return true;
|
||||
} catch (const Poco::Exception &E) {
|
||||
poco_warning(Logger(), fmt::format("{}: Failed with: {}", std::string(__func__),
|
||||
@@ -167,7 +167,7 @@ namespace OpenWifi {
|
||||
uint64_t ToDate) {
|
||||
try {
|
||||
Poco::Data::Session Sess = Pool_->get();
|
||||
|
||||
Sess.begin();
|
||||
bool DatesIncluded = (FromDate != 0 || ToDate != 0);
|
||||
|
||||
std::string Prefix{"DELETE FROM Statistics "};
|
||||
@@ -189,7 +189,7 @@ namespace OpenWifi {
|
||||
Poco::Data::Statement Select(Sess);
|
||||
Select << Statement + DateSelector;
|
||||
Select.execute();
|
||||
|
||||
Sess.commit();
|
||||
return true;
|
||||
} catch (const Poco::Exception &E) {
|
||||
poco_warning(Logger(), (fmt::format("{}: Failed with: {}", std::string(__func__),
|
||||
|
||||
@@ -49,8 +49,7 @@ namespace OpenWifi {
|
||||
"Data TEXT, "
|
||||
"Recorded BIGINT, "
|
||||
"INDEX StatSerial0 (SerialNumber)), ",
|
||||
"INDEX StatSerial (SerialNumber ASC, Recorded ASC))",
|
||||
Poco::Data::Keywords::now;
|
||||
"INDEX StatSerial (SerialNumber ASC, Recorded ASC))", Poco::Data::Keywords::now;
|
||||
}
|
||||
return 0;
|
||||
} catch (const Poco::Exception &E) {
|
||||
@@ -154,8 +153,7 @@ namespace OpenWifi {
|
||||
"alter table devices add column lastRecordedContact bigint",
|
||||
"alter table devices add column simulated boolean",
|
||||
"alter table devices add column certificateExpiryDate bigint",
|
||||
"alter table devices add column connectReason TEXT"
|
||||
};
|
||||
"alter table devices add column connectReason TEXT"};
|
||||
|
||||
for (const auto &i : Script) {
|
||||
try {
|
||||
@@ -275,9 +273,19 @@ namespace OpenWifi {
|
||||
"Models TEXT, "
|
||||
"Description TEXT, "
|
||||
"Created BIGINT , "
|
||||
"LastModified BIGINT)",
|
||||
"LastModified BIGINT, Platform TEXT)",
|
||||
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;
|
||||
} catch (const Poco::Exception &E) {
|
||||
Logger().log(E);
|
||||
|
||||
Reference in New Issue
Block a user