mirror of
https://github.com/Telecominfraproject/wlan-cloud-ucentralgw.git
synced 2025-11-01 19:28:01 +00:00
Compare commits
534 Commits
v2.10.0-RC
...
kv3.0.13
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
de3682d7ba | ||
|
|
5fcc12b3ed | ||
|
|
0795e046fe | ||
|
|
8392b4bbc1 | ||
|
|
5727432d1b | ||
|
|
addd6ed346 | ||
|
|
3ee2adf03c | ||
|
|
1b915e988f | ||
|
|
084cfb78dd | ||
|
|
996cdba49d | ||
|
|
d211222052 | ||
|
|
b92d0ff308 | ||
|
|
843e7039b3 | ||
|
|
e9e0a6845d | ||
|
|
3e255f3257 | ||
|
|
b75a1aa923 | ||
|
|
2333cc7a40 | ||
|
|
d67e0c573e | ||
|
|
75d89d263d | ||
|
|
30a9eb1f68 | ||
|
|
5b5d609d6b | ||
|
|
d7c79f4eaf | ||
|
|
e97e13d1b1 | ||
|
|
9d7f4da504 | ||
|
|
a3b6e7c315 | ||
|
|
451680cd5a | ||
|
|
7be48c3cfc | ||
|
|
dcfb9b0b03 | ||
|
|
5a378a2332 | ||
|
|
6d9315a0a8 | ||
|
|
660dada3d7 | ||
|
|
20cbf1837a | ||
|
|
483edf9cda | ||
|
|
3fb78edb01 | ||
|
|
0920d4ace2 | ||
|
|
d66325fc35 | ||
|
|
4f7e39b33c | ||
|
|
7fd0655d22 | ||
|
|
5b02f509b6 | ||
|
|
537ed0c05b | ||
|
|
765210bb1d | ||
|
|
0bf2cc3d8b | ||
|
|
e359711ee3 | ||
|
|
b03f1a0ea6 | ||
|
|
4049e43079 | ||
|
|
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 | ||
|
|
7d8e15bf66 | ||
|
|
3f60c5abc6 | ||
|
|
d85fb32af9 | ||
|
|
030991f13c | ||
|
|
142541180f | ||
|
|
9bd48bf029 | ||
|
|
8581048528 | ||
|
|
6cfb0ae975 | ||
|
|
45561de44b | ||
|
|
2fccfd756e | ||
|
|
df42837a76 | ||
|
|
4bc1ac1aef | ||
|
|
77ee9d48d0 | ||
|
|
7154cca4b9 | ||
|
|
77732bdb95 | ||
|
|
7a8a05d77d | ||
|
|
aa2c28355b | ||
|
|
b6cb5d003b | ||
|
|
c93acdf54a | ||
|
|
0c5e0d649e | ||
|
|
1757440cfe | ||
|
|
c3ccfe455e | ||
|
|
66ec7745bb | ||
|
|
531c51dd64 | ||
|
|
227ec2dc96 | ||
|
|
50c5c76484 | ||
|
|
7a567e400b | ||
|
|
148eabdbc2 | ||
|
|
94ae20ce65 | ||
|
|
fd80f02f0b | ||
|
|
943cdd5010 | ||
|
|
36a5f4a5da | ||
|
|
e0e8cc1295 | ||
|
|
d7bad290e9 | ||
|
|
06766d2ed9 | ||
|
|
913a3e4ce1 | ||
|
|
4e713e4471 | ||
|
|
cb10ea6a7f | ||
|
|
f5095b9f79 | ||
|
|
8a69089513 | ||
|
|
ba6c657587 | ||
|
|
177deb8cd2 | ||
|
|
1dfc478d0e | ||
|
|
f077fb7fad | ||
|
|
0dc1be1f41 | ||
|
|
e1a0864b68 | ||
|
|
222c796eee | ||
|
|
15fe0df04a | ||
|
|
ad1a3c694c | ||
|
|
04be75f037 | ||
|
|
8cd26ce8cb | ||
|
|
525f53aaa9 | ||
|
|
ab95733067 | ||
|
|
35f4e26ca4 | ||
|
|
14f63cb324 | ||
|
|
0962c8383a | ||
|
|
891965a321 | ||
|
|
4d2adc3c3a | ||
|
|
24eb4079d7 | ||
|
|
53010fca84 | ||
|
|
6f3079ab0a | ||
|
|
c73a7c6c09 | ||
|
|
bb60fef3d6 | ||
|
|
b52766d23a | ||
|
|
6f9a9471c3 | ||
|
|
992c169ac7 | ||
|
|
ba8a932b36 | ||
|
|
13dc97d35b | ||
|
|
0ef01e5547 | ||
|
|
138b236832 | ||
|
|
a0d4606c22 | ||
|
|
a5200e46b7 | ||
|
|
2d3866a987 | ||
|
|
0251b40287 | ||
|
|
1e2f215902 | ||
|
|
8184027534 | ||
|
|
a43841b867 | ||
|
|
c391ea2f04 | ||
|
|
111faaa80d | ||
|
|
687cbcd0a4 | ||
|
|
c48665d4c5 | ||
|
|
c873681adc | ||
|
|
cb64f8a809 | ||
|
|
0d8be1fd46 | ||
|
|
e496f71e7d | ||
|
|
de7c8b687a | ||
|
|
61e346e0bf | ||
|
|
67bf9ca8c6 | ||
|
|
14b7fc8a0e | ||
|
|
546d6f9ee0 | ||
|
|
fe74fdecf9 | ||
|
|
c53a67edd5 | ||
|
|
5207f1e1a0 | ||
|
|
53aa2f05d2 | ||
|
|
2405b9fe95 | ||
|
|
bc14bf28bf | ||
|
|
878e705db5 | ||
|
|
be62022344 | ||
|
|
432434a377 | ||
|
|
60860ad9de | ||
|
|
29d6f2dda1 | ||
|
|
330b4176f2 | ||
|
|
75b76bb380 | ||
|
|
c48d129f4a | ||
|
|
673f506ff0 | ||
|
|
ac078ec1b8 | ||
|
|
2007998ae1 | ||
|
|
8050228b40 | ||
|
|
a73ea9b260 | ||
|
|
334728ca4e | ||
|
|
33e010bf78 | ||
|
|
657c96f8cd | ||
|
|
5cd421a4b9 | ||
|
|
b5a0c96927 | ||
|
|
e5a22a1af2 | ||
|
|
4f1fa18cf6 | ||
|
|
bc04d0b774 | ||
|
|
598a15100d | ||
|
|
3227883074 | ||
|
|
4a4c771e52 | ||
|
|
2f45a6955d | ||
|
|
78015d2ecf | ||
|
|
9235495e2c | ||
|
|
84e4a201e7 | ||
|
|
89522132d0 | ||
|
|
780cf3e18f | ||
|
|
6ba3c6d713 | ||
|
|
eae89452ff | ||
|
|
33884c8b81 | ||
|
|
1b33470d69 | ||
|
|
625ace2d50 | ||
|
|
09b50cde9b | ||
|
|
1c6022c227 | ||
|
|
960640cc05 | ||
|
|
ebc4fd6f4c | ||
|
|
2542635aa8 | ||
|
|
8150daa6d5 | ||
|
|
06af6eb5a1 | ||
|
|
fcc765c981 | ||
|
|
98db7f19d1 | ||
|
|
904d034d5f | ||
|
|
52fa1ac922 | ||
|
|
7790cde143 | ||
|
|
1d294c86a2 | ||
|
|
45ba1d94ba | ||
|
|
bdcb1aebce | ||
|
|
cb276b3246 | ||
|
|
eeac5844f6 | ||
|
|
396462c5a2 | ||
|
|
b83b15d2a3 | ||
|
|
1a6fb2a277 | ||
|
|
c2012bcc00 | ||
|
|
15f938fc07 | ||
|
|
8718bb882d | ||
|
|
bc38160b71 | ||
|
|
99c037b1ed | ||
|
|
c66ab909d4 | ||
|
|
cf811a5767 | ||
|
|
d7b5d7fda3 | ||
|
|
797165f10d | ||
|
|
32f094562a | ||
|
|
bc8f714362 | ||
|
|
ec0f2ae59e | ||
|
|
8f34181ae5 | ||
|
|
92f14f517a | ||
|
|
caf1ec9381 | ||
|
|
6b49c684c5 | ||
|
|
5425366f0c | ||
|
|
6ea604c64f | ||
|
|
816885273d | ||
|
|
da6a49cda6 | ||
|
|
0b02e0d8fd | ||
|
|
f03a5ca216 | ||
|
|
cc1aac5520 | ||
|
|
fb265ff767 | ||
|
|
746458d6ac | ||
|
|
63d2bcde53 | ||
|
|
68827af75b | ||
|
|
ba525dfc19 | ||
|
|
174c0fa430 | ||
|
|
e50392d837 | ||
|
|
d28d70e5b9 | ||
|
|
240950787c | ||
|
|
e6da06e22c | ||
|
|
7edbdb719c | ||
|
|
992616c01b | ||
|
|
a17529d0c4 | ||
|
|
c1d4082401 | ||
|
|
fabea09f3d | ||
|
|
bb577a3fc1 | ||
|
|
1d5007ab6a | ||
|
|
624f995966 | ||
|
|
e78ed60974 | ||
|
|
df769135b6 | ||
|
|
8a77ba8c76 | ||
|
|
d0931d95d5 | ||
|
|
a4c6d26a6c | ||
|
|
6b0594a393 | ||
|
|
9844b8a6b8 | ||
|
|
3d1887c5a8 | ||
|
|
ed845b6a0d | ||
|
|
7d58000caa | ||
|
|
0f3c847c60 | ||
|
|
d5bc014618 | ||
|
|
104da1278b | ||
|
|
6933602706 | ||
|
|
b7df12e7b0 | ||
|
|
029bc8e3df | ||
|
|
ed66a2cc2b | ||
|
|
25383df599 | ||
|
|
25fb62403d | ||
|
|
c928c1492b | ||
|
|
958b07b0df | ||
|
|
642c2bb914 | ||
|
|
0486907e33 | ||
|
|
6b92d0619c | ||
|
|
7093999c19 | ||
|
|
ef2e4069d0 | ||
|
|
3fdb6a6177 | ||
|
|
3b9d3ee422 | ||
|
|
a4ea9744cc | ||
|
|
1aa3af7cec | ||
|
|
10cced8d5e | ||
|
|
de85d4e517 | ||
|
|
a06a6a2b27 | ||
|
|
1a4af66a8a | ||
|
|
6db4feeedd | ||
|
|
dfdfd06ab1 | ||
|
|
842995f7f6 | ||
|
|
ba01cfa02b | ||
|
|
329dfbbcde | ||
|
|
ac1b5df59a | ||
|
|
8f2dd3ec6e | ||
|
|
8edf3af709 | ||
|
|
4392b37c0b | ||
|
|
286607fc5d | ||
|
|
4f15fb055d | ||
|
|
3864082269 | ||
|
|
076ad66754 | ||
|
|
cd5d8365fb | ||
|
|
1b4ba18d70 | ||
|
|
80502c7414 | ||
|
|
dea0e371fd | ||
|
|
df9c11b640 | ||
|
|
fef2e00fef | ||
|
|
9f27ed2d64 | ||
|
|
a9ebb18609 | ||
|
|
7b2d557d90 | ||
|
|
fe50bdc8c5 | ||
|
|
3ae4676df2 | ||
|
|
ff78235bf7 | ||
|
|
68d11560ee | ||
|
|
b468952e04 | ||
|
|
aec6e6f71d | ||
|
|
1020473e54 | ||
|
|
3433a13b62 | ||
|
|
b9ecb8632a | ||
|
|
be97cca949 | ||
|
|
0c46a0a957 | ||
|
|
3e0d091f4d | ||
|
|
1387c67219 | ||
|
|
fd02712159 | ||
|
|
c75689800e | ||
|
|
b094709d4c | ||
|
|
f1a6f42b8a |
171
.github/workflows/ci.yml
vendored
171
.github/workflows/ci.yml
vendored
@@ -1,19 +1,19 @@
|
||||
name: CI
|
||||
name: Build Docker image
|
||||
|
||||
on:
|
||||
push:
|
||||
paths-ignore:
|
||||
- 'openapi/**'
|
||||
- '**.md'
|
||||
- 'version'
|
||||
- 'package*.json'
|
||||
- 'helm/*.yaml'
|
||||
- 'CMakeLists.txt'
|
||||
branches:
|
||||
- master
|
||||
- 'release/*'
|
||||
tags:
|
||||
- 'v*'
|
||||
- kinara
|
||||
pull_request:
|
||||
branches:
|
||||
- master
|
||||
- 'release/*'
|
||||
- kinara
|
||||
|
||||
defaults:
|
||||
run:
|
||||
@@ -21,81 +21,102 @@ 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
|
||||
ECR_REGISTRY: 471112855615.dkr.ecr.us-east-1.amazonaws.com
|
||||
ECR_REPOSITORY: owgw
|
||||
AWS_REGION: us-east-1
|
||||
|
||||
steps:
|
||||
- name: Checkout actions repo
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
repository: Telecominfraproject/.github
|
||||
path: github
|
||||
- name: Checkout source
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
path: build
|
||||
token: ${{ secrets.GIT_PUSH_PAT }}
|
||||
persist-credentials: true
|
||||
|
||||
- name: Build and push Docker image
|
||||
uses: ./github/composite-actions/docker-image-build
|
||||
with:
|
||||
image_name: owgw
|
||||
registry: tip-tip-wlan-cloud-ucentral.jfrog.io
|
||||
registry_user: ucentral
|
||||
registry_password: ${{ secrets.DOCKER_REGISTRY_PASSWORD }}
|
||||
- name: Checkout dot github repo
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
repository: kinarasystems/.github
|
||||
ref: main
|
||||
path: tools
|
||||
token: ${{ secrets.GIT_PUSH_PAT }}
|
||||
|
||||
- name: Notify on failure via Slack
|
||||
if: failure() && github.ref == 'refs/heads/master'
|
||||
uses: rtCamp/action-slack-notify@v2
|
||||
env:
|
||||
SLACK_USERNAME: GitHub Actions failure notifier
|
||||
SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK }}
|
||||
SLACK_COLOR: "${{ job.status }}"
|
||||
SLACK_ICON: https://raw.githubusercontent.com/quintessence/slack-icons/master/images/github-logo-slack-icon.png
|
||||
SLACK_TITLE: Docker build failed for OWGW service
|
||||
- name: Bump version and checkin
|
||||
if: github.ref == 'refs/heads/kinara'
|
||||
id: bump-version
|
||||
run: |
|
||||
cd build
|
||||
../tools/utils/setup-git-credentials "${{ secrets.GIT_PUSH_PAT}}"
|
||||
../tools/utils/ver-bump -b -a -p -V kv -y helm/Chart.yaml -Y helm/values.yaml -M CMakeLists.txt
|
||||
|
||||
trigger-testing:
|
||||
if: startsWith(github.ref, 'refs/pull/')
|
||||
- name: Configure AWS credentials
|
||||
uses: aws-actions/configure-aws-credentials@v4
|
||||
with:
|
||||
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
||||
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
||||
aws-region: ${{ env.AWS_REGION }}
|
||||
|
||||
- name: Login to Amazon ECR
|
||||
id: login-ecr
|
||||
uses: aws-actions/amazon-ecr-login@v2
|
||||
|
||||
- name: Build, tag, and push image to Amazon ECR
|
||||
id: build-image
|
||||
env:
|
||||
ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
|
||||
IMAGE_TAG: ${{ github.sha }}
|
||||
GITHUB_REF: ${{ github.ref }}
|
||||
run: |
|
||||
cd build
|
||||
version=$(cat version)
|
||||
../tools/utils/docker_build \
|
||||
-m kinara \
|
||||
-b "$GITHUB_REF" \
|
||||
-t "$IMAGE_TAG" \
|
||||
-r "$ECR_REGISTRY/$ECR_REPOSITORY" \
|
||||
-v "kv${version}"
|
||||
|
||||
- name: Notify via Teams
|
||||
#if: failure() && github.ref == 'refs/heads/kinara'
|
||||
if: always()
|
||||
uses: skitionek/notify-microsoft-teams@master
|
||||
with:
|
||||
webhook_url: ${{ secrets.MS_TEAMS_WEBHOOK }}
|
||||
needs: ${{ toJson(needs) }}
|
||||
job: ${{ toJson(job) }}
|
||||
steps: ${{ toJson(steps) }}
|
||||
dry_run: False
|
||||
|
||||
deploy-to-dev:
|
||||
runs-on: ubuntu-latest
|
||||
needs: docker
|
||||
steps:
|
||||
- name: Get base branch name and set as output
|
||||
id: get_base_branch
|
||||
run: |
|
||||
echo "branch=$(echo ${GITHUB_BASE_REF##*/} | sed 's/master/main/g')" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Checkout actions repo
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
repository: Telecominfraproject/.github
|
||||
path: github
|
||||
|
||||
- name: Trigger testing of OpenWifi Docker Compose deployment and wait for result
|
||||
uses: ./github/composite-actions/trigger-workflow-and-wait
|
||||
env:
|
||||
BASE_BRANCH: ${{ steps.get_base_branch.outputs.branch }}
|
||||
with:
|
||||
owner: Telecominfraproject
|
||||
repo: wlan-testing
|
||||
workflow: ow_docker-compose.yml
|
||||
token: ${{ secrets.WLAN_TESTING_PAT }}
|
||||
ref: master
|
||||
inputs: '{"deployment_version": "${{ env.BASE_BRANCH }}", "owgw_version": "${{ github.sha }}", "owsec_version": "${{ env.BASE_BRANCH }}", "owfms_version": "${{ env.BASE_BRANCH }}", "owprov_version": "${{ env.BASE_BRANCH }}", "owanalytics_version": "${{ env.BASE_BRANCH }}", "owsub_version": "${{ env.BASE_BRANCH }}", "microservice": "owgw"}'
|
||||
|
||||
trigger-deploy-to-dev:
|
||||
runs-on: ubuntu-latest
|
||||
if: github.ref == 'refs/heads/master'
|
||||
if: github.ref == 'refs/heads/kinara'
|
||||
env:
|
||||
DEPLOY_NAME: owgw
|
||||
AWS_DEFAULT_REGION: us-east-1
|
||||
AWS_NAMESPACE: kic-dev1
|
||||
AWS_EKS_NAME: kinara-dev
|
||||
KUBECTL_VERSION: "v1.27.14"
|
||||
needs:
|
||||
- docker
|
||||
steps:
|
||||
- name: Checkout actions repo
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
repository: Telecominfraproject/.github
|
||||
path: github
|
||||
- name: Configure AWS credentials
|
||||
uses: aws-actions/configure-aws-credentials@v4
|
||||
with:
|
||||
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
||||
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
||||
aws-region: ${{ env.AWS_DEFAULT_REGION }}
|
||||
|
||||
- name: Trigger deployment of the latest version to dev instance and wait for result
|
||||
uses: ./github/composite-actions/trigger-workflow-and-wait
|
||||
with:
|
||||
owner: Telecominfraproject
|
||||
repo: wlan-testing
|
||||
workflow: ucentralgw-dev-deployment.yaml
|
||||
token: ${{ secrets.WLAN_TESTING_PAT }}
|
||||
ref: master
|
||||
inputs: '{"force_latest": "true"}'
|
||||
- name: Fetch kubeconfig
|
||||
run: |
|
||||
aws eks update-kubeconfig --name ${{ env.AWS_EKS_NAME }} --region ${{ env.AWS_DEFAULT_REGION }}
|
||||
|
||||
- name: Install kubectl
|
||||
run: |
|
||||
curl -s -LO "https://dl.k8s.io/release/${{ env.KUBECTL_VERSION }}/bin/linux/amd64/kubectl"
|
||||
sudo install -o root -g root -m 0755 kubectl /usr/local/bin/kubectl
|
||||
|
||||
- name: Rolling update of deployment
|
||||
run: |
|
||||
kubectl rollout restart deployment/${{ env.DEPLOY_NAME }} -n ${{ env.AWS_NAMESPACE }}
|
||||
|
||||
26
.github/workflows/cleanup.yml
vendored
26
.github/workflows/cleanup.yml
vendored
@@ -1,26 +0,0 @@
|
||||
name: Clean up PR Docker images
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
branches:
|
||||
- master
|
||||
types: [ closed ]
|
||||
|
||||
defaults:
|
||||
run:
|
||||
shell: bash
|
||||
|
||||
jobs:
|
||||
cleanup:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Cleanup Docker image with PR branch tag
|
||||
run: |
|
||||
export PR_BRANCH_TAG=$(echo ${GITHUB_HEAD_REF#refs/heads/} | tr '/' '-')
|
||||
|
||||
if [[ ! $PR_BRANCH_TAG =~ (main|master|release-*) ]]; then
|
||||
echo "PR branch is $PR_BRANCH_TAG, deleting Docker image"
|
||||
curl -s -uucentral:${{ secrets.DOCKER_REGISTRY_PASSWORD }} -X DELETE "https://tip.jfrog.io/artifactory/tip-wlan-cloud-ucentral/owgw/$PR_BRANCH_TAG"
|
||||
else
|
||||
echo "PR branch is $PR_BRANCH_TAG, not deleting Docker image"
|
||||
fi
|
||||
24
.github/workflows/enforce-jira-issue-key.yml
vendored
24
.github/workflows/enforce-jira-issue-key.yml
vendored
@@ -1,24 +0,0 @@
|
||||
name: Ensure Jira issue is linked
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types: [opened, edited, reopened, synchronize]
|
||||
branches:
|
||||
- 'release/*'
|
||||
|
||||
jobs:
|
||||
check_for_issue_key:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout actions repo
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
repository: Telecominfraproject/.github
|
||||
path: github
|
||||
|
||||
- name: Run JIRA check
|
||||
uses: ./github/composite-actions/enforce-jira-issue-key
|
||||
with:
|
||||
jira_base_url: ${{ secrets.TIP_JIRA_URL }}
|
||||
jira_user_email: ${{ secrets.TIP_JIRA_USER_EMAIL }}
|
||||
jira_api_token: ${{ secrets.TIP_JIRA_API_TOKEN }}
|
||||
41
.github/workflows/openapi-pages.yml
vendored
41
.github/workflows/openapi-pages.yml
vendored
@@ -1,41 +0,0 @@
|
||||
name: Update OpenAPI docs on GitHub Pages
|
||||
|
||||
on:
|
||||
push:
|
||||
paths:
|
||||
- 'openapi/**'
|
||||
branches:
|
||||
- master
|
||||
workflow_dispatch:
|
||||
|
||||
defaults:
|
||||
run:
|
||||
shell: bash
|
||||
|
||||
jobs:
|
||||
docsgen:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Generate static HTML page with docs from OpenAPI definition
|
||||
run: |
|
||||
docker run --rm -v "${PWD}:/local" openapitools/openapi-generator-cli:v6.2.1 generate -i https://raw.githubusercontent.com/Telecominfraproject/wlan-cloud-ucentralgw/master/openapi/owgw.yaml -g html2 --skip-validate-spec -o /local/
|
||||
|
||||
- name: Update OpenAPI docs
|
||||
run: |
|
||||
mkdir tmp-docs
|
||||
mv index.html tmp-docs/index.html
|
||||
mkdir -p ~/.ssh
|
||||
ssh-keyscan -H github.com >> ~/.ssh/known_hosts
|
||||
echo https://tip-automation:${{ secrets.GIT_PUSH_PAT }}@github.com > ~/.git-credentials
|
||||
git config --global credential.helper store
|
||||
git config --global user.email "tip-automation@telecominfraproject.com"
|
||||
git config --global user.name "TIP Automation User"
|
||||
git pull
|
||||
git checkout gh-pages || git checkout -b gh-pages
|
||||
rm -rf docs
|
||||
mv tmp-docs docs
|
||||
git add docs
|
||||
git commit -m'Update OpenAPI docs for GitHub pages'
|
||||
git push --set-upstream origin gh-pages
|
||||
46
.github/workflows/release.yml
vendored
46
.github/workflows/release.yml
vendored
@@ -1,46 +0,0 @@
|
||||
name: Release chart package
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- 'v*'
|
||||
|
||||
defaults:
|
||||
run:
|
||||
shell: bash
|
||||
|
||||
jobs:
|
||||
helm-package:
|
||||
runs-on: ubuntu-20.04
|
||||
env:
|
||||
HELM_REPO_URL: https://tip.jfrog.io/artifactory/tip-wlan-cloud-ucentral-helm/
|
||||
HELM_REPO_USERNAME: ucentral
|
||||
steps:
|
||||
- name: Checkout uCentral assembly chart repo
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
path: wlan-cloud-ucentralgw
|
||||
|
||||
- name: Build package
|
||||
working-directory: wlan-cloud-ucentralgw/helm
|
||||
run: |
|
||||
helm plugin install https://github.com/aslafy-z/helm-git --version 0.10.0
|
||||
helm repo add bitnami https://charts.bitnami.com/bitnami
|
||||
helm repo update
|
||||
helm dependency update
|
||||
mkdir dist
|
||||
helm package . -d dist
|
||||
|
||||
- name: Generate GitHub release body
|
||||
working-directory: wlan-cloud-ucentralgw/helm
|
||||
run: |
|
||||
pip3 install yq -q
|
||||
echo "Docker image - tip-tip-wlan-cloud-ucentral.jfrog.io/owgw:$GITHUB_REF_NAME" > release.txt
|
||||
echo "Helm charted may be attached to this release" >> release.txt
|
||||
echo "Deployment artifacts may be found in https://github.com/Telecominfraproject/wlan-cloud-ucentral-deploy/tree/$GITHUB_REF_NAME" >> release.txt
|
||||
|
||||
- name: Create GitHub release
|
||||
uses: softprops/action-gh-release@v1
|
||||
with:
|
||||
body_path: wlan-cloud-ucentralgw/helm/release.txt
|
||||
files: wlan-cloud-ucentralgw/helm/dist/*
|
||||
3
.gitignore
vendored
3
.gitignore
vendored
@@ -21,10 +21,11 @@ _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
|
||||
|
||||
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>
|
||||
|
||||
2
.idea/ucentral.iml
generated
2
.idea/ucentral.iml
generated
@@ -2,7 +2,7 @@
|
||||
<module classpath="CMake" type="CPP_MODULE" version="4">
|
||||
<component name="FacetManager">
|
||||
<facet type="Python" name="Python facet">
|
||||
<configuration sdkName="Python 3.9 (venv)" />
|
||||
<configuration sdkName="Python 3.9 (wlan-cloud-ucentralgw)" />
|
||||
</facet>
|
||||
</component>
|
||||
</module>
|
||||
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-v1
|
||||
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-v1
|
||||
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-v1
|
||||
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 ../..
|
||||
```
|
||||
|
||||
44
CHANGELOG.md
Normal file
44
CHANGELOG.md
Normal file
@@ -0,0 +1,44 @@
|
||||
## 3.0.13 (October 30, 2024)
|
||||
- chore: updated package.json, updated helm/Chart.yaml, updated helm/values.yaml, updated CMakeLists.txt, updated version, updated CHANGELOG.md, bumped 3.0.12 -> 3.0.13
|
||||
- Merge pull request #16 from kinarasystems/WIFI-14227-feat-compressed-config
|
||||
|
||||
## 3.0.12 (September 27, 2024)
|
||||
- chore: updated package.json, updated helm/Chart.yaml, updated helm/values.yaml, updated CMakeLists.txt, updated version, updated CHANGELOG.md, bumped 3.0.11 -> 3.0.12
|
||||
- Merge pull request #15 from kinarasystems/WIFI-14134-fix_file_upload_status
|
||||
|
||||
## 3.0.11 (September 27, 2024)
|
||||
- chore: updated package.json, updated helm/Chart.yaml, updated helm/values.yaml, updated CMakeLists.txt, updated version, updated CHANGELOG.md, bumped 3.0.10 -> 3.0.11
|
||||
- Merge pull request #14 from kinarasystems/WIFI-14134-fix_file_upload_status
|
||||
|
||||
## 3.0.10 (September 18, 2024)
|
||||
- chore: updated package.json, updated helm/Chart.yaml, updated helm/values.yaml, updated CMakeLists.txt, updated version, updated CHANGELOG.md, bumped 3.0.9 -> 3.0.10
|
||||
- Merge pull request #12 from kinarasystems/cable_diag
|
||||
|
||||
## 3.0.9 (August 30, 2024)
|
||||
- chore: updated package.json, updated helm/Chart.yaml, updated helm/values.yaml, updated CMakeLists.txt, updated version, updated CHANGELOG.md, bumped 3.0.8 -> 3.0.9
|
||||
- Merge pull request #11 from kinarasystems/fixedconfig
|
||||
|
||||
## 3.0.8 (August 08, 2024)
|
||||
- chore: updated package.json, updated helm/Chart.yaml, updated helm/values.yaml, updated CMakeLists.txt, updated version, updated CHANGELOG.md, bumped 3.0.7 -> 3.0.8
|
||||
- Merge pull request #10 from kinarasystems/WIFI-13875-fix-use-dns
|
||||
|
||||
## 3.0.7 (August 07, 2024)
|
||||
- chore: updated package.json, updated helm/Chart.yaml, updated helm/values.yaml, updated CMakeLists.txt, updated version, updated CHANGELOG.md, bumped 3.0.6 -> 3.0.7
|
||||
- Merge branch 'Telecominfraproject:master' into kinara
|
||||
|
||||
## 3.0.6 (July 30, 2024)
|
||||
- chore: updated package.json, updated helm/Chart.yaml, updated helm/values.yaml, updated CMakeLists.txt, updated version, updated CHANGELOG.md, bumped 3.0.5 -> 3.0.6
|
||||
- chore: updated package.json, updated helm/Chart.yaml, updated helm/values.yaml, updated CMakeLists.txt, updated version, updated CHANGELOG.md, bumped 3.0.4 -> 3.0.5
|
||||
|
||||
## 3.0.5 (July 22, 2024)
|
||||
- chore: updated package.json, updated helm/Chart.yaml, updated helm/values.yaml, updated CMakeLists.txt, updated version, updated CHANGELOG.md, bumped 3.0.4 -> 3.0.5
|
||||
- Merge pull request #8 from kinarasystems/command
|
||||
|
||||
## 3.0.4 (July 17, 2024)
|
||||
- chore: updated package.json, updated helm/Chart.yaml, updated helm/values.yaml, updated CMakeLists.txt, updated version, updated CHANGELOG.md, bumped 3.0.3 -> 3.0.4
|
||||
- Merge pull request #7 from kinarasystems/fix_uptime_update_after_reboot
|
||||
|
||||
## 3.0.3 (June 19, 2024)
|
||||
- chore: updated package.json, updated helm/Chart.yaml, updated helm/values.yaml, updated CMakeLists.txt, updated version, created CHANGELOG.md, bumped 3.0.2 -> 3.0.3
|
||||
- Merge pull request #6 from kinarasystems/devices
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
cmake_minimum_required(VERSION 3.13)
|
||||
project(owgw VERSION 2.10.0)
|
||||
project(owgw VERSION 3.0.13)
|
||||
|
||||
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)
|
||||
@@ -49,7 +50,7 @@ if(GIT_FOUND AND EXISTS "${PROJECT_SOURCE_DIR}/.git")
|
||||
string(REGEX REPLACE "\n$" "" GIT_HASH "${GIT_HASH}")
|
||||
endif()
|
||||
|
||||
add_definitions(-DTIP_GATEWAY_SERVICE="1" -DPOCO_LOG_DEBUG="1")
|
||||
add_definitions(-DTIP_GATEWAY_SERVICE="1" -DPOCO_LOG_DEBUG="1" -DBOOST_NO_CXX98_FUNCTION_BASE=1)
|
||||
|
||||
find_package(OpenSSL REQUIRED)
|
||||
find_package(ZLIB REQUIRED)
|
||||
@@ -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
|
||||
@@ -199,7 +201,7 @@ add_executable( owgw
|
||||
src/AP_WS_Process_deviceupdate.cpp
|
||||
src/AP_WS_Process_telemetry.cpp
|
||||
src/AP_WS_Process_venuebroadcast.cpp
|
||||
src/RADSEC_server.h
|
||||
src/RADIUS_Destination.h
|
||||
src/UI_GW_WebSocketNotifications.cpp src/UI_GW_WebSocketNotifications.h
|
||||
src/framework/RESTAPI_SystemConfiguration.h
|
||||
src/ScriptManager.cpp src/ScriptManager.h
|
||||
@@ -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/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)
|
||||
|
||||
@@ -223,14 +226,17 @@ INSTALL(TARGETS owgw
|
||||
|
||||
target_link_libraries(owgw PUBLIC
|
||||
${Poco_LIBRARIES}
|
||||
${ZLIB_LIBRARIES})
|
||||
${ZLIB_LIBRARIES}
|
||||
)
|
||||
|
||||
if(NOT SMALL_BUILD)
|
||||
target_link_libraries(owgw PUBLIC
|
||||
${MySQL_LIBRARIES} ${ZLIB_LIBRARIES}
|
||||
CppKafka::cppkafka
|
||||
fmt::fmt
|
||||
)
|
||||
${MySQL_LIBRARIES}
|
||||
${ZLIB_LIBRARIES}
|
||||
CppKafka::cppkafka
|
||||
fmt::fmt
|
||||
resolv
|
||||
)
|
||||
if(UNIX AND NOT APPLE)
|
||||
target_link_libraries(owgw PUBLIC PocoJSON)
|
||||
endif()
|
||||
|
||||
62
Dockerfile
62
Dockerfile
@@ -1,7 +1,9 @@
|
||||
ARG DEBIAN_VERSION=11.5-slim
|
||||
ARG POCO_VERSION=poco-tip-v2
|
||||
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
|
||||
|
||||
FROM debian:$DEBIAN_VERSION AS build-base
|
||||
|
||||
@@ -15,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
|
||||
@@ -29,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
|
||||
@@ -43,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
|
||||
@@ -53,12 +55,14 @@ RUN cmake ..
|
||||
RUN cmake --build . --config Release -j8
|
||||
RUN cmake --build . --target install
|
||||
|
||||
FROM build-base AS owgw-build
|
||||
FROM build-base AS app-build
|
||||
|
||||
ADD CMakeLists.txt build /owgw/
|
||||
ADD cmake /owgw/cmake
|
||||
ADD src /owgw/src
|
||||
ADD .git /owgw/.git
|
||||
ARG APP_NAME
|
||||
|
||||
ADD CMakeLists.txt build /${APP_NAME}/
|
||||
ADD cmake /${APP_NAME}/cmake
|
||||
ADD src /${APP_NAME}/src
|
||||
ADD .git /${APP_NAME}/.git
|
||||
|
||||
COPY --from=poco-build /usr/local/include /usr/local/include
|
||||
COPY --from=poco-build /usr/local/lib /usr/local/lib
|
||||
@@ -66,23 +70,33 @@ COPY --from=cppkafka-build /usr/local/include /usr/local/include
|
||||
COPY --from=cppkafka-build /usr/local/lib /usr/local/lib
|
||||
COPY --from=valijson-build /usr/local/include /usr/local/include
|
||||
|
||||
WORKDIR /owgw
|
||||
WORKDIR /${APP_NAME}
|
||||
RUN mkdir cmake-build
|
||||
WORKDIR /owgw/cmake-build
|
||||
WORKDIR /${APP_NAME}/cmake-build
|
||||
RUN cmake ..
|
||||
RUN cmake --build . --config Release -j8
|
||||
|
||||
FROM debian:$DEBIAN_VERSION
|
||||
|
||||
ENV OWGW_USER=owgw \
|
||||
OWGW_ROOT=/owgw-data \
|
||||
OWGW_CONFIG=/owgw-data
|
||||
ARG APP_NAME
|
||||
ARG APP_HOME_DIR
|
||||
|
||||
RUN useradd "$OWGW_USER"
|
||||
ENV APP_NAME=$APP_NAME \
|
||||
APP_USER=$APP_NAME \
|
||||
APP_ROOT=/$APP_NAME-data \
|
||||
APP_CONFIG=/$APP_NAME-data \
|
||||
APP_HOME_DIR=$APP_HOME_DIR
|
||||
|
||||
RUN mkdir /openwifi
|
||||
RUN mkdir -p "$OWGW_ROOT" "$OWGW_CONFIG" && \
|
||||
chown "$OWGW_USER": "$OWGW_ROOT" "$OWGW_CONFIG"
|
||||
# This is for legacy
|
||||
ENV OWGW_USER=$APP_USER \
|
||||
OWGW_ROOT=$APP_ROOT \
|
||||
OWGW_CONFIG=$APP_CONFIG
|
||||
|
||||
RUN useradd $APP_USER
|
||||
|
||||
RUN mkdir $APP_HOME_DIR
|
||||
RUN mkdir -p $APP_ROOT $APP_CONFIG && \
|
||||
chown $APP_USER: $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 \
|
||||
@@ -91,14 +105,14 @@ RUN apt-get update && apt-get install --no-install-recommends -y \
|
||||
COPY readiness_check /readiness_check
|
||||
COPY test_scripts/curl/cli /cli
|
||||
|
||||
COPY owgw.properties.tmpl /
|
||||
COPY $APP_NAME.properties.tmpl /
|
||||
COPY docker-entrypoint.sh /
|
||||
COPY wait-for-postgres.sh /
|
||||
COPY rtty_ui /dist/rtty_ui
|
||||
RUN wget https://raw.githubusercontent.com/Telecominfraproject/wlan-cloud-ucentral-deploy/main/docker-compose/certs/restapi-ca.pem \
|
||||
-O /usr/local/share/ca-certificates/restapi-ca-selfsigned.crt
|
||||
|
||||
COPY --from=owgw-build /owgw/cmake-build/owgw /openwifi/owgw
|
||||
COPY --from=app-build /$APP_NAME/cmake-build/$APP_NAME $APP_HOME_DIR/$APP_NAME
|
||||
COPY --from=cppkafka-build /cppkafka/cmake-build/src/lib /usr/local/lib/
|
||||
COPY --from=poco-build /poco/cmake-build/lib /usr/local/lib/
|
||||
|
||||
@@ -107,4 +121,4 @@ RUN ldconfig
|
||||
EXPOSE 15002 16002 16003 17002 16102
|
||||
|
||||
ENTRYPOINT ["/docker-entrypoint.sh"]
|
||||
CMD ["/openwifi/owgw"]
|
||||
CMD ${APP_HOME_DIR}/${APP_NAME}
|
||||
|
||||
173
PROTOCOL.md
173
PROTOCOL.md
@@ -355,6 +355,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
|
||||
@@ -775,6 +808,146 @@ The device should answer:
|
||||
}
|
||||
```
|
||||
|
||||
#### Controller wants the device to replace its certificates
|
||||
Controller sends this command to run a predefined script. Extreme care must be taken.
|
||||
```json
|
||||
{ "jsonrpc" : "2.0" ,
|
||||
"method" : "certupdate" ,
|
||||
"params" : {
|
||||
"serial" : <serial number>,
|
||||
"certificates" : <BASE64 encoded tar file of the cert package from the certificate portal>
|
||||
},
|
||||
"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.
|
||||
|
||||
```json
|
||||
{ "jsonrpc" : "2.0" ,
|
||||
"method" : "transfer" ,
|
||||
"params" : {
|
||||
"serial" : <serial number>,
|
||||
"server" : <controller hostname>,
|
||||
"port" : <controller port number (integer)>,
|
||||
},
|
||||
"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>
|
||||
}
|
||||
```
|
||||
|
||||
### RRM AP device commands
|
||||
The following command is used to send RRM commands to an AP. RRM commands are send to an AP, however the
|
||||
controller will not or cannot verify if they have been sent or the action was performed.
|
||||
|
||||
```json
|
||||
{ "jsonrpc" : "2.0" ,
|
||||
"method" : "rrm" ,
|
||||
"params" : {
|
||||
"serial" : <serial number>,
|
||||
"actions" : [ array of actions. Each possible action is defined next]
|
||||
},
|
||||
"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>
|
||||
}
|
||||
```
|
||||
|
||||
#### RRM Roam action
|
||||
|
||||
##### Kick
|
||||
```json
|
||||
{
|
||||
"action" : "kick" ,
|
||||
"addr" : <mac if the client that shall be kicked> ,
|
||||
"reason": <number>, (default: 5, https://www.cisco.com/assets/sol/sb/WAP371_Emulators/WAP371_Emulator_v1-0-1-5/help/Apx_ReasonCodes2.html)
|
||||
"ban_time": <number> (seconds, optional)
|
||||
}
|
||||
```
|
||||
|
||||
##### Channel Switch Announcement
|
||||
```json
|
||||
{
|
||||
"action" : "channel_switch" ,
|
||||
"bssid" : <mac of the SSID> , (all other SSIDs on the same radio will perform the same action)
|
||||
"channel" : <number> (HT/HW mode will be retained upon issuing the CSA)
|
||||
}
|
||||
```
|
||||
|
||||
##### Change TX-Power
|
||||
```json
|
||||
{
|
||||
"action" : "tx_power" ,
|
||||
"bssid" : <mac of the SSID> , (all other SSIDs on the same radio will perform the same action)
|
||||
"level" : <number> (DBm inside the positive number space)
|
||||
}
|
||||
```
|
||||
|
||||
##### Beacon Scan
|
||||
```json
|
||||
{
|
||||
"action" : "beacon_request" ,
|
||||
"addr" : <mac if the client that shall perform the scan> ,
|
||||
"ssid": <string>, (the SSID the client shall scan for on all frequencies),
|
||||
"channel": <number> (the channel that shall be scanned)
|
||||
}
|
||||
```
|
||||
|
||||
##### BSS Transition
|
||||
```json
|
||||
{
|
||||
"action" : "bss_transition" ,
|
||||
"addr" : <mac if the client that shall perform the roam> ,
|
||||
"neighbors": [ <string> ], (an array of BSSIDs the client shall consider as roamin candidates)
|
||||
}
|
||||
```
|
||||
|
||||
##### Update neighbours
|
||||
```json
|
||||
{
|
||||
"action" : "neighbors" ,
|
||||
"bssid" : <mac of the SSID> , (the SSID of the specific VAP)
|
||||
"neighbors": [ [ <BSS>, <ssid>, <neighbor report> ] ]
|
||||
}
|
||||
```
|
||||
|
||||
### `rtty server`
|
||||
More information about the [rtty server](https://github.com/zhaojh329/rtty) can be found here.
|
||||
|
||||
|
||||
21
buildaws
Executable file
21
buildaws
Executable file
@@ -0,0 +1,21 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
[ -z "$AWS_PROFILE" ] && echo "Please set AWS_PROFILE" && exit 1
|
||||
registry="471112855615.dkr.ecr.us-east-1.amazonaws.com"
|
||||
repo="owgw"
|
||||
aws ecr get-login-password --region us-east-1 | docker login --username AWS --password-stdin "$registry"
|
||||
img="$registry/$repo"
|
||||
if [ -n "$1" ] ; then
|
||||
version="$1"
|
||||
else
|
||||
version="latest"
|
||||
fi
|
||||
#date > about.txt
|
||||
#id=$(git rev-parse HEAD)
|
||||
#br=$(git branch --show-current)
|
||||
#echo "$br" >> about.txt
|
||||
#echo "$id" >> about.txt
|
||||
#echo "Built manually via $0" >> about.txt
|
||||
#docker build --no-cache -t $img:$version .
|
||||
docker build -t $img:$version .
|
||||
docker push $img:$version
|
||||
20
buildit
Executable file
20
buildit
Executable file
@@ -0,0 +1,20 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
repo="owgw"
|
||||
[ -z "$REMOTE_DOCKER_HOST" ] && echo "Please set DOCKER_HOST" && exit 1
|
||||
[ -z "$REMOTE_DOCKER_PASSWORD" ] && echo "Please set DOCKER_PASSWORD" && exit 1
|
||||
img="$REMOTE_DOCKER_HOST/kinara/$repo"
|
||||
if [ -n "$1" ] ; then
|
||||
version="$1"
|
||||
else
|
||||
version="latest"
|
||||
fi
|
||||
#date > about.txt
|
||||
#id=$(git rev-parse HEAD)
|
||||
#br=$(git branch --show-current)
|
||||
#echo "$br" >> about.txt
|
||||
#echo "$id" >> about.txt
|
||||
#echo "Built manually via $0" >> about.txt
|
||||
#docker build --no-cache -t $img:$version .
|
||||
docker build -t $img:$version .
|
||||
docker push $img:$version
|
||||
@@ -6,35 +6,35 @@ if [ "$SELFSIGNED_CERTS" = 'true' ]; then
|
||||
fi
|
||||
|
||||
if [[ "$TEMPLATE_CONFIG" = 'true' ]]; then
|
||||
WEBSOCKET_HOST_ROOTCA=${WEBSOCKET_HOST_ROOTCA:-"\$OWGW_ROOT/certs/root.pem"} \
|
||||
WEBSOCKET_HOST_ISSUER=${WEBSOCKET_HOST_ISSUER:-"\$OWGW_ROOT/certs/issuer.pem"} \
|
||||
WEBSOCKET_HOST_CERT=${WEBSOCKET_HOST_CERT:-"\$OWGW_ROOT/certs/websocket-cert.pem"} \
|
||||
WEBSOCKET_HOST_KEY=${WEBSOCKET_HOST_KEY:-"\$OWGW_ROOT/certs/websocket-key.pem"} \
|
||||
WEBSOCKET_HOST_CLIENTCAS=${WEBSOCKET_HOST_CLIENTCAS:-"\$OWGW_ROOT/certs/clientcas.pem"} \
|
||||
WEBSOCKET_HOST_CAS=${WEBSOCKET_HOST_CAS:-"\$OWGW_ROOT/certs/cas"} \
|
||||
WEBSOCKET_HOST_ROOTCA=${WEBSOCKET_HOST_ROOTCA:-"\${APP_ROOT}/certs/root.pem"} \
|
||||
WEBSOCKET_HOST_ISSUER=${WEBSOCKET_HOST_ISSUER:-"\${APP_ROOT}/certs/issuer.pem"} \
|
||||
WEBSOCKET_HOST_CERT=${WEBSOCKET_HOST_CERT:-"\${APP_ROOT}/certs/websocket-cert.pem"} \
|
||||
WEBSOCKET_HOST_KEY=${WEBSOCKET_HOST_KEY:-"\${APP_ROOT}/certs/websocket-key.pem"} \
|
||||
WEBSOCKET_HOST_CLIENTCAS=${WEBSOCKET_HOST_CLIENTCAS:-"\${APP_ROOT}/certs/clientcas.pem"} \
|
||||
WEBSOCKET_HOST_CAS=${WEBSOCKET_HOST_CAS:-"\${APP_ROOT}/certs/cas"} \
|
||||
WEBSOCKET_HOST_PORT=${WEBSOCKET_HOST_PORT:-"15002"} \
|
||||
WEBSOCKET_HOST_KEY_PASSWORD=${WEBSOCKET_HOST_KEY_PASSWORD:-"mypassword"} \
|
||||
RESTAPI_HOST_ROOTCA=${RESTAPI_HOST_ROOTCA:-"\$OWGW_ROOT/certs/restapi-ca.pem"} \
|
||||
RESTAPI_HOST_ROOTCA=${RESTAPI_HOST_ROOTCA:-"\${APP_ROOT}/certs/restapi-ca.pem"} \
|
||||
RESTAPI_HOST_PORT=${RESTAPI_HOST_PORT:-"16002"} \
|
||||
RESTAPI_HOST_CERT=${RESTAPI_HOST_CERT:-"\$OWGW_ROOT/certs/restapi-cert.pem"} \
|
||||
RESTAPI_HOST_KEY=${RESTAPI_HOST_KEY:-"\$OWGW_ROOT/certs/restapi-key.pem"} \
|
||||
RESTAPI_HOST_CERT=${RESTAPI_HOST_CERT:-"\${APP_ROOT}/certs/restapi-cert.pem"} \
|
||||
RESTAPI_HOST_KEY=${RESTAPI_HOST_KEY:-"\${APP_ROOT}/certs/restapi-key.pem"} \
|
||||
RESTAPI_HOST_KEY_PASSWORD=${RESTAPI_HOST_KEY_PASSWORD:-"mypassword"} \
|
||||
INTERNAL_RESTAPI_HOST_ROOTCA=${INTERNAL_RESTAPI_HOST_ROOTCA:-"\$OWGW_ROOT/certs/restapi-ca.pem"} \
|
||||
INTERNAL_RESTAPI_HOST_ROOTCA=${INTERNAL_RESTAPI_HOST_ROOTCA:-"\${APP_ROOT}/certs/restapi-ca.pem"} \
|
||||
INTERNAL_RESTAPI_HOST_PORT=${INTERNAL_RESTAPI_HOST_PORT:-"17002"} \
|
||||
INTERNAL_RESTAPI_HOST_CERT=${INTERNAL_RESTAPI_HOST_CERT:-"\$OWGW_ROOT/certs/restapi-cert.pem"} \
|
||||
INTERNAL_RESTAPI_HOST_KEY=${INTERNAL_RESTAPI_HOST_KEY:-"\$OWGW_ROOT/certs/restapi-key.pem"} \
|
||||
INTERNAL_RESTAPI_HOST_CERT=${INTERNAL_RESTAPI_HOST_CERT:-"\${APP_ROOT}/certs/restapi-cert.pem"} \
|
||||
INTERNAL_RESTAPI_HOST_KEY=${INTERNAL_RESTAPI_HOST_KEY:-"\${APP_ROOT}/certs/restapi-key.pem"} \
|
||||
INTERNAL_RESTAPI_HOST_KEY_PASSWORD=${INTERNAL_RESTAPI_HOST_KEY_PASSWORD:-"mypassword"} \
|
||||
FILEUPLOADER_HOST_ROOTCA=${FILEUPLOADER_HOST_ROOTCA:-"\$OWGW_ROOT/certs/restapi-ca.pem"} \
|
||||
FILEUPLOADER_HOST_ROOTCA=${FILEUPLOADER_HOST_ROOTCA:-"\${APP_ROOT}/certs/restapi-ca.pem"} \
|
||||
FILEUPLOADER_HOST_NAME=${FILEUPLOADER_HOST_NAME:-"localhost"} \
|
||||
FILEUPLOADER_HOST_PORT=${FILEUPLOADER_HOST_PORT:-"16003"} \
|
||||
FILEUPLOADER_HOST_CERT=${FILEUPLOADER_HOST_CERT:-"\$OWGW_ROOT/certs/restapi-cert.pem"} \
|
||||
FILEUPLOADER_HOST_KEY=${FILEUPLOADER_HOST_KEY:-"\$OWGW_ROOT/certs/restapi-key.pem"} \
|
||||
FILEUPLOADER_HOST_CERT=${FILEUPLOADER_HOST_CERT:-"\${APP_ROOT}/certs/restapi-cert.pem"} \
|
||||
FILEUPLOADER_HOST_KEY=${FILEUPLOADER_HOST_KEY:-"\${APP_ROOT}/certs/restapi-key.pem"} \
|
||||
FILEUPLOADER_HOST_KEY_PASSWORD=${FILEUPLOADER_HOST_KEY_PASSWORD:-"mypassword"} \
|
||||
FILEUPLOADER_PATH=${FILEUPLOADER_PATH:-"\$OWGW_ROOT/uploads"} \
|
||||
FILEUPLOADER_PATH=${FILEUPLOADER_PATH:-"\${APP_ROOT}/uploads"} \
|
||||
FILEUPLOADER_URI=${FILEUPLOADER_URI:-"https://localhost:16003"} \
|
||||
SERVICE_KEY=${SERVICE_KEY:-"\$OWGW_ROOT/certs/restapi-key.pem"} \
|
||||
SERVICE_KEY=${SERVICE_KEY:-"\${APP_ROOT}/certs/restapi-key.pem"} \
|
||||
SERVICE_KEY_PASSWORD=${SERVICE_KEY_PASSWORD:-"mypassword"} \
|
||||
SYSTEM_DATA=${SYSTEM_DATA:-"\$OWGW_ROOT/data"} \
|
||||
SYSTEM_DATA=${SYSTEM_DATA:-"\${APP_ROOT}/data"} \
|
||||
SYSTEM_URI_PRIVATE=${SYSTEM_URI_PRIVATE:-"https://localhost:17002"} \
|
||||
SYSTEM_URI_PUBLIC=${SYSTEM_URI_PUBLIC:-"https://localhost:16002"} \
|
||||
SYSTEM_URI_UI=${SYSTEM_URI_UI:-"http://localhost"} \
|
||||
@@ -51,7 +51,7 @@ if [[ "$TEMPLATE_CONFIG" = 'true' ]]; then
|
||||
RTTY_TOKEN=${RTTY_TOKEN:-""} \
|
||||
RTTY_TIMEOUT=${RTTY_TIMEOUT:-"60"} \
|
||||
RTTY_VIEWPORT=${RTTY_VIEWPORT:-"5913"} \
|
||||
RTTY_ASSETS=${RTTY_ASSETS:-"\$OWGW_ROOT/rtty_ui"} \
|
||||
RTTY_ASSETS=${RTTY_ASSETS:-"\${APP_ROOT}/rtty_ui"} \
|
||||
RADIUS_PROXY_ENABLE=${RADIUS_PROXY_ENABLE:-"false"} \
|
||||
RADIUS_PROXY_ACCOUNTING_PORT=${RADIUS_PROXY_ACCOUNTING_PORT:-"1813"} \
|
||||
RADIUS_PROXY_AUTHENTICATION_PORT=${RADIUS_PROXY_AUTHENTICATION_PORT:-"1812"} \
|
||||
@@ -64,41 +64,41 @@ if [[ "$TEMPLATE_CONFIG" = 'true' ]]; then
|
||||
KAFKA_SSL_KEY_PASSWORD=${KAFKA_SSL_KEY_PASSWORD:-""} \
|
||||
STORAGE_TYPE=${STORAGE_TYPE:-"sqlite"} \
|
||||
STORAGE_TYPE_POSTGRESQL_HOST=${STORAGE_TYPE_POSTGRESQL_HOST:-"localhost"} \
|
||||
STORAGE_TYPE_POSTGRESQL_USERNAME=${STORAGE_TYPE_POSTGRESQL_USERNAME:-"owgw"} \
|
||||
STORAGE_TYPE_POSTGRESQL_PASSWORD=${STORAGE_TYPE_POSTGRESQL_PASSWORD:-"owgw"} \
|
||||
STORAGE_TYPE_POSTGRESQL_DATABASE=${STORAGE_TYPE_POSTGRESQL_DATABASE:-"owgw"} \
|
||||
STORAGE_TYPE_POSTGRESQL_USERNAME=${STORAGE_TYPE_POSTGRESQL_USERNAME:-"${APP_USER}"} \
|
||||
STORAGE_TYPE_POSTGRESQL_PASSWORD=${STORAGE_TYPE_POSTGRESQL_PASSWORD:-"${APP_USER}"} \
|
||||
STORAGE_TYPE_POSTGRESQL_DATABASE=${STORAGE_TYPE_POSTGRESQL_DATABASE:-"${APP_NAME}"} \
|
||||
STORAGE_TYPE_POSTGRESQL_PORT=${STORAGE_TYPE_POSTGRESQL_PORT:-"5432"} \
|
||||
STORAGE_TYPE_MYSQL_HOST=${STORAGE_TYPE_MYSQL_HOST:-"localhost"} \
|
||||
STORAGE_TYPE_MYSQL_USERNAME=${STORAGE_TYPE_MYSQL_USERNAME:-"owgw"} \
|
||||
STORAGE_TYPE_MYSQL_PASSWORD=${STORAGE_TYPE_MYSQL_PASSWORD:-"owgw"} \
|
||||
STORAGE_TYPE_MYSQL_DATABASE=${STORAGE_TYPE_MYSQL_DATABASE:-"owgw"} \
|
||||
STORAGE_TYPE_MYSQL_USERNAME=${STORAGE_TYPE_MYSQL_USERNAME:-"${APP_USER}"} \
|
||||
STORAGE_TYPE_MYSQL_PASSWORD=${STORAGE_TYPE_MYSQL_PASSWORD:-"${APP_USER}"} \
|
||||
STORAGE_TYPE_MYSQL_DATABASE=${STORAGE_TYPE_MYSQL_DATABASE:-"${APP_NAME}"} \
|
||||
STORAGE_TYPE_MYSQL_PORT=${STORAGE_TYPE_MYSQL_PORT:-"3306"} \
|
||||
CERTIFICATES_ALLOWMISMATCH=${CERTIFICATES_ALLOWMISMATCH:-"false"} \
|
||||
IPINFO_DEFAULT_COUNTRY=${IPINFO_DEFAULT_COUNTRY:-"US"} \
|
||||
DEVICE_SESSION_TIMEOUT=${DEVICE_SESSION_TIMEOUT:-"600"} \
|
||||
envsubst < /owgw.properties.tmpl > $OWGW_CONFIG/owgw.properties
|
||||
envsubst < /"${APP_NAME}".properties.tmpl > "${APP_CONFIG}"/"${APP_NAME}".properties
|
||||
fi
|
||||
|
||||
# Check if rtty_ui directory exists
|
||||
export RTTY_ASSETS=$(grep 'rtty.assets' $OWGW_CONFIG/owgw.properties | awk -F '=' '{print $2}' | xargs | envsubst)
|
||||
export RTTY_ASSETS=$(grep 'rtty.assets' "${APP_CONFIG}"/"${APP_NAME}".properties | awk -F '=' '{print $2}' | xargs | envsubst)
|
||||
|
||||
if [ -z "$RTTY_ASSETS" ]; then
|
||||
export RTTY_ASSETS="$OWGW_ROOT/rtty_ui"
|
||||
export RTTY_ASSETS="${APP_ROOT}/rtty_ui"
|
||||
fi
|
||||
|
||||
if [[ ! -d "$(dirname $RTTY_ASSETS)" ]]; then
|
||||
mkdir -p $(dirname $RTTY_ASSETS)
|
||||
mkdir -p "$(dirname $RTTY_ASSETS)"
|
||||
fi
|
||||
|
||||
if [[ ! -d "$RTTY_ASSETS" ]]; then
|
||||
cp -r /dist/rtty_ui $RTTY_ASSETS
|
||||
fi
|
||||
|
||||
if [ "$1" = '/openwifi/owgw' -a "$(id -u)" = '0' ]; then
|
||||
if [ "$1" = "${APP_HOME_DIR}/${APP_NAME}" -a "$(id -u)" = '0' ]; then
|
||||
if [ "$RUN_CHOWN" = 'true' ]; then
|
||||
chown -R "$OWGW_USER": "$OWGW_ROOT" "$OWGW_CONFIG"
|
||||
chown -R "$APP_USER": "${APP_ROOT}" "$APP_CONFIG"
|
||||
fi
|
||||
exec gosu "$OWGW_USER" "$@"
|
||||
exec gosu "$APP_USER" "$@"
|
||||
fi
|
||||
|
||||
exec "$@"
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
apiVersion: v2
|
||||
appVersion: "1.0"
|
||||
appVersion: "3.0.13"
|
||||
description: A Helm chart for Kubernetes
|
||||
name: owgw
|
||||
version: 0.1.0
|
||||
dependencies:
|
||||
- name: postgresql
|
||||
repository: https://tip.jfrog.io/artifactory/tip-wlan-cloud-ucentral-helm/
|
||||
version: 10.9.2
|
||||
condition: postgresql.enabled
|
||||
- name: mysql
|
||||
repository: https://tip.jfrog.io/artifactory/tip-wlan-cloud-ucentral-helm/
|
||||
version: 8.8.3
|
||||
condition: mysql.enabled
|
||||
- name: mariadb
|
||||
repository: https://tip.jfrog.io/artifactory/tip-wlan-cloud-ucentral-helm/
|
||||
version: 9.4.2
|
||||
condition: mariadb.enabled
|
||||
- name: postgresql
|
||||
repository: https://tip.jfrog.io/artifactory/tip-wlan-cloud-ucentral-helm/
|
||||
version: 10.9.2
|
||||
condition: postgresql.enabled
|
||||
- name: mysql
|
||||
repository: https://tip.jfrog.io/artifactory/tip-wlan-cloud-ucentral-helm/
|
||||
version: 8.8.3
|
||||
condition: mysql.enabled
|
||||
- name: mariadb
|
||||
repository: https://tip.jfrog.io/artifactory/tip-wlan-cloud-ucentral-helm/
|
||||
version: 9.4.2
|
||||
condition: mariadb.enabled
|
||||
|
||||
@@ -2,24 +2,21 @@
|
||||
replicaCount: 1
|
||||
strategyType: Recreate
|
||||
revisionHistoryLimit: 2
|
||||
|
||||
nameOverride: ""
|
||||
fullnameOverride: ""
|
||||
|
||||
images:
|
||||
owgw:
|
||||
repository: tip-tip-wlan-cloud-ucentral.jfrog.io/owgw
|
||||
tag: master
|
||||
repository: 471112855615.dkr.ecr.us-east-1.amazonaws.com/owgw
|
||||
tag: kv3.0.13
|
||||
pullPolicy: Always
|
||||
# regcred:
|
||||
# registry: tip-tip-wlan-cloud-ucentral.jfrog.io
|
||||
# username: username
|
||||
# password: password
|
||||
# regcred:
|
||||
# registry: tip-tip-wlan-cloud-ucentral.jfrog.io
|
||||
# username: username
|
||||
# password: password
|
||||
dockerize:
|
||||
repository: tip-tip-wlan-cloud-ucentral.jfrog.io/dockerize
|
||||
tag: 0.16.0
|
||||
repository: 471112855615.dkr.ecr.us-east-1.amazonaws.com/wait-ready
|
||||
tag: latest
|
||||
pullPolicy: IfNotPresent
|
||||
|
||||
services:
|
||||
owgw:
|
||||
type: ClusterIP
|
||||
@@ -62,7 +59,6 @@ services:
|
||||
servicePort: 3799
|
||||
targetPort: 3799
|
||||
protocol: UDP
|
||||
|
||||
checks:
|
||||
owgw:
|
||||
liveness:
|
||||
@@ -73,33 +69,31 @@ checks:
|
||||
exec:
|
||||
command:
|
||||
- /readiness_check
|
||||
|
||||
ingresses:
|
||||
restapi:
|
||||
enabled: false
|
||||
annotations: {}
|
||||
# kubernetes.io/ingress.class: nginx
|
||||
# kubernetes.io/tls-acme: "true"
|
||||
# kubernetes.io/ingress.class: nginx
|
||||
# kubernetes.io/tls-acme: "true"
|
||||
hosts:
|
||||
- restapi.chart-example.local
|
||||
- restapi.chart-example.local
|
||||
paths:
|
||||
- path: /
|
||||
pathType: ImplementationSpecific
|
||||
serviceName: owgw
|
||||
servicePort: restapi
|
||||
- path: /
|
||||
pathType: ImplementationSpecific
|
||||
serviceName: owgw
|
||||
servicePort: restapi
|
||||
fileuploader:
|
||||
enabled: false
|
||||
annotations: {}
|
||||
# kubernetes.io/ingress.class: nginx
|
||||
# kubernetes.io/tls-acme: "true"
|
||||
# kubernetes.io/ingress.class: nginx
|
||||
# kubernetes.io/tls-acme: "true"
|
||||
hosts:
|
||||
- fileuploader.chart-example.local
|
||||
- fileuploader.chart-example.local
|
||||
paths:
|
||||
- path: /
|
||||
pathType: ImplementationSpecific
|
||||
serviceName: owgw
|
||||
servicePort: fileuploader
|
||||
|
||||
- path: /
|
||||
pathType: ImplementationSpecific
|
||||
serviceName: owgw
|
||||
servicePort: fileuploader
|
||||
volumes:
|
||||
owgw:
|
||||
- name: config
|
||||
@@ -125,18 +119,17 @@ volumes:
|
||||
volumeDefinition: |
|
||||
persistentVolumeClaim:
|
||||
claimName: {{ template "owgw.fullname" . }}-pvc
|
||||
|
||||
resources: {}
|
||||
# We usually recommend not to specify default resources and to leave this as a conscious
|
||||
# choice for the user. This also increases chances charts run on environments with little
|
||||
# resources, such as Minikube. If you do want to specify resources, uncomment the following
|
||||
# lines, adjust them as necessary, and remove the curly braces after 'resources:'.
|
||||
# requests:
|
||||
# cpu: 100m
|
||||
# memory: 128Mi
|
||||
# limits:
|
||||
# cpu: 100m
|
||||
# memory: 128Mi
|
||||
# We usually recommend not to specify default resources and to leave this as a conscious
|
||||
# choice for the user. This also increases chances charts run on environments with little
|
||||
# resources, such as Minikube. If you do want to specify resources, uncomment the following
|
||||
# lines, adjust them as necessary, and remove the curly braces after 'resources:'.
|
||||
# requests:
|
||||
# cpu: 100m
|
||||
# memory: 128Mi
|
||||
# limits:
|
||||
# cpu: 100m
|
||||
# memory: 128Mi
|
||||
|
||||
securityContext:
|
||||
fsGroup: 1000
|
||||
@@ -151,18 +144,12 @@ securityContext:
|
||||
# value: "2"
|
||||
#- name: net.ipv4.tcp_keepalive_time
|
||||
# value: "45"
|
||||
|
||||
nodeSelector: {}
|
||||
|
||||
tolerations: []
|
||||
|
||||
affinity: {}
|
||||
|
||||
podAnnotations: {}
|
||||
|
||||
podSecurityPolicy:
|
||||
enabled: false
|
||||
|
||||
persistence:
|
||||
enabled: true
|
||||
# storageClassName: "-"
|
||||
@@ -170,7 +157,6 @@ persistence:
|
||||
- ReadWriteOnce
|
||||
size: 10Gi
|
||||
annotations: {}
|
||||
|
||||
# Application
|
||||
public_env_variables:
|
||||
OWGW_ROOT: /owgw-data
|
||||
@@ -180,12 +166,10 @@ public_env_variables:
|
||||
# NOTE in order for readiness check to use system info you need to set READINESS_METHOD to "systeminfo" and set OWSEC to the OWSEC's REST API endpoint
|
||||
#READINESS_METHOD: systeminfo
|
||||
#OWSEC: gw-qa01.cicd.lab.wlan.tip.build:16001
|
||||
|
||||
secret_env_variables:
|
||||
# NOTE in order for readiness check to use system info method you need to override these values to the real OWSEC credentials
|
||||
OWSEC_USERNAME: tip@ucentral.com
|
||||
OWSEC_PASSWORD: openwifi
|
||||
|
||||
configProperties:
|
||||
# -> Public part
|
||||
# Websocket
|
||||
@@ -310,7 +294,6 @@ configProperties:
|
||||
archiver.db.2.keep: 7
|
||||
archiver.db.3.name: commandlist
|
||||
archiver.db.3.keep: 7
|
||||
|
||||
# -> Secret part
|
||||
# Websocket
|
||||
ucentral.websocket.host.0.key.password: mypassword
|
||||
@@ -332,10 +315,8 @@ configProperties:
|
||||
## MySQL
|
||||
storage.type.mysql.username: stephb
|
||||
storage.type.mysql.password: snoopy99
|
||||
|
||||
# NOTE: List of required certificates may be found in "certs" key. Alternative way to pass required certificates is to create external secret with all required certificates and set secret name in "existingCertsSecret" key. Details may be found in https://github.com/Telecominfraproject/wlan-cloud-ucentral-deploy/tree/main/chart#tldr
|
||||
existingCertsSecret: ""
|
||||
|
||||
certs:
|
||||
clientcas.pem: ""
|
||||
issuer.pem: ""
|
||||
@@ -345,66 +326,53 @@ certs:
|
||||
root.pem: ""
|
||||
websocket-cert.pem: ""
|
||||
websocket-key.pem: ""
|
||||
|
||||
certsCAs:
|
||||
issuer.pem: ""
|
||||
root.pem: ""
|
||||
|
||||
# PostgreSQL (https://github.com/bitnami/charts/tree/master/bitnami/postgresql)
|
||||
postgresql:
|
||||
enabled: false
|
||||
|
||||
image:
|
||||
registry: docker.io
|
||||
repository: bitnami/postgresql
|
||||
tag: 11.13.0-debian-10-r0
|
||||
|
||||
postgresqlPostgresPassword: "rootPassword"
|
||||
postgresqlUsername: stephb
|
||||
postgresqlPassword: snoopy99
|
||||
postgresqlDatabase: owgw
|
||||
|
||||
persistence:
|
||||
enabled: true
|
||||
storageClass: ""
|
||||
size: 8Gi
|
||||
|
||||
# MySQL (https://github.com/bitnami/charts/tree/master/bitnami/mysql)
|
||||
mysql:
|
||||
enabled: false
|
||||
|
||||
image:
|
||||
registry: docker.io
|
||||
repository: bitnami/mysql
|
||||
tag: 8.0.26-debian-10-r10
|
||||
|
||||
auth:
|
||||
rootPassword: rootPassword
|
||||
database: owgw
|
||||
username: stephb
|
||||
password: snoopy99
|
||||
|
||||
primary:
|
||||
persistence:
|
||||
enabled: true
|
||||
storageClass: ""
|
||||
size: 8Gi
|
||||
|
||||
# MariaDB (https://github.com/bitnami/charts/tree/master/bitnami/mariadb)
|
||||
mariadb:
|
||||
enabled: false
|
||||
|
||||
image:
|
||||
registry: docker.io
|
||||
repository: bitnami/mariadb
|
||||
tag: 10.5.12-debian-10-r0
|
||||
|
||||
auth:
|
||||
rootPassword: rootPassword
|
||||
database: owgw
|
||||
username: stephb
|
||||
password: snoopy99
|
||||
|
||||
primary:
|
||||
persistence:
|
||||
enabled: true
|
||||
|
||||
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
|
||||
}
|
||||
@@ -2,7 +2,7 @@ openapi: 3.0.1
|
||||
info:
|
||||
title: uCentral gateway API
|
||||
description: A process to manage configuration for devices.
|
||||
version: 2.10.0
|
||||
version: 2.11.0
|
||||
license:
|
||||
name: BSD3
|
||||
url: https://github.com/Telecominfraproject/wlan-cloud-ucentralgw/blob/master/LICENSE
|
||||
@@ -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:
|
||||
@@ -553,6 +563,35 @@ components:
|
||||
items:
|
||||
$ref : '#/components/schemas/DefaultConfiguration'
|
||||
|
||||
DefaultFirmware:
|
||||
type: object
|
||||
properties:
|
||||
deviceType:
|
||||
type: string
|
||||
description:
|
||||
type: string
|
||||
uri:
|
||||
type: string
|
||||
revision:
|
||||
type: string
|
||||
imageCreationDate:
|
||||
type: integer
|
||||
format: int64
|
||||
created:
|
||||
type: integer
|
||||
format: int64
|
||||
lastModified:
|
||||
type: integer
|
||||
format: int64
|
||||
|
||||
DefaultFirmwareList:
|
||||
type: object
|
||||
properties:
|
||||
firmwares:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/DefaultFirmware'
|
||||
|
||||
UpgradeRequest:
|
||||
type: object
|
||||
properties:
|
||||
@@ -874,6 +913,114 @@ components:
|
||||
kafkaClients:
|
||||
type: integer
|
||||
|
||||
RRM_Kick:
|
||||
type: object
|
||||
properties:
|
||||
action:
|
||||
type: string
|
||||
enum:
|
||||
- kick
|
||||
addr:
|
||||
type: string
|
||||
format: mac
|
||||
reason:
|
||||
type: integer
|
||||
default: 5
|
||||
ban_time:
|
||||
type: integer
|
||||
format: int64
|
||||
|
||||
RRM_channel_switch:
|
||||
type: object
|
||||
properties:
|
||||
action:
|
||||
type: string
|
||||
enum:
|
||||
- channel_switch
|
||||
bssid:
|
||||
type: string
|
||||
format: mac
|
||||
channel:
|
||||
type: integer
|
||||
|
||||
RRM_tx_power:
|
||||
type: object
|
||||
properties:
|
||||
action:
|
||||
type: string
|
||||
enum:
|
||||
- tx_power
|
||||
bssid:
|
||||
type: string
|
||||
format: mac
|
||||
level:
|
||||
type: integer
|
||||
|
||||
RRM_beacon_request:
|
||||
type: object
|
||||
properties:
|
||||
action:
|
||||
type: string
|
||||
enum:
|
||||
- beacon_request
|
||||
addr:
|
||||
type: string
|
||||
format: mac
|
||||
ssid:
|
||||
type: string
|
||||
channel:
|
||||
type: integer
|
||||
|
||||
RRM_bss_transition:
|
||||
type: object
|
||||
properties:
|
||||
action:
|
||||
type: string
|
||||
enum:
|
||||
- bss_transition
|
||||
addr:
|
||||
type: string
|
||||
format: mac
|
||||
neighbors:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
format: mac
|
||||
|
||||
RRM_neighbors:
|
||||
type: object
|
||||
properties:
|
||||
action:
|
||||
type: string
|
||||
enum:
|
||||
- neighbors
|
||||
bssid:
|
||||
type: string
|
||||
format: mac
|
||||
neighbors:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
format: mac
|
||||
|
||||
RRM_action:
|
||||
type: object
|
||||
oneOf:
|
||||
- $ref: '#/components/schemas/RRM_Kick'
|
||||
- $ref: '#/components/schemas/RRM_channel_switch'
|
||||
- $ref: '#/components/schemas/RRM_tx_power'
|
||||
- $ref: '#/components/schemas/RRM_beacon_request'
|
||||
- $ref: '#/components/schemas/RRM_bss_transition'
|
||||
- $ref: '#/components/schemas/RRM_neighbors'
|
||||
|
||||
RRM_actions:
|
||||
type: object
|
||||
properties:
|
||||
actions:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/RRM_action'
|
||||
|
||||
#########################################################################################
|
||||
##
|
||||
## These are endpoints that all services in the uCentral stack must provide
|
||||
@@ -942,12 +1089,6 @@ components:
|
||||
- $ref: '#/components/schemas/StringList'
|
||||
- $ref: '#/components/schemas/TagValuePairList'
|
||||
|
||||
SystemCommandResults:
|
||||
type: object
|
||||
oneOf:
|
||||
- $ref: '#/components/schemas/StringList'
|
||||
- $ref: '#/components/schemas/TagValuePairList'
|
||||
|
||||
NoteInfo:
|
||||
type: object
|
||||
properties:
|
||||
@@ -987,6 +1128,33 @@ components:
|
||||
type: integer
|
||||
format: int64
|
||||
|
||||
SystemResources:
|
||||
type: object
|
||||
properties:
|
||||
numberOfFileDescriptors:
|
||||
type: integer
|
||||
format: int64
|
||||
currRealMem:
|
||||
type: integer
|
||||
format: int64
|
||||
peakRealMem:
|
||||
type: integer
|
||||
format: int64
|
||||
currVirtMem:
|
||||
type: integer
|
||||
format: int64
|
||||
peakVirtMem:
|
||||
type: integer
|
||||
format: int64
|
||||
|
||||
SystemCommandResults:
|
||||
type: object
|
||||
oneOf:
|
||||
- $ref: '#/components/schemas/SystemResources'
|
||||
- $ref: '#/components/schemas/SystemInfoResults'
|
||||
- $ref: '#/components/schemas/StringList'
|
||||
- $ref: '#/components/schemas/TagValuePairList'
|
||||
|
||||
SystemCommandSetLogLevel:
|
||||
type: object
|
||||
properties:
|
||||
@@ -1289,6 +1457,30 @@ components:
|
||||
$ref: '#/components/schemas/RadiusProxyServerConfig'
|
||||
coaConfig:
|
||||
$ref: '#/components/schemas/RadiusProxyServerConfig'
|
||||
radsecPoolType:
|
||||
type: string
|
||||
enum:
|
||||
- generic
|
||||
- orion
|
||||
- globalreach
|
||||
- radsec
|
||||
default:
|
||||
generic
|
||||
poolProxyIp:
|
||||
type: string
|
||||
description: This is the fake IP for the entire pool
|
||||
example:
|
||||
- These addresses must match the addresses in the AP configuration and must start with 0.0
|
||||
- 0.0.0.1
|
||||
- 0.0.1.1
|
||||
radsecPoolKeepAlive:
|
||||
type: integer
|
||||
description: The keep alive value in seconds. Usually 30s or less.
|
||||
format: int64
|
||||
default: 25
|
||||
enabled:
|
||||
type: boolean
|
||||
default: true
|
||||
|
||||
RadiusProxyPoolList:
|
||||
type: object
|
||||
@@ -1358,6 +1550,55 @@ components:
|
||||
type: string
|
||||
chargeableUserIdentity:
|
||||
type: string
|
||||
userName:
|
||||
type: string
|
||||
|
||||
DeviceTransferRequest:
|
||||
type: object
|
||||
properties:
|
||||
serialNumber:
|
||||
type: string
|
||||
format: uuid
|
||||
server:
|
||||
type: string
|
||||
format: hostname
|
||||
port:
|
||||
type: integer
|
||||
format: int32
|
||||
|
||||
DeviceCertificateUpdateRequest:
|
||||
type: object
|
||||
properties:
|
||||
serialNumber:
|
||||
type: string
|
||||
encodedCertificate:
|
||||
type: string
|
||||
format: base64
|
||||
description: This is a base64 encoded string of the certificate bundle (the current bundle .tar.gz file from the PKI portal)
|
||||
|
||||
PowerCycleRequest:
|
||||
type: object
|
||||
properties:
|
||||
serial:
|
||||
type: string
|
||||
when:
|
||||
type: integer
|
||||
format: int64
|
||||
ports:
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
properties:
|
||||
name:
|
||||
type: string
|
||||
example:
|
||||
- Ethernet0
|
||||
cycle:
|
||||
type: integer
|
||||
default: 10000
|
||||
minimum: 1
|
||||
maximum: 60000
|
||||
description: off time in milliseconds
|
||||
|
||||
paths:
|
||||
/devices:
|
||||
@@ -1450,6 +1691,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
|
||||
@@ -1505,8 +1762,12 @@ paths:
|
||||
type: integer
|
||||
format: int64
|
||||
required: false
|
||||
|
||||
|
||||
- in: query
|
||||
description: Filter the results
|
||||
name: simulatedDevices
|
||||
schema:
|
||||
type: boolean
|
||||
required: false
|
||||
responses:
|
||||
200:
|
||||
$ref: '#/components/responses/Success'
|
||||
@@ -1771,6 +2032,123 @@ paths:
|
||||
404:
|
||||
$ref: '#/components/responses/NotFound'
|
||||
|
||||
/default_firmwares:
|
||||
get:
|
||||
tags:
|
||||
- Firmware
|
||||
summary: Retrieve the lists of all default firmwares.
|
||||
description: Retrieve the lists of all default firmwares.
|
||||
operationId: getDefaultFirmwares
|
||||
|
||||
responses:
|
||||
200:
|
||||
description: List of default firmwares
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/DefaultFirmwareList'
|
||||
403:
|
||||
$ref: '#/components/responses/Unauthorized'
|
||||
404:
|
||||
$ref: '#/components/responses/NotFound'
|
||||
|
||||
/default_firmware/{deviceType}:
|
||||
get:
|
||||
tags:
|
||||
- Firmware
|
||||
summary: Retrieve a default firmware.
|
||||
description: Retrieve a default firmware.
|
||||
operationId: getDefaultFirmware
|
||||
parameters:
|
||||
- in: path
|
||||
name: deviceType
|
||||
schema:
|
||||
type: string
|
||||
required: true
|
||||
responses:
|
||||
200:
|
||||
description: Default firmware included
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/DefaultFirmware'
|
||||
403:
|
||||
$ref: '#/components/responses/Unauthorized'
|
||||
404:
|
||||
$ref: '#/components/responses/NotFound'
|
||||
|
||||
post:
|
||||
tags:
|
||||
- Firmware
|
||||
summary: Create a default firmware.
|
||||
description: Create a default firmware.
|
||||
operationId: createDefaultFirmware
|
||||
parameters:
|
||||
- in: path
|
||||
name: deviceType
|
||||
schema:
|
||||
type: string
|
||||
required: true
|
||||
requestBody:
|
||||
description: Information used to create the new firmware entry
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/DefaultFirmware'
|
||||
responses:
|
||||
200:
|
||||
$ref: '#/components/responses/Success'
|
||||
403:
|
||||
$ref: '#/components/responses/Unauthorized'
|
||||
404:
|
||||
$ref: '#/components/responses/NotFound'
|
||||
|
||||
delete:
|
||||
tags:
|
||||
- Firmware
|
||||
summary: Delete a default default firmware
|
||||
description: Delete a default default firmware
|
||||
operationId: deleteDefaultFirmware
|
||||
parameters:
|
||||
- in: path
|
||||
name: deviceType
|
||||
schema:
|
||||
type: string
|
||||
required: true
|
||||
responses:
|
||||
204:
|
||||
$ref: '#/components/responses/Success'
|
||||
403:
|
||||
$ref: '#/components/responses/Unauthorized'
|
||||
404:
|
||||
$ref: '#/components/responses/NotFound'
|
||||
|
||||
put:
|
||||
tags:
|
||||
- Firmware
|
||||
summary: Update a default firmware
|
||||
description: Update a default firmware
|
||||
operationId: updateDefaultFirmware
|
||||
parameters:
|
||||
- in: path
|
||||
name: deviceType
|
||||
schema:
|
||||
type: string
|
||||
required: true
|
||||
requestBody:
|
||||
description: Firmware details
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/DefaultFirmware'
|
||||
responses:
|
||||
200:
|
||||
$ref: '#/components/responses/Success'
|
||||
403:
|
||||
$ref: '#/components/responses/Unauthorized'
|
||||
404:
|
||||
$ref: '#/components/responses/NotFound'
|
||||
|
||||
/device/{serialNumber}:
|
||||
get:
|
||||
tags:
|
||||
@@ -2382,7 +2760,7 @@ paths:
|
||||
404:
|
||||
$ref: '#/components/responses/NotFound'
|
||||
|
||||
/device/{serialNumber}/:
|
||||
/device/{serialNumber}/script:
|
||||
post:
|
||||
tags:
|
||||
- Commands
|
||||
@@ -2596,6 +2974,116 @@ paths:
|
||||
404:
|
||||
$ref: '#/components/responses/NotFound'
|
||||
|
||||
/device/{serialNumber}/rrm:
|
||||
post:
|
||||
tags:
|
||||
- Commands
|
||||
summary: Send RRM commands to a device.
|
||||
operationId: sendRRMcommandsForADevice
|
||||
parameters:
|
||||
- in: path
|
||||
name: serialNumber
|
||||
schema:
|
||||
type: string
|
||||
required: true
|
||||
requestBody:
|
||||
description: Commands to send
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/RRM_actions'
|
||||
responses:
|
||||
200:
|
||||
$ref: '#/components/responses/Success'
|
||||
403:
|
||||
$ref: '#/components/responses/Unauthorized'
|
||||
404:
|
||||
$ref: '#/components/responses/NotFound'
|
||||
|
||||
/device/{serialNumber}/transfer:
|
||||
post:
|
||||
tags:
|
||||
- Commands
|
||||
summary: Transfer a device to a new redirector.
|
||||
operationId: transferDevice
|
||||
parameters:
|
||||
- in: path
|
||||
name: serialNumber
|
||||
schema:
|
||||
type: string
|
||||
required: true
|
||||
requestBody:
|
||||
description: Transfer details
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/DeviceTransferRequest'
|
||||
responses:
|
||||
200:
|
||||
$ref: '#/components/responses/Success'
|
||||
403:
|
||||
$ref: '#/components/responses/Unauthorized'
|
||||
404:
|
||||
$ref: '#/components/responses/NotFound'
|
||||
|
||||
/device/{serialNumber}/certupdate:
|
||||
post:
|
||||
tags:
|
||||
- Commands
|
||||
summary: Update the certificates for a device.
|
||||
operationId: updateCertificates
|
||||
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/DeviceCertificateUpdateRequest'
|
||||
responses:
|
||||
200:
|
||||
$ref: '#/components/responses/Success'
|
||||
403:
|
||||
$ref: '#/components/responses/Unauthorized'
|
||||
404:
|
||||
$ref: '#/components/responses/NotFound'
|
||||
|
||||
/device/{serialNumber}/powercycle:
|
||||
post:
|
||||
tags:
|
||||
- Commands
|
||||
summary: Perform PoE power cycle for some PoE ports.
|
||||
operationId: performPowerCycle
|
||||
parameters:
|
||||
- in: path
|
||||
name: serialNumber
|
||||
schema:
|
||||
type: string
|
||||
required: true
|
||||
requestBody:
|
||||
description: Certificate update details
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/PowerCycleRequest'
|
||||
responses:
|
||||
200:
|
||||
$ref: '#/components/responses/Success'
|
||||
403:
|
||||
$ref: '#/components/responses/Unauthorized'
|
||||
404:
|
||||
$ref: '#/components/responses/NotFound'
|
||||
|
||||
/ouis:
|
||||
get:
|
||||
tags:
|
||||
@@ -3086,6 +3574,7 @@ paths:
|
||||
type: string
|
||||
enum:
|
||||
- coadm
|
||||
- disconnectUser
|
||||
requestBody:
|
||||
description: operationParameters
|
||||
content:
|
||||
@@ -3101,8 +3590,6 @@ paths:
|
||||
404:
|
||||
$ref: '#/components/responses/NotFound'
|
||||
|
||||
|
||||
|
||||
/deviceDashboard:
|
||||
get:
|
||||
tags:
|
||||
@@ -3199,16 +3686,12 @@ paths:
|
||||
type: string
|
||||
enum:
|
||||
- info
|
||||
- extraConfiguration
|
||||
- resources
|
||||
required: true
|
||||
|
||||
responses:
|
||||
200:
|
||||
description: Successful command execution
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
oneOf:
|
||||
- $ref: '#/components/schemas/SystemInfoResults'
|
||||
$ref: '#/components/schemas/SystemCommandResults'
|
||||
403:
|
||||
$ref: '#/components/responses/Unauthorized'
|
||||
404:
|
||||
|
||||
@@ -145,7 +145,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}
|
||||
|
||||
15
package.json
Normal file
15
package.json
Normal file
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"name": "owgw",
|
||||
"version": "3.0.13",
|
||||
"description": "This is the Kinara version of OpenWifi OWGW",
|
||||
"author": "Kinara Systems",
|
||||
"homepage": "https://kinarasystems.com",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/kinarasystems/wlan-cloud-ucentralgw"
|
||||
},
|
||||
"keywords": [
|
||||
"owgw",
|
||||
"gateway"
|
||||
]
|
||||
}
|
||||
@@ -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,49 @@
|
||||
// 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/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) {
|
||||
|
||||
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,28 +54,86 @@ namespace OpenWifi {
|
||||
WS_->setNoDelay(false);
|
||||
WS_->setKeepAlive(true);
|
||||
WS_->setBlocking(false);
|
||||
uuid_ = MicroServiceRandom(std::numeric_limits<std::uint64_t>::max()-1);
|
||||
|
||||
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_Server()->IncrementConnectionCount();
|
||||
}
|
||||
|
||||
void AP_WS_Connection::Start() {
|
||||
Registered_ = true;
|
||||
Valid_ = 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 =
|
||||
@@ -97,7 +148,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;
|
||||
}
|
||||
|
||||
@@ -110,7 +160,6 @@ namespace OpenWifi {
|
||||
Logger_,
|
||||
fmt::format("TLS-CONNECTION({}): Session={} No certificates available..", CId_,
|
||||
State_.sessionId));
|
||||
EndConnection();
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -121,11 +170,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_,
|
||||
@@ -135,30 +192,27 @@ 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_);
|
||||
|
||||
poco_trace(Logger_,
|
||||
fmt::format("TLS-CONNECTION({}): Session={} CN={} Completed. (t={})", CId_,
|
||||
@@ -222,151 +276,14 @@ namespace OpenWifi {
|
||||
return false;
|
||||
}
|
||||
|
||||
static void NotifyKafkaDisconnect(const std::string &SerialNumber) {
|
||||
try {
|
||||
Poco::JSON::Object Disconnect;
|
||||
Poco::JSON::Object Details;
|
||||
Details.set(uCentralProtocol::SERIALNUMBER, SerialNumber);
|
||||
Details.set(uCentralProtocol::TIMESTAMP, Utils::Now());
|
||||
Disconnect.set(uCentralProtocol::DISCONNECTION, Details);
|
||||
Poco::JSON::Stringifier Stringify;
|
||||
std::ostringstream OS;
|
||||
Stringify.condense(Disconnect, OS);
|
||||
KafkaManager()->PostMessage(KafkaTopics::CONNECTION, SerialNumber, std::make_shared<std::string>(OS.str()));
|
||||
} catch (...) {
|
||||
}
|
||||
}
|
||||
|
||||
AP_WS_Connection::~AP_WS_Connection() {
|
||||
Valid_ = false;
|
||||
EndConnection();
|
||||
}
|
||||
|
||||
void DeviceDisconnectionCleanup(const std::string &SerialNumber) {
|
||||
void AP_WS_Connection::DeviceDisconnectionCleanup(const std::string &SerialNumber, std::uint64_t uuid) {
|
||||
if (KafkaManager()->Enabled()) {
|
||||
NotifyKafkaDisconnect(SerialNumber);
|
||||
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_);
|
||||
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 +364,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 +495,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 +521,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,49 +561,50 @@ 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::ProcessIncomingFrame() {
|
||||
Poco::Buffer<char> IncomingFrame(0);
|
||||
|
||||
bool KillConnection=false;
|
||||
try {
|
||||
int Op, flags;
|
||||
int Op, flags;
|
||||
auto IncomingSize = WS_->receiveFrame(IncomingFrame, flags);
|
||||
|
||||
Op = flags & Poco::Net::WebSocket::FRAME_OP_BITMASK;
|
||||
@@ -706,84 +624,81 @@ namespace OpenWifi {
|
||||
State_.LastContact = Utils::Now();
|
||||
|
||||
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 |
|
||||
(int)Poco::Net::WebSocket::FRAME_FLAG_FIN);
|
||||
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 |
|
||||
(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("locale", State_.locale);
|
||||
PingObject.set(uCentralProtocol::PING, PingDetails);
|
||||
Poco::JSON::Stringifier Stringify;
|
||||
std::ostringstream OS;
|
||||
Stringify.condense(PingObject, OS);
|
||||
KafkaManager()->PostMessage(KafkaTopics::CONNECTION, SerialNumber_, std::make_shared<std::string>(OS.str()));
|
||||
}
|
||||
return;
|
||||
} break;
|
||||
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);
|
||||
}
|
||||
} 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_PONG: {
|
||||
poco_trace(Logger_, fmt::format("PONG({}): received and ignored.", CId_));
|
||||
} break;
|
||||
|
||||
case Poco::Net::WebSocket::FRAME_OP_TEXT: {
|
||||
poco_trace(Logger_,
|
||||
fmt::format("FRAME({}): Frame received (length={}, flags={}). Msg={}",
|
||||
CId_, IncomingSize, flags, IncomingFrame.begin()));
|
||||
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>();
|
||||
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);
|
||||
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("INVALID-PAYLOAD({}): Payload is not JSON-RPC 2.0: {}",
|
||||
CId_, IncomingFrame.begin()));
|
||||
fmt::format("FRAME({}): illegal transaction header, missing 'jsonrpc': {}",
|
||||
CId_, iS.str()));
|
||||
Errors_++;
|
||||
}
|
||||
} 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_));
|
||||
} 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;
|
||||
}
|
||||
} catch (const Poco::Net::ConnectionResetException &E) {
|
||||
poco_warning(Logger_,
|
||||
@@ -791,21 +706,21 @@ namespace OpenWifi {
|
||||
CId_, E.displayText(),
|
||||
IncomingFrame.begin() == nullptr ? "" : IncomingFrame.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(),
|
||||
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(),
|
||||
State_.sessionId));
|
||||
return EndConnection();
|
||||
KillConnection=true;
|
||||
} catch (const Poco::Net::SSLConnectionUnexpectedlyClosedException &E) {
|
||||
poco_warning(
|
||||
Logger_,
|
||||
@@ -814,54 +729,54 @@ namespace OpenWifi {
|
||||
CId_, E.displayText(),
|
||||
IncomingFrame.begin() == nullptr ? "" : IncomingFrame.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(),
|
||||
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(),
|
||||
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(),
|
||||
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(),
|
||||
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(),
|
||||
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) {
|
||||
@@ -954,24 +869,55 @@ namespace OpenWifi {
|
||||
|
||||
void AP_WS_Connection::ProcessIncomingRadiusData(const Poco::JSON::Object::Ptr &Doc) {
|
||||
if (Doc->has(uCentralProtocol::RADIUSDATA)) {
|
||||
std::string secret;
|
||||
auto Type = Doc->get(uCentralProtocol::RADIUS).toString();
|
||||
if (Type == uCentralProtocol::RADIUSACCT) {
|
||||
auto Data = Doc->get(uCentralProtocol::RADIUSDATA).toString();
|
||||
auto DecodedData = Base64Decode(Data);
|
||||
RADIUS_proxy_server()->SendAccountingData(SerialNumber_, DecodedData.c_str(),
|
||||
DecodedData.size(),secret);
|
||||
DecodedData.size());
|
||||
} else if (Type == uCentralProtocol::RADIUSAUTH) {
|
||||
auto Data = Doc->get(uCentralProtocol::RADIUSDATA).toString();
|
||||
auto DecodedData = Base64Decode(Data);
|
||||
RADIUS_proxy_server()->SendAuthenticationData(SerialNumber_, DecodedData.c_str(),
|
||||
DecodedData.size(), secret);
|
||||
DecodedData.size());
|
||||
} else if (Type == uCentralProtocol::RADIUSCOA) {
|
||||
auto Data = Doc->get(uCentralProtocol::RADIUSDATA).toString();
|
||||
auto DecodedData = Base64Decode(Data);
|
||||
RADIUS_proxy_server()->SendCoAData(SerialNumber_, DecodedData.c_str(),
|
||||
DecodedData.size(), secret);
|
||||
DecodedData.size());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <shared_mutex>
|
||||
#include <mutex>
|
||||
#include <string>
|
||||
|
||||
#include "Poco/JSON/Object.h"
|
||||
@@ -14,8 +14,10 @@
|
||||
#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 {
|
||||
|
||||
@@ -25,16 +27,17 @@ namespace OpenWifi {
|
||||
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 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 +46,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 +59,33 @@ namespace OpenWifi {
|
||||
bool StopKafkaTelemetry(uint64_t RPCID);
|
||||
|
||||
inline void GetLastStats(std::string &LastStats) {
|
||||
std::shared_lock G(ConnectionMutex_);
|
||||
LastStats = RawLastStats_;
|
||||
}
|
||||
|
||||
inline void SetLastStats(const std::string &LastStats) {
|
||||
std::unique_lock 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::unique_lock G(ConnectionMutex_);
|
||||
RawLastHealthcheck_ = H;
|
||||
}
|
||||
|
||||
inline void GetLastHealthCheck(GWObjects::HealthCheck &H) {
|
||||
std::shared_lock G(ConnectionMutex_);
|
||||
H = RawLastHealthcheck_;
|
||||
if(!Dead_) {
|
||||
std::lock_guard G(ConnectionMutex_);
|
||||
H = RawLastHealthcheck_;
|
||||
}
|
||||
}
|
||||
|
||||
inline void GetState(GWObjects::ConnectionState &State) const {
|
||||
std::shared_lock 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 {
|
||||
std::shared_lock G(ConnectionMutex_);
|
||||
R = Restrictions_;
|
||||
inline GWObjects::DeviceRestrictions GetRestrictions() {
|
||||
std::lock_guard G(ConnectionMutex_);
|
||||
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 +105,14 @@ namespace OpenWifi {
|
||||
|
||||
friend class AP_WS_Server;
|
||||
|
||||
inline GWObjects::DeviceRestrictions Restrictions() const {
|
||||
std::shared_lock G(ConnectionMutex_);
|
||||
return Restrictions_;
|
||||
}
|
||||
|
||||
inline bool MustBeSecureRtty() const { return RttyMustBeSecure_; }
|
||||
void Start();
|
||||
|
||||
private:
|
||||
mutable std::shared_mutex ConnectionMutex_;
|
||||
std::shared_mutex TelemetryMutex_;
|
||||
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,32 +123,56 @@ 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;
|
||||
|
||||
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;
|
||||
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
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -21,11 +21,7 @@ namespace OpenWifi {
|
||||
|
||||
if (ParamsObj->has(uCentralProtocol::SERIAL) && ParamsObj->has(uCentralProtocol::DATA)) {
|
||||
if (KafkaManager()->Enabled()) {
|
||||
auto Data = ParamsObj->get(uCentralProtocol::DATA);
|
||||
Poco::JSON::Stringifier Stringify;
|
||||
std::ostringstream OS;
|
||||
Stringify.condense(ParamsObj, OS);
|
||||
KafkaManager()->PostMessage(KafkaTopics::ALERTS, SerialNumber_, std::make_shared<std::string>(OS.str()));
|
||||
KafkaManager()->PostMessage(KafkaTopics::ALERTS, SerialNumber_, *ParamsObj);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,6 +14,8 @@
|
||||
#include "framework/KafkaManager.h"
|
||||
#include "framework/utils.h"
|
||||
|
||||
#include "firmware_revision_cache.h"
|
||||
|
||||
#include "UI_GW_WebSocketNotifications.h"
|
||||
#include <GWKafkaEvents.h>
|
||||
|
||||
@@ -30,9 +32,7 @@ namespace OpenWifi {
|
||||
Event.set("type", "device.firmware_change");
|
||||
Event.set("timestamp", Utils::Now());
|
||||
Event.set("payload", EventDetails);
|
||||
std::ostringstream OS;
|
||||
Event.stringify(OS);
|
||||
KafkaManager()->PostMessage(KafkaTopics::DEVICE_EVENT_QUEUE, SerialNumber, std::make_shared<std::string>(OS.str()));
|
||||
KafkaManager()->PostMessage(KafkaTopics::DEVICE_EVENT_QUEUE, SerialNumber, Event);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -49,9 +49,7 @@ namespace OpenWifi {
|
||||
Event.set("type", "device.not_provisioned");
|
||||
Event.set("timestamp", Utils::Now());
|
||||
Event.set("payload", EventDetails);
|
||||
std::ostringstream OS;
|
||||
Event.stringify(OS);
|
||||
KafkaManager()->PostMessage(KafkaTopics::DEVICE_EVENT_QUEUE, SerialNumber, std::make_shared<std::string>(OS.str()));
|
||||
KafkaManager()->PostMessage(KafkaTopics::DEVICE_EVENT_QUEUE, SerialNumber, Event);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -63,14 +61,18 @@ namespace OpenWifi {
|
||||
auto Firmware = ParamsObj->get(uCentralProtocol::FIRMWARE).toString();
|
||||
auto Capabilities = ParamsObj->getObject(uCentralProtocol::CAPABILITIES);
|
||||
|
||||
std::string DevicePassword;
|
||||
if(ParamsObj->has("password")) {
|
||||
DevicePassword = ParamsObj->get("password").toString();
|
||||
}
|
||||
|
||||
SerialNumber_ = Serial;
|
||||
SerialNumberInt_ = Utils::SerialNumberToInt(SerialNumber_);
|
||||
|
||||
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();
|
||||
@@ -81,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();
|
||||
}
|
||||
@@ -97,25 +101,61 @@ 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");
|
||||
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) {
|
||||
StorageService()->CreateDefaultDevice(SerialNumber_, Caps, Firmware, PeerAddress_, State_.VerifiedCertificate==GWObjects::SIMULATED );
|
||||
// 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)) {
|
||||
Poco::JSON::Object UpgradeCommand, Params;
|
||||
UpgradeCommand.set(uCentralProtocol::JSONRPC,uCentralProtocol::JSONRPC_VERSION);
|
||||
UpgradeCommand.set(uCentralProtocol::METHOD,uCentralProtocol::UPGRADE);
|
||||
Params.set(uCentralProtocol::SERIALNUMBER, SerialNumber_);
|
||||
Params.set(uCentralProtocol::WHEN, 0);
|
||||
Params.set(uCentralProtocol::URI, MinimumFirmware.uri);
|
||||
Params.set(uCentralProtocol::KEEP_REDIRECTOR,1);
|
||||
UpgradeCommand.set(uCentralProtocol::PARAMS, Params);
|
||||
UpgradeCommand.set(uCentralProtocol::ID, 1);
|
||||
|
||||
std::ostringstream Command;
|
||||
UpgradeCommand.stringify(Command);
|
||||
if(Send(Command.str())) {
|
||||
poco_information(
|
||||
Logger(),
|
||||
fmt::format(
|
||||
"Forcing device {} to upgrade to {} before connection is allowed.",
|
||||
SerialNumber_, MinimumFirmware.revision));
|
||||
} else {
|
||||
poco_error(
|
||||
Logger(),
|
||||
fmt::format(
|
||||
"Could not force device {} to upgrade to {} before connection is allowed.",
|
||||
SerialNumber_, MinimumFirmware.revision));
|
||||
}
|
||||
return;
|
||||
} else {
|
||||
StorageService()->CreateDefaultDevice( DbSession_->Session(),
|
||||
SerialNumber_, Caps, Firmware, PeerAddress_,
|
||||
State_.VerifiedCertificate == GWObjects::SIMULATED);
|
||||
}
|
||||
} else if (!Daemon()->AutoProvisioning() && !DeviceExists) {
|
||||
SendKafkaDeviceNotProvisioned(SerialNumber_, Firmware, Compatible_, CId_);
|
||||
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) {
|
||||
@@ -135,6 +175,17 @@ namespace OpenWifi {
|
||||
}
|
||||
}
|
||||
|
||||
if(ParamsObj->has("reason")) {
|
||||
State_.connectReason = ParamsObj->get("reason").toString();
|
||||
DeviceInfo.connectReason = State_.connectReason;
|
||||
++Updated;
|
||||
}
|
||||
|
||||
if(DeviceInfo.DevicePassword!=DevicePassword) {
|
||||
DeviceInfo.DevicePassword = DevicePassword.empty() ? "openwifi" : DevicePassword ;
|
||||
++Updated;
|
||||
}
|
||||
|
||||
if (DeviceInfo.lastRecordedContact==0) {
|
||||
DeviceInfo.lastRecordedContact = Utils::Now();
|
||||
++Updated;
|
||||
@@ -155,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;
|
||||
}
|
||||
|
||||
@@ -170,13 +226,21 @@ namespace OpenWifi {
|
||||
++Updated;
|
||||
}
|
||||
|
||||
if (Updated) {
|
||||
StorageService()->UpdateDevice(DeviceInfo);
|
||||
if(DeviceInfo.certificateExpiryDate!=State_.certificateExpiryDate) {
|
||||
DeviceInfo.certificateExpiryDate = State_.certificateExpiryDate;
|
||||
++Updated;
|
||||
}
|
||||
|
||||
if (Updated) {
|
||||
StorageService()->UpdateDevice(DbSession_->Session(), DeviceInfo);
|
||||
}
|
||||
}
|
||||
|
||||
if(!Simulated_) {
|
||||
uint64_t UpgradedUUID = 0;
|
||||
LookForUpgrade(UUID, UpgradedUUID);
|
||||
State_.UUID = UpgradedUUID;
|
||||
if (LookForUpgrade(DbSession_->Session(), UUID, UpgradedUUID)) {
|
||||
State_.UUID = UpgradedUUID;
|
||||
}
|
||||
}
|
||||
|
||||
State_.Compatible = Compatible_;
|
||||
@@ -225,14 +289,11 @@ namespace OpenWifi {
|
||||
GWWebSocketNotifications::DeviceConnected(Notification);
|
||||
|
||||
if (KafkaManager()->Enabled()) {
|
||||
Poco::JSON::Stringifier Stringify;
|
||||
|
||||
ParamsObj->set(uCentralProtocol::CONNECTIONIP, CId_);
|
||||
ParamsObj->set("locale", State_.locale);
|
||||
ParamsObj->set(uCentralProtocol::TIMESTAMP, Utils::Now());
|
||||
std::ostringstream OS;
|
||||
Stringify.condense(ParamsObj, OS);
|
||||
KafkaManager()->PostMessage(KafkaTopics::CONNECTION, SerialNumber_, std::make_shared<std::string>(OS.str()));
|
||||
ParamsObj->set(uCentralProtocol::UUID, uuid_);
|
||||
KafkaManager()->PostMessage(KafkaTopics::CONNECTION, SerialNumber_, *ParamsObj);
|
||||
}
|
||||
} else {
|
||||
poco_warning(
|
||||
|
||||
@@ -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,10 +21,10 @@ 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("DEVICEUPDATE({}): Device is updating its login password.", Serial));
|
||||
fmt::format("DEVICE-UPDATE({}): Device is updating its login password.", Serial));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -34,11 +34,13 @@ namespace OpenWifi {
|
||||
FullEvent.set("type", EventType);
|
||||
FullEvent.set("timestamp", EventTimeStamp);
|
||||
FullEvent.set("payload", EventPayload);
|
||||
|
||||
std::ostringstream OS;
|
||||
FullEvent.stringify(OS);
|
||||
KafkaManager()->PostMessage(KafkaTopics::DEVICE_EVENT_QUEUE, SerialNumber_,
|
||||
std::make_shared<std::string>(OS.str()));
|
||||
if(strncmp(EventType.c_str(),"rrm.",4) == 0 ) {
|
||||
KafkaManager()->PostMessage(KafkaTopics::RRM, SerialNumber_,
|
||||
FullEvent);
|
||||
} else {
|
||||
KafkaManager()->PostMessage(KafkaTopics::DEVICE_EVENT_QUEUE, SerialNumber_,
|
||||
FullEvent);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (const Poco::Exception &E) {
|
||||
|
||||
@@ -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;
|
||||
@@ -40,10 +42,6 @@ namespace OpenWifi {
|
||||
CId_, UUID, request_uuid));
|
||||
}
|
||||
|
||||
uint64_t UpgradedUUID;
|
||||
LookForUpgrade(UUID, UpgradedUUID);
|
||||
State_.UUID = UpgradedUUID;
|
||||
|
||||
GWObjects::HealthCheck Check;
|
||||
|
||||
Check.SerialNumber = SerialNumber_;
|
||||
@@ -52,19 +50,15 @@ 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()) {
|
||||
Poco::JSON::Stringifier Stringify;
|
||||
std::ostringstream OS;
|
||||
ParamsObj->set("timestamp", Utils::Now());
|
||||
Stringify.condense(ParamsObj, OS);
|
||||
KafkaManager()->PostMessage(KafkaTopics::HEALTHCHECK, SerialNumber_, std::make_shared<std::string>(OS.str()));
|
||||
if (KafkaManager()->Enabled() && !AP_WS_Server()->KafkaDisableHealthChecks()) {
|
||||
KafkaManager()->PostMessage(KafkaTopics::HEALTHCHECK, SerialNumber_, *ParamsObj);
|
||||
}
|
||||
} else {
|
||||
poco_warning(Logger_, fmt::format("HEALTHCHECK({}): Missing parameter", CId_));
|
||||
|
||||
@@ -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,27 +40,28 @@ namespace OpenWifi {
|
||||
UUID, request_uuid));
|
||||
}
|
||||
|
||||
uint64_t UpgradedUUID;
|
||||
LookForUpgrade(UUID, UpgradedUUID);
|
||||
State_.UUID = UpgradedUUID;
|
||||
std::lock_guard Guard(DbSession_->Mutex());
|
||||
if(!Simulated_) {
|
||||
uint64_t 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()) {
|
||||
Poco::JSON::Stringifier Stringify;
|
||||
std::ostringstream OS;
|
||||
Stringify.condense(ParamsObj, OS);
|
||||
KafkaManager()->PostMessage(KafkaTopics::STATE, SerialNumber_, std::make_shared<std::string>(OS.str()));
|
||||
if (KafkaManager()->Enabled() && !AP_WS_Server()->KafkaDisableState()) {
|
||||
KafkaManager()->PostMessage(KafkaTopics::STATE, SerialNumber_, *ParamsObj);
|
||||
}
|
||||
|
||||
GWWebSocketNotifications::SingleDevice_t N;
|
||||
|
||||
@@ -27,7 +27,7 @@ namespace OpenWifi {
|
||||
std::ostringstream SS;
|
||||
Payload->stringify(SS);
|
||||
auto now = Utils::Now();
|
||||
auto KafkaPayload = std::make_shared<std::string>(SS.str());
|
||||
auto KafkaPayload = SS.str();
|
||||
if (ParamsObj->has("adhoc")) {
|
||||
KafkaManager()->PostMessage(KafkaTopics::DEVICE_TELEMETRY, SerialNumber_,
|
||||
KafkaPayload);
|
||||
@@ -35,18 +35,16 @@ namespace OpenWifi {
|
||||
}
|
||||
if (TelemetryWebSocketRefCount_) {
|
||||
if (now < TelemetryWebSocketTimer_) {
|
||||
// std::cout << SerialNumber_ << ": Updating WebSocket telemetry" <<
|
||||
// std::endl;
|
||||
|
||||
TelemetryWebSocketPackets_++;
|
||||
State_.websocketPackets = TelemetryWebSocketPackets_;
|
||||
TelemetryStream()->NotifyEndPoint(SerialNumberInt_, *KafkaPayload);
|
||||
TelemetryStream()->NotifyEndPoint(SerialNumberInt_, KafkaPayload);
|
||||
} else {
|
||||
StopWebSocketTelemetry(CommandManager()->Next_RPC_ID());
|
||||
}
|
||||
}
|
||||
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_,
|
||||
|
||||
@@ -21,11 +21,7 @@ namespace OpenWifi {
|
||||
|
||||
if (ParamsObj->has(uCentralProtocol::SERIAL) && ParamsObj->has(uCentralProtocol::DATA)) {
|
||||
if (KafkaManager()->Enabled()) {
|
||||
auto Data = ParamsObj->get(uCentralProtocol::DATA);
|
||||
Poco::JSON::Stringifier Stringify;
|
||||
std::ostringstream OS;
|
||||
Stringify.condense(ParamsObj, OS);
|
||||
KafkaManager()->PostMessage(KafkaTopics::WIFISCAN, SerialNumber_, std::make_shared<std::string>(OS.str()));
|
||||
KafkaManager()->PostMessage(KafkaTopics::WIFISCAN, SerialNumber_, *ParamsObj);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,62 +0,0 @@
|
||||
//
|
||||
// Created by stephane bourque on 2022-02-03.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <shared_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() * 2;
|
||||
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::shared_lock Lock(Mutex_);
|
||||
NextReactor_++;
|
||||
NextReactor_ %= NumberOfThreads_;
|
||||
return *Reactors_[NextReactor_];
|
||||
}
|
||||
|
||||
private:
|
||||
std::shared_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,32 +6,66 @@
|
||||
// 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,
|
||||
@@ -57,7 +91,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_) {
|
||||
@@ -107,7 +141,6 @@ namespace OpenWifi {
|
||||
Context->flushSessionCache();
|
||||
Context->enableSessionCache(true);
|
||||
Context->enableExtendedCertificateVerification(false);
|
||||
// Context->disableStatelessSessionResumption();
|
||||
Context->disableProtocols(Poco::Net::Context::PROTO_TLSV1 |
|
||||
Poco::Net::Context::PROTO_TLSV1_1);
|
||||
|
||||
@@ -136,6 +169,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_) {
|
||||
@@ -157,252 +193,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();
|
||||
auto now = Utils::Now();
|
||||
bool AP_WS_Server::Disconnect(uint64_t SerialNumber) {
|
||||
std::shared_ptr<AP_WS_Connection> Connection;
|
||||
{
|
||||
auto hashIndex = MACHash::Hash(SerialNumber);
|
||||
std::lock_guard DeviceLock(SerialNumbersMutex_[hashIndex]);
|
||||
auto DeviceHint = SerialNumbers_[hashIndex].find(SerialNumber);
|
||||
if (DeviceHint == SerialNumbers_[hashIndex].end() || DeviceHint->second == nullptr) {
|
||||
return false;
|
||||
}
|
||||
Connection = DeviceHint->second;
|
||||
SerialNumbers_[hashIndex].erase(DeviceHint);
|
||||
}
|
||||
|
||||
{
|
||||
std::lock_guard Lock(WSServerMutex_);
|
||||
if (!Garbage_.empty()) {
|
||||
Garbage_.clear();
|
||||
auto H = SessionHash::Hash(Connection->State_.sessionId);
|
||||
std::lock_guard SessionLock(SessionMutex_[H]);
|
||||
Sessions_[H].erase(Connection->State_.sessionId);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void AP_WS_Server::CleanupSessions() {
|
||||
|
||||
while(Running_) {
|
||||
std::this_thread::sleep_for(std::chrono::seconds(10));
|
||||
|
||||
while(Running_ && !CleanupSessions_.empty()) {
|
||||
std::pair<uint64_t, uint64_t> Session;
|
||||
{
|
||||
std::lock_guard G(CleanupMutex_);
|
||||
Session = CleanupSessions_.front();
|
||||
CleanupSessions_.pop_front();
|
||||
}
|
||||
poco_trace(this->Logger(),fmt::format("Cleaning up session: {} for device: {}", Session.first, Utils::IntToSerialNumber(Session.second)));
|
||||
EndSession(Session.first, Session.second);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AP_WS_Server::run() {
|
||||
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;
|
||||
}
|
||||
|
||||
NumberOfConnectedDevices_ = 0;
|
||||
NumberOfConnectingDevices_ = 0;
|
||||
AverageDeviceConnectionTime_ = 0;
|
||||
uint64_t total_connected_time = 0;
|
||||
LocalLogger.information(fmt::format("Garbage collecting starting run." ));
|
||||
|
||||
auto hint = SerialNumbers_.begin();
|
||||
while (hint != end(SerialNumbers_)) {
|
||||
if (hint->second.second == nullptr) {
|
||||
hint = SerialNumbers_.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_));
|
||||
Sessions_.erase(hint->second.second->State_.sessionId);
|
||||
Garbage_.push_back(hint->second.second);
|
||||
hint = SerialNumbers_.erase(hint);
|
||||
} else if (hint->second.second->State_.Connected) {
|
||||
NumberOfConnectedDevices_++;
|
||||
total_connected_time += (now - hint->second.second->State_.started);
|
||||
hint++;
|
||||
} else {
|
||||
NumberOfConnectingDevices_++;
|
||||
hint++;
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
AverageDeviceConnectionTime_ = NumberOfConnectedDevices_ > 0
|
||||
? total_connected_time / NumberOfConnectedDevices_
|
||||
: 0;
|
||||
if ((now - last_log) > 120) {
|
||||
last_log = now;
|
||||
poco_information(Logger(),
|
||||
fmt::format("Active AP connections: {} Connecting: {} Average connection time: {} seconds",
|
||||
NumberOfConnectedDevices_, NumberOfConnectingDevices_,
|
||||
AverageDeviceConnectionTime_));
|
||||
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"));
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
std::ostringstream OS;
|
||||
FullEvent.stringify(OS);
|
||||
KafkaManager()->PostMessage(KafkaTopics::DEVICE_EVENT_QUEUE, "system",
|
||||
std::make_shared<std::string>(OS.str()));
|
||||
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::GetHealthDevices(std::uint64_t lowLimit, std::uint64_t highLimit, std::vector<std::string> & SerialNumbers) {
|
||||
SerialNumbers.clear();
|
||||
for(int i=0;i<SessionHash::HashMax();i++) {
|
||||
std::lock_guard Lock(SessionMutex_[i]);
|
||||
for (const auto &connection : Sessions_[i]) {
|
||||
if (connection.second->RawLastHealthcheck_.Sanity >= lowLimit &&
|
||||
connection.second->RawLastHealthcheck_.Sanity <= highLimit) {
|
||||
SerialNumbers.push_back(connection.second->SerialNumber_);
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool AP_WS_Server::GetStatistics(uint64_t SerialNumber, std::string &Statistics) const {
|
||||
std::shared_ptr<AP_WS_Connection> DevicePtr;
|
||||
std::shared_ptr<AP_WS_Connection> Connection;
|
||||
{
|
||||
std::lock_guard Lock(WSServerMutex_);
|
||||
auto Device = SerialNumbers_.find(SerialNumber);
|
||||
if (Device == SerialNumbers_.end() || Device->second.second == nullptr) {
|
||||
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;
|
||||
}
|
||||
DevicePtr = Device->second.second;
|
||||
Connection = DeviceHint->second;
|
||||
}
|
||||
DevicePtr->GetLastStats(Statistics);
|
||||
Connection->GetLastStats(Statistics);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool AP_WS_Server::GetState(uint64_t SerialNumber, GWObjects::ConnectionState &State) const {
|
||||
std::shared_ptr<AP_WS_Connection> DevicePtr;
|
||||
std::shared_ptr<AP_WS_Connection> Connection;
|
||||
{
|
||||
std::lock_guard Lock(WSServerMutex_);
|
||||
auto Device = SerialNumbers_.find(SerialNumber);
|
||||
if (Device == SerialNumbers_.end() || Device->second.second == nullptr) {
|
||||
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;
|
||||
}
|
||||
DevicePtr = Device->second.second;
|
||||
Connection = DeviceHint->second;
|
||||
}
|
||||
DevicePtr->GetState(State);
|
||||
Connection->GetState(State);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool AP_WS_Server::GetHealthcheck(uint64_t SerialNumber,
|
||||
GWObjects::HealthCheck &CheckData) const {
|
||||
std::shared_ptr<AP_WS_Connection> DevicePtr;
|
||||
std::shared_ptr<AP_WS_Connection> Connection;
|
||||
{
|
||||
std::lock_guard Lock(WSServerMutex_);
|
||||
auto Device = SerialNumbers_.find(SerialNumber);
|
||||
if (Device == SerialNumbers_.end() || Device->second.second == nullptr) {
|
||||
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;
|
||||
}
|
||||
DevicePtr = Device->second.second;
|
||||
Connection = Device->second;
|
||||
}
|
||||
Connection->GetLastHealthCheck(CheckData);
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
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) {
|
||||
{
|
||||
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)));
|
||||
}
|
||||
|
||||
{
|
||||
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)));
|
||||
}
|
||||
DevicePtr->GetLastHealthCheck(CheckData);
|
||||
return true;
|
||||
}
|
||||
|
||||
void AP_WS_Server::SetSessionDetails(uint64_t connection_id, uint64_t SerialNumber) {
|
||||
std::lock_guard Lock(WSServerMutex_);
|
||||
|
||||
auto Conn = Sessions_.find(connection_id);
|
||||
if (Conn == end(Sessions_))
|
||||
return;
|
||||
|
||||
auto CurrentSerialNumber = SerialNumbers_.find(SerialNumber);
|
||||
if ((CurrentSerialNumber == SerialNumbers_.end()) ||
|
||||
(CurrentSerialNumber->second.first < connection_id)) {
|
||||
SerialNumbers_[SerialNumber] = std::make_pair(connection_id, Conn->second);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
bool AP_WS_Server::EndSession(uint64_t session_id, uint64_t serial_number) {
|
||||
std::lock_guard G(WSServerMutex_);
|
||||
|
||||
auto Session = Sessions_.find(session_id);
|
||||
if (Session == end(Sessions_))
|
||||
return false;
|
||||
|
||||
Garbage_.push_back(Session->second);
|
||||
|
||||
auto Device = SerialNumbers_.find(serial_number);
|
||||
if (Device == end(SerialNumbers_)) {
|
||||
Sessions_.erase(Session);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (Device->second.first == session_id) {
|
||||
Sessions_.erase(Session);
|
||||
SerialNumbers_.erase(Device);
|
||||
return true;
|
||||
}
|
||||
|
||||
Sessions_.erase(Session);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool AP_WS_Server::EndSessionUnSafe(uint64_t session_id, uint64_t serial_number) {
|
||||
|
||||
auto Session = Sessions_.find(session_id);
|
||||
if (Session == end(Sessions_))
|
||||
return false;
|
||||
|
||||
Garbage_.push_back(Session->second);
|
||||
|
||||
auto Device = SerialNumbers_.find(serial_number);
|
||||
if (Device == end(SerialNumbers_)) {
|
||||
Sessions_.erase(Session);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (Device->second.first == session_id) {
|
||||
Sessions_.erase(Session);
|
||||
SerialNumbers_.erase(Device);
|
||||
return true;
|
||||
}
|
||||
|
||||
Sessions_.erase(Session);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool AP_WS_Server::Connected(uint64_t SerialNumber,
|
||||
GWObjects::DeviceRestrictions &Restrictions) const {
|
||||
std::shared_ptr<AP_WS_Connection> DevicePtr;
|
||||
std::shared_ptr<AP_WS_Connection> Connection;
|
||||
{
|
||||
std::lock_guard Lock(WSServerMutex_);
|
||||
auto Device = SerialNumbers_.find(SerialNumber);
|
||||
if (Device == end(SerialNumbers_) || Device->second.second == nullptr) {
|
||||
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;
|
||||
}
|
||||
DevicePtr = Device->second.second;
|
||||
Connection = DeviceHint->second;
|
||||
}
|
||||
DevicePtr->GetRestrictions(Restrictions);
|
||||
return DevicePtr->State_.Connected;
|
||||
|
||||
if(Connection->Dead_) {
|
||||
return false;
|
||||
}
|
||||
Restrictions = Connection->GetRestrictions();
|
||||
return Connection->State_.Connected;
|
||||
}
|
||||
|
||||
|
||||
bool AP_WS_Server::Connected(uint64_t SerialNumber) const {
|
||||
std::shared_ptr<AP_WS_Connection> DevicePtr;
|
||||
std::shared_ptr<AP_WS_Connection> Connection;
|
||||
{
|
||||
std::lock_guard Lock(WSServerMutex_);
|
||||
auto Device = SerialNumbers_.find(SerialNumber);
|
||||
if (Device == end(SerialNumbers_) || Device->second.second == nullptr) {
|
||||
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;
|
||||
}
|
||||
DevicePtr = Device->second.second;
|
||||
Connection = DeviceHint->second;
|
||||
}
|
||||
return DevicePtr->State_.Connected;
|
||||
|
||||
if(Connection->Dead_) {
|
||||
return false;
|
||||
}
|
||||
return Connection->State_.Connected;
|
||||
}
|
||||
|
||||
bool AP_WS_Server::SendFrame(uint64_t SerialNumber, const std::string &Payload) const {
|
||||
std::shared_ptr<AP_WS_Connection> DevicePtr;
|
||||
auto hashIndex = MACHash::Hash(SerialNumber);
|
||||
|
||||
std::shared_ptr<AP_WS_Connection> Connection;
|
||||
{
|
||||
std::lock_guard Lock(WSServerMutex_);
|
||||
auto Device = SerialNumbers_.find(SerialNumber);
|
||||
if (Device == SerialNumbers_.end() || Device->second.second == nullptr) {
|
||||
std::lock_guard DeviceLock(SerialNumbersMutex_[hashIndex]);
|
||||
auto DeviceHint = SerialNumbers_[hashIndex].find(SerialNumber);
|
||||
if (DeviceHint == end(SerialNumbers_[hashIndex]) || DeviceHint->second == nullptr) {
|
||||
return false;
|
||||
}
|
||||
DevicePtr = Device->second.second;
|
||||
Connection = DeviceHint->second;
|
||||
}
|
||||
|
||||
if(Connection->Dead_) {
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
return DevicePtr->Send(Payload);
|
||||
return Connection->Send(Payload);
|
||||
} catch (...) {
|
||||
poco_debug(Logger(), fmt::format(": SendFrame: Could not send data to device '{}'",
|
||||
Utils::IntToSerialNumber(SerialNumber)));
|
||||
@@ -411,61 +615,64 @@ namespace OpenWifi {
|
||||
}
|
||||
|
||||
void AP_WS_Server::StopWebSocketTelemetry(uint64_t RPCID, uint64_t SerialNumber) {
|
||||
std::shared_ptr<AP_WS_Connection> DevicePtr;
|
||||
std::shared_ptr<AP_WS_Connection> Connection;
|
||||
{
|
||||
std::lock_guard Lock(WSServerMutex_);
|
||||
|
||||
auto Device = SerialNumbers_.find(SerialNumber);
|
||||
if (Device == end(SerialNumbers_) || Device->second.second == nullptr) {
|
||||
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;
|
||||
}
|
||||
DevicePtr = Device->second.second;
|
||||
Connection = Device->second;
|
||||
}
|
||||
DevicePtr->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) {
|
||||
std::shared_ptr<AP_WS_Connection> DevicePtr;
|
||||
std::shared_ptr<AP_WS_Connection> Connection;
|
||||
{
|
||||
std::lock_guard Lock(WSServerMutex_);
|
||||
auto Device = SerialNumbers_.find(SerialNumber);
|
||||
if (Device == end(SerialNumbers_) || Device->second.second == nullptr) {
|
||||
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;
|
||||
}
|
||||
DevicePtr = Device->second.second;
|
||||
Connection = DeviceHint->second;
|
||||
}
|
||||
DevicePtr->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) {
|
||||
std::shared_ptr<AP_WS_Connection> DevicePtr;
|
||||
std::shared_ptr<AP_WS_Connection> Connection;
|
||||
{
|
||||
std::lock_guard Lock(WSServerMutex_);
|
||||
auto Device = SerialNumbers_.find(SerialNumber);
|
||||
if (Device == end(SerialNumbers_) || Device->second.second == nullptr) {
|
||||
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;
|
||||
}
|
||||
DevicePtr = Device->second.second;
|
||||
Connection = DeviceHint->second;
|
||||
}
|
||||
DevicePtr->SetKafkaTelemetryReporting(RPCID, Interval, Lifetime, TelemetryTypes);
|
||||
Connection->SetKafkaTelemetryReporting(RPCID, Interval, Lifetime, TelemetryTypes);
|
||||
}
|
||||
|
||||
void AP_WS_Server::StopKafkaTelemetry(uint64_t RPCID, uint64_t SerialNumber) {
|
||||
std::shared_ptr<AP_WS_Connection> DevicePtr;
|
||||
std::shared_ptr<AP_WS_Connection> Connection;
|
||||
{
|
||||
std::lock_guard Lock(WSServerMutex_);
|
||||
auto Device = SerialNumbers_.find(SerialNumber);
|
||||
if (Device == end(SerialNumbers_) || Device->second.second == nullptr) {
|
||||
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;
|
||||
}
|
||||
DevicePtr = Device->second.second;
|
||||
Connection = DeviceHint->second;
|
||||
}
|
||||
DevicePtr->StopKafkaTelemetry(RPCID);
|
||||
Connection->StopKafkaTelemetry(RPCID);
|
||||
}
|
||||
|
||||
void AP_WS_Server::GetTelemetryParameters(
|
||||
@@ -473,16 +680,19 @@ namespace OpenWifi {
|
||||
uint64_t &TelemetryWebSocketTimer, uint64_t &TelemetryKafkaTimer,
|
||||
uint64_t &TelemetryWebSocketCount, uint64_t &TelemetryKafkaCount,
|
||||
uint64_t &TelemetryWebSocketPackets, uint64_t &TelemetryKafkaPackets) {
|
||||
std::shared_ptr<AP_WS_Connection> DevicePtr;
|
||||
|
||||
std::shared_ptr<AP_WS_Connection> Connection;
|
||||
{
|
||||
std::lock_guard Lock(WSServerMutex_);
|
||||
auto Device = SerialNumbers_.find(SerialNumber);
|
||||
if (Device == end(SerialNumbers_) || Device->second.second == nullptr) {
|
||||
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;
|
||||
}
|
||||
DevicePtr = Device->second.second;
|
||||
Connection = DeviceHint->second;
|
||||
}
|
||||
DevicePtr->GetTelemetryParameters(TelemetryRunning, TelemetryInterval,
|
||||
|
||||
Connection->GetTelemetryParameters(TelemetryRunning, TelemetryInterval,
|
||||
TelemetryWebSocketTimer, TelemetryKafkaTimer,
|
||||
TelemetryWebSocketCount, TelemetryKafkaCount,
|
||||
TelemetryWebSocketPackets, TelemetryKafkaPackets);
|
||||
@@ -490,18 +700,25 @@ namespace OpenWifi {
|
||||
|
||||
bool AP_WS_Server::SendRadiusAccountingData(const std::string &SerialNumber,
|
||||
const unsigned char *buffer, std::size_t size) {
|
||||
std::shared_ptr<AP_WS_Connection> DevicePtr;
|
||||
|
||||
std::shared_ptr<AP_WS_Connection> Connection;
|
||||
{
|
||||
std::lock_guard Lock(WSServerMutex_);
|
||||
auto Device = SerialNumbers_.find(Utils::SerialNumberToInt(SerialNumber));
|
||||
if (Device == SerialNumbers_.end() || Device->second.second == nullptr) {
|
||||
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;
|
||||
}
|
||||
DevicePtr = Device->second.second;
|
||||
Connection = DeviceHint->second;
|
||||
}
|
||||
|
||||
if(Connection->Dead_) {
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
return DevicePtr->SendRadiusAccountingData(buffer, size);
|
||||
return Connection->SendRadiusAccountingData(buffer, size);
|
||||
} catch (...) {
|
||||
poco_debug(
|
||||
Logger(),
|
||||
@@ -513,18 +730,24 @@ namespace OpenWifi {
|
||||
|
||||
bool AP_WS_Server::SendRadiusAuthenticationData(const std::string &SerialNumber,
|
||||
const unsigned char *buffer, std::size_t size) {
|
||||
std::shared_ptr<AP_WS_Connection> DevicePtr;
|
||||
std::shared_ptr<AP_WS_Connection> Connection;
|
||||
{
|
||||
std::lock_guard Lock(WSServerMutex_);
|
||||
auto Device = SerialNumbers_.find(Utils::SerialNumberToInt(SerialNumber));
|
||||
if (Device == SerialNumbers_.end() || Device->second.second == nullptr) {
|
||||
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;
|
||||
}
|
||||
DevicePtr = Device->second.second;
|
||||
Connection = DeviceHint->second;
|
||||
}
|
||||
|
||||
if(Connection->Dead_) {
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
return DevicePtr->SendRadiusAuthenticationData(buffer, size);
|
||||
return Connection->SendRadiusAuthenticationData(buffer, size);
|
||||
} catch (...) {
|
||||
poco_debug(
|
||||
Logger(),
|
||||
@@ -536,18 +759,23 @@ namespace OpenWifi {
|
||||
|
||||
bool AP_WS_Server::SendRadiusCoAData(const std::string &SerialNumber,
|
||||
const unsigned char *buffer, std::size_t size) {
|
||||
std::shared_ptr<AP_WS_Connection> DevicePtr;
|
||||
std::shared_ptr<AP_WS_Connection> Connection;
|
||||
{
|
||||
std::lock_guard Lock(WSServerMutex_);
|
||||
auto Device = SerialNumbers_.find(Utils::SerialNumberToInt(SerialNumber));
|
||||
if (Device == SerialNumbers_.end() || Device->second.second == nullptr) {
|
||||
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;
|
||||
}
|
||||
DevicePtr = Device->second.second;
|
||||
Connection = DeviceHint->second;
|
||||
}
|
||||
|
||||
if(Connection->Dead_) {
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
return DevicePtr->SendRadiusCoAData(buffer, size);
|
||||
return Connection->SendRadiusCoAData(buffer, size);
|
||||
} catch (...) {
|
||||
poco_debug(Logger(),
|
||||
fmt::format(": SendRadiusCoAData: Could not send data to device '{}'",
|
||||
|
||||
@@ -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;
|
||||
@@ -75,59 +80,52 @@ namespace OpenWifi {
|
||||
bool IsCertOk() { return IssuerCert_ != nullptr; }
|
||||
bool ValidateCertificate(const std::string &ConnectionId,
|
||||
const Poco::Crypto::X509Certificate &Certificate);
|
||||
// Poco::Net::SocketReactor & GetNextReactor() { return ReactorPool_.NextReactor(); }
|
||||
|
||||
inline bool IsSimSerialNumber(const std::string &SerialNumber) const {
|
||||
return IsSim(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(WSServerMutex_);
|
||||
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 std::shared_ptr<AP_WS_Connection> FindConnection(uint64_t session_id) const {
|
||||
std::lock_guard Lock(WSServerMutex_);
|
||||
|
||||
auto Connection = Sessions_.find(session_id);
|
||||
if (Connection != end(Sessions_))
|
||||
return Connection->second;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
inline bool DeviceRequiresSecureRtty(uint64_t serialNumber) const {
|
||||
std::lock_guard Lock(WSServerMutex_);
|
||||
|
||||
auto Connection = SerialNumbers_.find(serialNumber);
|
||||
if (Connection==end(SerialNumbers_) || 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 {
|
||||
@@ -143,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,
|
||||
@@ -157,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);
|
||||
@@ -176,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 {
|
||||
@@ -185,84 +179,80 @@ 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_;
|
||||
}
|
||||
|
||||
inline bool GetHealthDevices(std::uint64_t lowLimit, std::uint64_t highLimit, std::vector<std::string> & SerialNumbers) {
|
||||
std::lock_guard G(WSServerMutex_);
|
||||
bool KafkaDisableState() const { return KafkaDisableState_; }
|
||||
bool KafkaDisableHealthChecks() const { return KafkaDisableHealthChecks_; }
|
||||
|
||||
for(const auto &connection:Sessions_) {
|
||||
if( connection.second->RawLastHealthcheck_.Sanity>=lowLimit &&
|
||||
connection.second->RawLastHealthcheck_.Sanity<=highLimit) {
|
||||
SerialNumbers.push_back(connection.second->SerialNumber_);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
inline 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
|
||||
) {
|
||||
std::lock_guard G(WSServerMutex_);
|
||||
auto session_hint = SerialNumbers_.find(Utils::SerialNumberToInt(serialNumber));
|
||||
if(session_hint==end(SerialNumbers_)) {
|
||||
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::recursive_mutex WSServerMutex_;
|
||||
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::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_;
|
||||
std::map<uint64_t, std::pair<uint64_t, std::shared_ptr<AP_WS_Connection>>> SerialNumbers_;
|
||||
std::atomic_bool AllowSerialNumberMismatch_ = true;
|
||||
std::atomic_uint64_t MismatchDepth_ = 2;
|
||||
|
||||
std::uint64_t NumberOfConnectedDevices_ = 0;
|
||||
std::uint64_t AverageDeviceConnectionTime_ = 0;
|
||||
std::uint64_t MismatchDepth_ = 2;
|
||||
|
||||
std::atomic_uint64_t NumberOfConnectedDevices_ = 0;
|
||||
std::atomic_uint64_t AverageDeviceConnectionTime_ = 0;
|
||||
std::uint64_t NumberOfConnectingDevices_ = 0;
|
||||
std::uint64_t SessionTimeOut_ = 10*60;
|
||||
mutable std::mutex StatsMutex_;
|
||||
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(to_string(Platform));
|
||||
}
|
||||
} 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;
|
||||
}
|
||||
}
|
||||
@@ -467,4 +452,16 @@ namespace OpenWifi {
|
||||
poco_warning(Logger(), fmt::format("{}: Failed to send command. ID: {}", UUID, RPC_ID));
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool CommandManager::FireAndForget(const std::string &SerialNumber, const std::string &Method, const Poco::JSON::Object &Params) {
|
||||
Poco::JSON::Object CompleteRPC;
|
||||
CompleteRPC.set(uCentralProtocol::JSONRPC, uCentralProtocol::JSONRPC_VERSION);
|
||||
CompleteRPC.set(uCentralProtocol::ID, 0);
|
||||
CompleteRPC.set(uCentralProtocol::METHOD, Method);
|
||||
CompleteRPC.set(uCentralProtocol::PARAMS, Params);
|
||||
std::stringstream ToSend;
|
||||
CompleteRPC.stringify(ToSend);
|
||||
poco_debug(Logger(), fmt::format("{}: Fire and forget command {}.", SerialNumber, Method));
|
||||
return AP_WS_Server()->SendFrame(SerialNumber, ToSend.str())>0;
|
||||
}
|
||||
} // namespace OpenWifi
|
||||
@@ -12,7 +12,7 @@
|
||||
#include <functional>
|
||||
#include <future>
|
||||
#include <map>
|
||||
#include <shared_mutex>
|
||||
#include <mutex>
|
||||
#include <utility>
|
||||
|
||||
#include "Poco/JSON/Object.h"
|
||||
@@ -162,8 +162,10 @@ namespace OpenWifi {
|
||||
inline auto CommandTimeout() const { return commandTimeOut_; }
|
||||
inline auto CommandRetry() const { return commandRetry_; }
|
||||
|
||||
bool FireAndForget(const std::string &SerialNumber, const std::string &Method,
|
||||
const Poco::JSON::Object &Params);
|
||||
private:
|
||||
mutable std::recursive_mutex LocalMutex_;
|
||||
mutable std::mutex LocalMutex_;
|
||||
std::atomic_bool Running_ = false;
|
||||
Poco::Thread ManagerThread;
|
||||
std::atomic_uint64_t Id_ = 3; // do not start @1. We ignore ID=1 & 0 is illegal..
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -35,6 +35,7 @@
|
||||
#include "VenueBroadcaster.h"
|
||||
#include "AP_WS_ConfigAutoUpgrader.h"
|
||||
#include "rttys/RTTYS_server.h"
|
||||
#include "firmware_revision_cache.h"
|
||||
|
||||
namespace OpenWifi {
|
||||
class Daemon *Daemon::instance() {
|
||||
@@ -42,21 +43,34 @@ namespace OpenWifi {
|
||||
vDAEMON_PROPERTIES_FILENAME, vDAEMON_ROOT_ENV_VAR, vDAEMON_CONFIG_ENV_VAR,
|
||||
vDAEMON_APP_NAME, vDAEMON_BUS_TIMER,
|
||||
SubSystemVec{GenericScheduler(), StorageService(), SerialNumberCache(), ConfigurationValidator(),
|
||||
UI_WebSocketClientServer(), OUIServer(), FindCountryFromIP(),
|
||||
CommandManager(), FileUploader(), StorageArchiver(), TelemetryStream(),
|
||||
RTTYS_server(), RADIUS_proxy_server(), VenueBroadcaster(), ScriptManager(),
|
||||
SignatureManager(), AP_WS_Server(),
|
||||
RegulatoryInfo(),
|
||||
RADIUSSessionTracker(),
|
||||
AP_WS_ConfigAutoUpgrader()
|
||||
UI_WebSocketClientServer(), OUIServer(), FindCountryFromIP(),
|
||||
CommandManager(), FileUploader(), StorageArchiver(), TelemetryStream(),
|
||||
RTTYS_server(), RADIUS_proxy_server(), VenueBroadcaster(), ScriptManager(),
|
||||
SignatureManager(), AP_WS_Server(),
|
||||
RegulatoryInfo(),
|
||||
RADIUSSessionTracker(),
|
||||
AP_WS_ConfigAutoUpgradeAgent(),
|
||||
FirmwareRevisionCache()
|
||||
});
|
||||
return &instance;
|
||||
}
|
||||
|
||||
static std::string ALBHealthCallback() {
|
||||
uint64_t Connections, AverageConnectionTime, NumberOfConnectingDevices;
|
||||
AP_WS_Server()->AverageDeviceStatistics(Connections, AverageConnectionTime,
|
||||
NumberOfConnectingDevices);
|
||||
std::ostringstream os;
|
||||
os << "Connections: " << Connections << std::endl <<
|
||||
"ConnectingDevices: " << NumberOfConnectingDevices << std::endl <<
|
||||
"ConnectionTime: " << AverageConnectionTime << std::endl;
|
||||
return os.str();
|
||||
}
|
||||
|
||||
void Daemon::PostInitialization([[maybe_unused]] Poco::Util::Application &self) {
|
||||
AutoProvisioning_ = config().getBool("openwifi.autoprovisioning", false);
|
||||
DeviceTypes_ = DefaultDeviceTypeList;
|
||||
WebSocketProcessor_ = std::make_unique<GwWebSocketClient>(logger());
|
||||
MicroServiceALBCallback(ALBHealthCallback);
|
||||
}
|
||||
|
||||
[[nodiscard]] std::string Daemon::IdentifyDevice(const std::string &Id) const {
|
||||
@@ -64,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);
|
||||
|
||||
@@ -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 {
|
||||
|
||||
|
||||
@@ -12,10 +12,7 @@ namespace OpenWifi {
|
||||
Event.set("type", type_);
|
||||
Event.set("timestamp", timestamp_);
|
||||
Event.set("payload", payload_);
|
||||
std::ostringstream OS;
|
||||
Event.stringify(OS);
|
||||
auto payload = std::make_shared<std::string>(OS.str());
|
||||
KafkaManager()->PostMessage(KafkaTopics::DEVICE_EVENT_QUEUE, Utils::IntToSerialNumber(serialNumber_), payload);
|
||||
KafkaManager()->PostMessage(KafkaTopics::DEVICE_EVENT_QUEUE, Utils::IntToSerialNumber(serialNumber_), Event);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -50,17 +50,27 @@ namespace OpenWifi {
|
||||
class DeviceConfigurationChangeKafkaEvent : public GWKafkaEvents {
|
||||
public:
|
||||
DeviceConfigurationChangeKafkaEvent(std::uint64_t serialNumber,
|
||||
std::uint64_t timestamp, const std::string 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();
|
||||
}
|
||||
|
||||
private:
|
||||
std::string config_;
|
||||
Poco::JSON::Object::Ptr config_;
|
||||
};
|
||||
|
||||
class DeviceBlacklistedKafkaEvent : public GWKafkaEvents {
|
||||
|
||||
@@ -28,7 +28,7 @@ namespace OpenWifi {
|
||||
bool Recovered = false;
|
||||
Poco::File OuiFile(CurrentOUIFileName_);
|
||||
if (OuiFile.exists()) {
|
||||
std::unique_lock Lock(LocalMutex_);
|
||||
std::lock_guard Lock(LocalMutex_);
|
||||
Recovered = ProcessFile(CurrentOUIFileName_, OUIs_);
|
||||
if (Recovered) {
|
||||
poco_notice(Logger(),
|
||||
@@ -150,7 +150,7 @@ namespace OpenWifi {
|
||||
|
||||
OUIMap TmpOUIs;
|
||||
if (GetFile(LatestOUIFileName_) && ProcessFile(LatestOUIFileName_, TmpOUIs)) {
|
||||
std::unique_lock G(LocalMutex_);
|
||||
std::lock_guard G(LocalMutex_);
|
||||
OUIs_ = std::move(TmpOUIs);
|
||||
LastUpdate_ = Utils::Now();
|
||||
Poco::File F1(CurrentOUIFileName_);
|
||||
@@ -163,7 +163,7 @@ namespace OpenWifi {
|
||||
} else if (OUIs_.empty()) {
|
||||
if (ProcessFile(CurrentOUIFileName_, TmpOUIs)) {
|
||||
LastUpdate_ = Utils::Now();
|
||||
std::unique_lock G(LocalMutex_);
|
||||
std::lock_guard G(LocalMutex_);
|
||||
OUIs_ = std::move(TmpOUIs);
|
||||
}
|
||||
}
|
||||
@@ -173,7 +173,7 @@ namespace OpenWifi {
|
||||
}
|
||||
|
||||
std::string OUIServer::GetManufacturer(const std::string &MAC) {
|
||||
std::shared_lock Lock(LocalMutex_);
|
||||
std::lock_guard Lock(LocalMutex_);
|
||||
|
||||
auto Manufacturer = OUIs_.find(Utils::SerialNumberToOUI(MAC));
|
||||
if (Manufacturer != OUIs_.end())
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <shared_mutex>
|
||||
#include <mutex>
|
||||
|
||||
#include "framework/SubSystemServer.h"
|
||||
|
||||
@@ -32,7 +32,7 @@ namespace OpenWifi {
|
||||
[[nodiscard]] bool ProcessFile(const std::string &FileName, OUIMap &Map);
|
||||
|
||||
private:
|
||||
std::shared_mutex LocalMutex_;
|
||||
std::mutex LocalMutex_;
|
||||
uint64_t LastUpdate_ = 0;
|
||||
bool Initialized_ = false;
|
||||
OUIMap OUIs_;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -98,7 +98,7 @@ namespace OpenWifi {
|
||||
void RADIUSSessionTracker::ProcessAuthenticationSession([[maybe_unused]] OpenWifi::SessionNotification &Notification) {
|
||||
std::lock_guard Guard(Mutex_);
|
||||
|
||||
std::string CallingStationId, AccountingSessionId, AccountingMultiSessionId, UserName, ChargeableUserIdentity, Interface, nasId;
|
||||
std::string CallingStationId, CalledStationId, AccountingSessionId, AccountingMultiSessionId, UserName, ChargeableUserIdentity, Interface, nasId;
|
||||
for (const auto &attribute : Notification.Packet_.Attrs_) {
|
||||
switch (attribute.type) {
|
||||
case RADIUS::Attributes::AUTH_USERNAME: {
|
||||
@@ -111,6 +111,11 @@ namespace OpenWifi {
|
||||
&Notification.Packet_.P_.attributes[attribute.pos],
|
||||
&Notification.Packet_.P_.attributes[attribute.pos + attribute.len]);
|
||||
} break;
|
||||
case RADIUS::Attributes::CALLED_STATION_ID: {
|
||||
CalledStationId.assign(
|
||||
&Notification.Packet_.P_.attributes[attribute.pos],
|
||||
&Notification.Packet_.P_.attributes[attribute.pos + attribute.len]);
|
||||
} break;
|
||||
case RADIUS::Attributes::ACCT_SESSION_ID: {
|
||||
AccountingSessionId.assign(
|
||||
&Notification.Packet_.P_.attributes[attribute.pos],
|
||||
@@ -153,7 +158,7 @@ namespace OpenWifi {
|
||||
ap_hint = AccountingSessions_.find(Notification.SerialNumber_);
|
||||
}
|
||||
|
||||
auto Index = CallingStationId; // + AccountingSessionId; // +AccountingMultiSessionId;
|
||||
auto Index = AccountingSessionId +AccountingMultiSessionId;
|
||||
auto session_hint = ap_hint->second.find(Index);
|
||||
if(session_hint==end(ap_hint->second)) {
|
||||
auto NewSession = std::make_shared<GWObjects::RADIUSSession>();
|
||||
@@ -161,6 +166,7 @@ namespace OpenWifi {
|
||||
NewSession->started = NewSession->lastTransaction = Utils::Now();
|
||||
NewSession->userName = UserName;
|
||||
NewSession->callingStationId = CallingStationId;
|
||||
NewSession->calledStationId = CalledStationId;
|
||||
NewSession->accountingSessionId = AccountingSessionId;
|
||||
NewSession->accountingMultiSessionId = AccountingMultiSessionId;
|
||||
NewSession->chargeableUserIdentity = ChargeableUserIdentity;
|
||||
@@ -171,7 +177,6 @@ namespace OpenWifi {
|
||||
} else {
|
||||
session_hint->second->lastTransaction = Utils::Now();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
std::uint32_t GetUiInt32(const std::uint8_t *buf) {
|
||||
@@ -188,7 +193,7 @@ namespace OpenWifi {
|
||||
RADIUSSessionTracker::ProcessAccountingSession(OpenWifi::SessionNotification &Notification) {
|
||||
std::lock_guard Guard(Mutex_);
|
||||
|
||||
std::string CallingStationId, AccountingSessionId, AccountingMultiSessionId, UserName, ChargeableUserIdentity, Interface;
|
||||
std::string CallingStationId, CalledStationId, AccountingSessionId, AccountingMultiSessionId, UserName, ChargeableUserIdentity, Interface;
|
||||
std::uint8_t AccountingPacketType = 0;
|
||||
std::uint32_t InputOctets=0, OutputOctets=0, InputPackets=0, OutputPackets=0, InputGigaWords=0, OutputGigaWords=0,
|
||||
SessionTime = 0;
|
||||
@@ -204,6 +209,11 @@ namespace OpenWifi {
|
||||
&Notification.Packet_.P_.attributes[attribute.pos],
|
||||
&Notification.Packet_.P_.attributes[attribute.pos + attribute.len]);
|
||||
} break;
|
||||
case RADIUS::Attributes::CALLED_STATION_ID: {
|
||||
CalledStationId.assign(
|
||||
&Notification.Packet_.P_.attributes[attribute.pos],
|
||||
&Notification.Packet_.P_.attributes[attribute.pos + attribute.len]);
|
||||
} break;
|
||||
case RADIUS::Attributes::ACCT_SESSION_ID: {
|
||||
AccountingSessionId.assign(
|
||||
&Notification.Packet_.P_.attributes[attribute.pos],
|
||||
@@ -258,7 +268,6 @@ namespace OpenWifi {
|
||||
}
|
||||
}
|
||||
|
||||
auto Index = CallingStationId; // + AccountingSessionId; // +AccountingMultiSessionId;
|
||||
auto ap_hint = AccountingSessions_.find(Notification.SerialNumber_);
|
||||
if(ap_hint==end(AccountingSessions_)) {
|
||||
SessionMap M;
|
||||
@@ -266,6 +275,7 @@ namespace OpenWifi {
|
||||
ap_hint = AccountingSessions_.find(Notification.SerialNumber_);
|
||||
}
|
||||
|
||||
auto Index = AccountingSessionId + AccountingMultiSessionId;
|
||||
auto session_hint = ap_hint->second.find(Index);
|
||||
if(session_hint==end(ap_hint->second)) {
|
||||
// find the calling_station_id
|
||||
@@ -275,12 +285,15 @@ namespace OpenWifi {
|
||||
return;
|
||||
}
|
||||
|
||||
// std::cout << "ACT -> " << Notification.SerialNumber_ << ": AccountingSessionId: " << AccountingSessionId << " AccountingMultiSessionId: " << AccountingMultiSessionId << std::endl;
|
||||
|
||||
auto NewSession = std::make_shared<GWObjects::RADIUSSession>();
|
||||
NewSession->serialNumber = Notification.SerialNumber_;
|
||||
NewSession->destination = Notification.Destination_;
|
||||
NewSession->started = NewSession->lastTransaction = Utils::Now();
|
||||
NewSession->userName = UserName;
|
||||
NewSession->callingStationId = CallingStationId;
|
||||
NewSession->calledStationId = CalledStationId;
|
||||
NewSession->accountingSessionId = AccountingSessionId;
|
||||
NewSession->accountingMultiSessionId = AccountingMultiSessionId;
|
||||
NewSession->accountingPacket = Notification.Packet_;
|
||||
@@ -319,6 +332,14 @@ namespace OpenWifi {
|
||||
session_hint->second->sessionTime = SessionTime;
|
||||
}
|
||||
}
|
||||
|
||||
/* if(ap_hint!=AccountingSessions_.end()) {
|
||||
std::cout << "Acct 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;
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
[[maybe_unused]] static void store_packet(const std::string &serialNumber, const char *buffer, std::size_t size, int i) {
|
||||
@@ -340,18 +361,19 @@ namespace OpenWifi {
|
||||
P.Identifier(std::rand() & 0x00ff);
|
||||
P.AppendAttribute(RADIUS::Attributes::AUTH_USERNAME, session->userName);
|
||||
P.AppendAttribute(RADIUS::Attributes::NAS_IP, (std::uint32_t)(0x7f000001));
|
||||
P.AppendAttribute(RADIUS::Attributes::CALLING_STATION_ID, session->callingStationId);
|
||||
if(!session->calledStationId.empty())
|
||||
P.AppendAttribute(RADIUS::Attributes::CALLED_STATION_ID, session->calledStationId);
|
||||
if(!session->callingStationId.empty())
|
||||
P.AppendAttribute(RADIUS::Attributes::CALLING_STATION_ID, session->callingStationId);
|
||||
if(!session->nasId.empty())
|
||||
P.AppendAttribute(RADIUS::Attributes::NAS_IDENTIFIER, session->nasId);
|
||||
if(!session->accountingSessionId.empty())
|
||||
P.AppendAttribute(RADIUS::Attributes::ACCT_SESSION_ID, session->accountingSessionId);
|
||||
if(!session->accountingMultiSessionId.empty())
|
||||
P.AppendAttribute(RADIUS::Attributes::ACCT_MULTI_SESSION_ID, session->accountingMultiSessionId);
|
||||
if(!session->chargeableUserIdentity.empty())
|
||||
P.AppendAttribute(RADIUS::Attributes::CHARGEABLE_USER_IDENTITY, session->chargeableUserIdentity);
|
||||
if(!session->nasId.empty())
|
||||
P.AppendAttribute(RADIUS::Attributes::NAS_IDENTIFIER, session->nasId);
|
||||
auto ProxyState = session->serialNumber + ":" + "0.0.0.0" + ":" + "3799" + ":" + session->interface;
|
||||
std::cout << "Proxy state: " << ProxyState << " Secret: " << session->secret << std::endl;
|
||||
// P.AppendAttribute(RADIUS::PROXY_STATE, ProxyState);
|
||||
// std::cout << "Proxy state: " << ProxyState << " Secret: " << session->secret << std::endl;
|
||||
P.AppendAttribute(RADIUS::Attributes::PROXY_STATE, ProxyState);
|
||||
P.RecomputeAuthenticator(session->secret);
|
||||
P.Log(std::cout);
|
||||
AP_WS_Server()->SendRadiusCoAData(session->serialNumber, P.Buffer(), P.Size_);
|
||||
@@ -368,9 +390,23 @@ namespace OpenWifi {
|
||||
return false;
|
||||
}
|
||||
|
||||
for(const auto &[_,session]:ap_hint->second) {
|
||||
if(session->accountingSessionId==sessionId) {
|
||||
SendCoADM(session);
|
||||
auto session_hint = ap_hint->second.find(sessionId);
|
||||
if(session_hint!=ap_hint->second.end()) {
|
||||
SendCoADM(session_hint->second);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RADIUSSessionTracker::DisconnectUser(const std::string &UserName) {
|
||||
poco_information(Logger(),fmt::format("Disconnect user {}.", UserName));
|
||||
std::lock_guard Guard(Mutex_);
|
||||
|
||||
for(const auto &AP:AccountingSessions_) {
|
||||
for(const auto &Session:AP.second) {
|
||||
if(Session.second->userName==UserName) {
|
||||
SendCoADM(Session.second);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -378,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 ));
|
||||
|
||||
@@ -165,6 +165,7 @@ namespace OpenWifi {
|
||||
|
||||
bool SendCoADM(const std::string &serialNumber, const std::string &sessionId);
|
||||
bool SendCoADM(const RADIUSSessionPtr &session);
|
||||
bool DisconnectUser(const std::string &UserName);
|
||||
|
||||
inline std::uint32_t HasSessions(const std::string & serialNumber) {
|
||||
std::lock_guard G(Mutex_);
|
||||
|
||||
747
src/RADIUS_Destination.h
Normal file
747
src/RADIUS_Destination.h
Normal file
@@ -0,0 +1,747 @@
|
||||
//
|
||||
// Created by stephane bourque on 2022-08-15.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
|
||||
#include "RESTObjects/RESTAPI_GWobjects.h"
|
||||
|
||||
#include "Poco/Crypto/X509Certificate.h"
|
||||
#include "Poco/Crypto/RSAKey.h"
|
||||
#include "Poco/Net/Context.h"
|
||||
#include "Poco/Net/NetException.h"
|
||||
#include "Poco/Net/SecureStreamSocket.h"
|
||||
#include "Poco/Net/SocketReactor.h"
|
||||
#include "Poco/TemporaryFile.h"
|
||||
|
||||
#include "framework/MicroServiceFuncs.h"
|
||||
|
||||
#include "fmt/format.h"
|
||||
|
||||
#include "AP_WS_Server.h"
|
||||
#include "RADIUS_helpers.h"
|
||||
#include <RESTObjects/RESTAPI_GWobjects.h>
|
||||
|
||||
namespace OpenWifi {
|
||||
|
||||
class RADIUS_Destination : public Poco::Runnable {
|
||||
public:
|
||||
RADIUS_Destination(Poco::Net::SocketReactor &R, const GWObjects::RadiusProxyPool &P)
|
||||
: Reactor_(R),
|
||||
Logger_(Poco::Logger::get(
|
||||
fmt::format("RADSEC: {}", P.name))),
|
||||
Pool_(P)
|
||||
{
|
||||
Type_ = GWObjects::RadiusEndpointType(P.radsecPoolType);
|
||||
Start();
|
||||
}
|
||||
|
||||
~RADIUS_Destination() override { Stop(); }
|
||||
|
||||
const int SMALLEST_RADIUS_PACKET = 20 + 19 + 4;
|
||||
const int DEFAULT_RADIUS_AUTHENTICATION_PORT = 1812;
|
||||
const int DEFAULT_RADIUS_ACCOUNTING_PORT = 1813;
|
||||
const int DEFAULT_RADIUS_CoA_PORT = 3799;
|
||||
|
||||
inline int Start() {
|
||||
ReconnectThread_.start(*this);
|
||||
return 0;
|
||||
}
|
||||
|
||||
inline void Stop() {
|
||||
TryAgain_ = false;
|
||||
Disconnect();
|
||||
ReconnectThread_.wakeUp();
|
||||
ReconnectThread_.join();
|
||||
}
|
||||
|
||||
inline void run() final {
|
||||
Poco::Thread::trySleep(5000);
|
||||
std::uint64_t CurrentDelay = 10, maxDelay=300, LastTry=0, LastKeepAlive=0;
|
||||
while (TryAgain_) {
|
||||
if (!Connected_) {
|
||||
if(!LastTry || (Utils::Now()-LastTry)>CurrentDelay) {
|
||||
LastTry = Utils::Now();
|
||||
if (!Connect()) {
|
||||
CurrentDelay *= 2;
|
||||
if(CurrentDelay>maxDelay) CurrentDelay=10;
|
||||
} else {
|
||||
CurrentDelay = 10;
|
||||
}
|
||||
}
|
||||
} else if ((Utils::Now() - LastKeepAlive) > Pool_.radsecKeepAlive) {
|
||||
RADIUS::RadiusOutputPacket P(Pool_.authConfig.servers[ServerIndex_].radsecSecret);
|
||||
P.MakeStatusMessage(Pool_.authConfig.servers[ServerIndex_].name);
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
inline bool SendData(const std::string &serial_number, const unsigned char *buffer,
|
||||
int length) {
|
||||
try {
|
||||
if (Connected_) {
|
||||
RADIUS::RadiusPacket P(buffer, length);
|
||||
int sent_bytes;
|
||||
if (P.VerifyMessageAuthenticator(Pool_.authConfig.servers[ServerIndex_].radsecSecret)) {
|
||||
poco_trace(Logger_, fmt::format("{}: {} Sending {} bytes", serial_number,
|
||||
P.PacketType(), length));
|
||||
sent_bytes = Socket_->sendBytes(buffer, length);
|
||||
} else {
|
||||
poco_trace(Logger_, fmt::format("{}: {} Sending {} bytes", serial_number,
|
||||
P.PacketType(), length));
|
||||
P.ComputeMessageAuthenticator(Pool_.authConfig.servers[ServerIndex_].radsecSecret);
|
||||
sent_bytes = Socket_->sendBytes(P.Buffer(), length);
|
||||
}
|
||||
return (sent_bytes == length);
|
||||
}
|
||||
} catch (const Poco::Exception &E) {
|
||||
Logger_.log(E);
|
||||
} catch (...) {
|
||||
poco_warning(Logger_, "Exception occurred: while sending data.");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
inline void
|
||||
onData([[maybe_unused]] const Poco::AutoPtr<Poco::Net::ReadableNotification> &pNf) {
|
||||
unsigned char Buffer[4096];
|
||||
|
||||
try {
|
||||
auto NumberOfReceivedBytes = Socket_->receiveBytes(Buffer, sizeof(Buffer));
|
||||
std::string ReplySource;
|
||||
if (NumberOfReceivedBytes >= 20) {
|
||||
RADIUS::RadiusPacket P(Buffer, NumberOfReceivedBytes);
|
||||
if (P.IsAuthentication()) {
|
||||
auto SerialNumber = P.ExtractSerialNumberFromProxyState();
|
||||
if (!SerialNumber.empty()) {
|
||||
poco_debug(Logger_,
|
||||
fmt::format("{}: {}:{} Received {} bytes.", SerialNumber,
|
||||
P.PacketType(),
|
||||
P.PacketTypeToString(),
|
||||
NumberOfReceivedBytes));
|
||||
AP_WS_Server()->SendRadiusAuthenticationData(SerialNumber, Buffer,
|
||||
NumberOfReceivedBytes);
|
||||
} else if(P.IsStatusMessageReply(ReplySource)) {
|
||||
poco_debug(Logger_,
|
||||
fmt::format("{}: Keepalive message received.", ReplySource));
|
||||
} else {
|
||||
poco_debug(Logger_, "AUTH packet dropped.");
|
||||
}
|
||||
} else if (P.IsAccounting()) {
|
||||
auto SerialNumber = P.ExtractSerialNumberFromProxyState();
|
||||
if (!SerialNumber.empty()) {
|
||||
poco_debug(Logger_,
|
||||
fmt::format("{}: {}:{} Received {} bytes.", SerialNumber,
|
||||
P.PacketType(),
|
||||
P.PacketTypeToString(), NumberOfReceivedBytes));
|
||||
AP_WS_Server()->SendRadiusAccountingData(SerialNumber, Buffer,
|
||||
NumberOfReceivedBytes);
|
||||
} else {
|
||||
poco_debug(Logger_, "ACCT packet dropped.");
|
||||
}
|
||||
} else if (P.IsAuthority()) {
|
||||
auto SerialNumber = P.ExtractSerialNumberTIP();
|
||||
if (!SerialNumber.empty()) {
|
||||
poco_debug(Logger_,
|
||||
fmt::format("{}: {}:{} Received {} bytes.", SerialNumber,
|
||||
P.PacketType(),
|
||||
P.PacketTypeToString(), NumberOfReceivedBytes));
|
||||
AP_WS_Server()->SendRadiusCoAData(SerialNumber, Buffer,
|
||||
NumberOfReceivedBytes);
|
||||
} else {
|
||||
poco_debug(Logger_, "CoA/DM packet dropped.");
|
||||
}
|
||||
} else {
|
||||
poco_warning(Logger_,
|
||||
fmt::format("Unknown packet: Type: {} (type={}) Length={}",
|
||||
P.PacketType(), P.PacketTypeInt(), P.BufferLen()));
|
||||
}
|
||||
return;
|
||||
} else {
|
||||
poco_warning(Logger_, "Invalid packet received. Resetting the connection.");
|
||||
}
|
||||
} catch (const Poco::Exception &E) {
|
||||
Logger_.log(E);
|
||||
} catch (...) {
|
||||
poco_warning(Logger_, "Exception occurred. Resetting the connection.");
|
||||
}
|
||||
Disconnect();
|
||||
}
|
||||
|
||||
inline void
|
||||
onError([[maybe_unused]] const Poco::AutoPtr<Poco::Net::ErrorNotification> &pNf) {
|
||||
poco_warning(Logger_, "Socker error. Terminating connection.");
|
||||
Disconnect();
|
||||
}
|
||||
|
||||
inline void
|
||||
onShutdown([[maybe_unused]] const Poco::AutoPtr<Poco::Net::ShutdownNotification> &pNf) {
|
||||
poco_warning(Logger_, "Socker socket shutdown. Terminating connection.");
|
||||
Disconnect();
|
||||
}
|
||||
|
||||
inline void OnAccountingSocketReadable(
|
||||
const Poco::AutoPtr<Poco::Net::ReadableNotification> &pNf) {
|
||||
Poco::Net::SocketAddress Sender;
|
||||
RADIUS::RadiusPacket P;
|
||||
|
||||
auto ReceiveSize = pNf->socket().impl()->receiveBytes(P.Buffer(), P.BufferLen());
|
||||
if (ReceiveSize < SMALLEST_RADIUS_PACKET) {
|
||||
poco_warning(Logger_, "Accounting: bad packet received.");
|
||||
return;
|
||||
}
|
||||
P.Evaluate(ReceiveSize);
|
||||
auto SerialNumber = P.ExtractSerialNumberFromProxyState();
|
||||
if (SerialNumber.empty()) {
|
||||
poco_warning(Logger_, "Accounting: missing serial number. Dropping request.");
|
||||
return;
|
||||
}
|
||||
poco_debug(
|
||||
Logger_,
|
||||
fmt::format(
|
||||
"Accounting Packet Response received for {}", SerialNumber ));
|
||||
AP_WS_Server()->SendRadiusAccountingData(SerialNumber, P.Buffer(), P.Size());
|
||||
}
|
||||
|
||||
inline void OnAuthenticationSocketReadable(
|
||||
const Poco::AutoPtr<Poco::Net::ReadableNotification> &pNf) {
|
||||
Poco::Net::SocketAddress Sender;
|
||||
RADIUS::RadiusPacket P;
|
||||
|
||||
auto ReceiveSize = pNf->socket().impl()->receiveBytes(P.Buffer(), P.BufferLen());
|
||||
if (ReceiveSize < SMALLEST_RADIUS_PACKET) {
|
||||
poco_warning(Logger_, "Authentication: bad packet received.");
|
||||
return;
|
||||
}
|
||||
P.Evaluate(ReceiveSize);
|
||||
|
||||
if(Logger_.trace()) {
|
||||
P.Log(std::cout);
|
||||
}
|
||||
auto SerialNumber = P.ExtractSerialNumberFromProxyState();
|
||||
if (SerialNumber.empty()) {
|
||||
poco_warning(Logger_, "Authentication: missing serial number. Dropping request.");
|
||||
return;
|
||||
}
|
||||
auto CallingStationID = P.ExtractCallingStationID();
|
||||
auto CalledStationID = P.ExtractCalledStationID();
|
||||
|
||||
poco_debug(
|
||||
Logger_,
|
||||
fmt::format(
|
||||
"Authentication Packet received for {}, CalledStationID: {}, CallingStationID:{}",
|
||||
SerialNumber, CalledStationID, CallingStationID));
|
||||
AP_WS_Server()->SendRadiusAuthenticationData(SerialNumber, P.Buffer(), P.Size());
|
||||
}
|
||||
|
||||
inline void OnCoASocketReadable(
|
||||
const Poco::AutoPtr<Poco::Net::ReadableNotification> &pNf) {
|
||||
Poco::Net::SocketAddress Sender;
|
||||
RADIUS::RadiusPacket P;
|
||||
|
||||
auto ReceiveSize = pNf.get()->socket().impl()->receiveBytes(P.Buffer(), P.BufferLen());
|
||||
if (ReceiveSize < SMALLEST_RADIUS_PACKET) {
|
||||
poco_warning(Logger_, "CoA/DM: bad packet received.");
|
||||
return;
|
||||
}
|
||||
|
||||
P.Evaluate(ReceiveSize);
|
||||
auto SerialNumber = P.ExtractSerialNumberTIP();
|
||||
if (SerialNumber.empty()) {
|
||||
poco_warning(Logger_, "CoA/DM: missing serial number. Dropping request.");
|
||||
return;
|
||||
}
|
||||
auto CallingStationID = P.ExtractCallingStationID();
|
||||
auto CalledStationID = P.ExtractCalledStationID();
|
||||
|
||||
poco_debug(
|
||||
Logger_,
|
||||
fmt::format("CoA Packet received for {}, CalledStationID: {}, CallingStationID:{}",
|
||||
SerialNumber, CalledStationID, CallingStationID));
|
||||
AP_WS_Server()->SendRadiusCoAData(SerialNumber, P.Buffer(), P.Size());
|
||||
}
|
||||
|
||||
static inline bool IsExpired(const Poco::Crypto::X509Certificate &C) {
|
||||
return C.expiresOn().timestamp().epochTime() < (std::time_t)Utils::Now();
|
||||
}
|
||||
|
||||
static inline void Cat(const std::string &F1, const std::string & F2, const std::string &F) {
|
||||
std::ofstream of(F.c_str(),std::ios_base::trunc|std::ios_base::out|std::ios_base::binary);
|
||||
std::ifstream if1(F1.c_str(),std::ios_base::binary|std::ios_base::in);
|
||||
Poco::StreamCopier::copyStream(if1,of);
|
||||
of << std::endl;
|
||||
std::ifstream if2(F2.c_str(),std::ios_base::binary|std::ios_base::in);
|
||||
Poco::StreamCopier::copyStream(if2,of);
|
||||
of << std::endl;
|
||||
of.close();
|
||||
}
|
||||
|
||||
inline bool Connect_GlobalReach() {
|
||||
|
||||
if (TryAgain_) {
|
||||
std::lock_guard G(LocalMutex_);
|
||||
|
||||
Poco::TemporaryFile CertFile_(MicroServiceDataDirectory());
|
||||
Poco::TemporaryFile KeyFile_(MicroServiceDataDirectory());
|
||||
Poco::TemporaryFile OpenRoamingRootCertFile_(MicroServiceDataDirectory());
|
||||
Poco::TemporaryFile Intermediate0(MicroServiceDataDirectory());
|
||||
Poco::TemporaryFile Intermediate1(MicroServiceDataDirectory());
|
||||
|
||||
DecodeFile(KeyFile_.path(), Pool_.acctConfig.servers[ServerIndex_].radsecKey);
|
||||
DecodeFile(CertFile_.path(), Pool_.acctConfig.servers[ServerIndex_].radsecCert);
|
||||
DecodeFile(Intermediate0.path(), Pool_.acctConfig.servers[ServerIndex_].radsecCacerts[0]);
|
||||
DecodeFile(Intermediate1.path(), Pool_.acctConfig.servers[ServerIndex_].radsecCacerts[1]);
|
||||
|
||||
const static std::string OpenRoamingRootCert{
|
||||
"-----BEGIN CERTIFICATE-----\n"
|
||||
"MIIClDCCAhugAwIBAgIUF1f+h+uJNHyr+ZqTpwew8LYRAW0wCgYIKoZIzj0EAwMw\n"
|
||||
"gYkxCzAJBgNVBAYTAkdCMQ8wDQYDVQQIEwZMb25kb24xDzANBgNVBAcTBkxvbmRv\n"
|
||||
"bjEsMCoGA1UEChMjR2xvYmFsUmVhY2ggVGVjaG5vbG9neSBFTUVBIExpbWl0ZWQx\n"
|
||||
"KjAoBgNVBAMTIUdsb2JhbFJlYWNoIENlcnRpZmljYXRlIEF1dGhvcml0eTAeFw0y\n"
|
||||
"MzA3MTQwOTMyMDBaFw00MzA3MDkwOTMyMDBaMIGJMQswCQYDVQQGEwJHQjEPMA0G\n"
|
||||
"A1UECBMGTG9uZG9uMQ8wDQYDVQQHEwZMb25kb24xLDAqBgNVBAoTI0dsb2JhbFJl\n"
|
||||
"YWNoIFRlY2hub2xvZ3kgRU1FQSBMaW1pdGVkMSowKAYDVQQDEyFHbG9iYWxSZWFj\n"
|
||||
"aCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAARy\n"
|
||||
"f02umFNy5W/TtM5nfMaLhRF61vLxhT8iNQHR1mXiRmNdME3ArForBcAm2eolHPcJ\n"
|
||||
"RH9DcXs59d2zzoPEaBjXADTCjUts3F7G6fjqvfki2e/txx/xfUopQO8G54XcFWqj\n"
|
||||
"QjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRS\n"
|
||||
"tNe7MgAFwTaMZKUtS1/8pVoBqjAKBggqhkjOPQQDAwNnADBkAjA7VKHTybtSMBcN\n"
|
||||
"717jGYvkWlcj4c9/LzPtkHO053wGsPigaq+1SjY7tDhS/g9oUQACMA6UqH2e8cfn\n"
|
||||
"cZqmBNVNN3DBjIb4anug7F+FnYOQF36ua6MLBeGn3aKxvu1aO+hjPg==\n"
|
||||
"-----END CERTIFICATE-----\n"};
|
||||
|
||||
std::ofstream ofs{OpenRoamingRootCertFile_.path().c_str(),
|
||||
std::ios_base::trunc | std::ios_base::out |
|
||||
std::ios_base::binary};
|
||||
ofs << OpenRoamingRootCert;
|
||||
ofs.close();
|
||||
|
||||
auto SecureContext = Poco::AutoPtr<Poco::Net::Context>(
|
||||
new Poco::Net::Context(Poco::Net::Context::TLS_CLIENT_USE, ""));
|
||||
|
||||
if (Pool_.acctConfig.servers[ServerIndex_].allowSelfSigned) {
|
||||
SecureContext->setSecurityLevel(Poco::Net::Context::SECURITY_LEVEL_NONE);
|
||||
SecureContext->enableExtendedCertificateVerification(false);
|
||||
}
|
||||
|
||||
SecureContext->usePrivateKey(Poco::Crypto::RSAKey("", KeyFile_.path(), ""));
|
||||
Poco::Crypto::X509Certificate Cert(CertFile_.path());
|
||||
if (!IsExpired(Cert)) {
|
||||
SecureContext->useCertificate(Poco::Crypto::X509Certificate(CertFile_.path()));
|
||||
} else {
|
||||
poco_error(
|
||||
Logger_,
|
||||
fmt::format(
|
||||
"Certificate for {} has expired. We cannot connect to this server.",
|
||||
Pool_.acctConfig.servers[ServerIndex_].name));
|
||||
return false;
|
||||
}
|
||||
|
||||
SecureContext->addCertificateAuthority(
|
||||
Poco::Crypto::X509Certificate(OpenRoamingRootCertFile_.path()));
|
||||
SecureContext->addChainCertificate(
|
||||
Poco::Crypto::X509Certificate(Intermediate0.path()));
|
||||
SecureContext->addChainCertificate(
|
||||
Poco::Crypto::X509Certificate(Intermediate1.path()));
|
||||
SecureContext->enableExtendedCertificateVerification(false);
|
||||
|
||||
Socket_ = std::make_unique<Poco::Net::SecureStreamSocket>(SecureContext);
|
||||
ServerIndex_ = 0 ;
|
||||
for (const auto &PoolEntryServer : Pool_.acctConfig.servers) {
|
||||
Poco::Net::SocketAddress Destination(PoolEntryServer.ip, PoolEntryServer.port);
|
||||
try {
|
||||
poco_information(Logger_, fmt::format("Attempting to connect to {}", CommonName()));
|
||||
Socket_->connect(Destination, Poco::Timespan(20, 0));
|
||||
Socket_->completeHandshake();
|
||||
|
||||
if (!Pool_.authConfig.servers[ServerIndex_].allowSelfSigned) {
|
||||
Socket_->verifyPeerCertificate();
|
||||
}
|
||||
|
||||
if (Socket_->havePeerCertificate()) {
|
||||
Peer_Cert_ = std::make_unique<Poco::Crypto::X509Certificate>(
|
||||
Socket_->peerCertificate());
|
||||
}
|
||||
|
||||
Socket_->setBlocking(false);
|
||||
Socket_->setNoDelay(true);
|
||||
Socket_->setKeepAlive(true);
|
||||
Socket_->setReceiveTimeout(Poco::Timespan(1 * 60 * 60, 0));
|
||||
|
||||
Reactor_.addEventHandler(
|
||||
*Socket_,
|
||||
Poco::NObserver<RADIUS_Destination, Poco::Net::ReadableNotification>(
|
||||
*this, &RADIUS_Destination::onData));
|
||||
Reactor_.addEventHandler(
|
||||
*Socket_, Poco::NObserver<RADIUS_Destination, Poco::Net::ErrorNotification>(
|
||||
*this, &RADIUS_Destination::onError));
|
||||
Reactor_.addEventHandler(
|
||||
*Socket_,
|
||||
Poco::NObserver<RADIUS_Destination, Poco::Net::ShutdownNotification>(
|
||||
*this, &RADIUS_Destination::onShutdown));
|
||||
|
||||
Connected_ = true;
|
||||
poco_information(Logger_, fmt::format("Connected. CN={}", CommonName()));
|
||||
return true;
|
||||
} catch (const Poco::Net::NetException &E) {
|
||||
poco_warning(Logger_, "NetException: Could not connect.");
|
||||
Logger_.log(E);
|
||||
} catch (const Poco::Exception &E) {
|
||||
poco_warning(Logger_, "Exception: Could not connect.");
|
||||
Logger_.log(E);
|
||||
} catch (...) {
|
||||
poco_warning(Logger_, "Could not connect.");
|
||||
}
|
||||
ServerIndex_++;
|
||||
}
|
||||
}
|
||||
ServerIndex_=0;
|
||||
return false;
|
||||
}
|
||||
|
||||
inline bool Connect_Orion() {
|
||||
if (TryAgain_) {
|
||||
std::lock_guard G(LocalMutex_);
|
||||
|
||||
Poco::TemporaryFile CertFile_(MicroServiceDataDirectory());
|
||||
Poco::TemporaryFile KeyFile_(MicroServiceDataDirectory());
|
||||
std::vector<std::unique_ptr<Poco::TemporaryFile>> CaCertFiles_;
|
||||
|
||||
DecodeFile(CertFile_.path(), Pool_.acctConfig.servers[ServerIndex_].radsecCert);
|
||||
DecodeFile(KeyFile_.path(), Pool_.acctConfig.servers[ServerIndex_].radsecKey);
|
||||
|
||||
Poco::Crypto::X509Certificate Cert(CertFile_.path());
|
||||
if(IsExpired(Cert)) {
|
||||
poco_error(Logger_, fmt::format("Certificate for {} has expired. We cannot connect to this server.", Pool_.acctConfig.servers[ServerIndex_].name));
|
||||
return false;
|
||||
}
|
||||
|
||||
for (auto &cert : Pool_.acctConfig.servers[ServerIndex_].radsecCacerts) {
|
||||
CaCertFiles_.emplace_back(
|
||||
std::make_unique<Poco::TemporaryFile>(MicroServiceDataDirectory()));
|
||||
DecodeFile(CaCertFiles_[CaCertFiles_.size() - 1]->path(), cert);
|
||||
}
|
||||
|
||||
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) {
|
||||
SecureContext->setSecurityLevel(Poco::Net::Context::SECURITY_LEVEL_NONE);
|
||||
SecureContext->enableExtendedCertificateVerification(false);
|
||||
}
|
||||
|
||||
for (const auto &ca : CaCertFiles_) {
|
||||
Poco::Crypto::X509Certificate cert(ca->path());
|
||||
SecureContext->addCertificateAuthority(cert);
|
||||
}
|
||||
|
||||
Socket_ = std::make_unique<Poco::Net::SecureStreamSocket>(SecureContext);
|
||||
ServerIndex_ = 0 ;
|
||||
for (const auto &PoolEntryServer : Pool_.acctConfig.servers) {
|
||||
Poco::Net::SocketAddress Destination(PoolEntryServer.ip, PoolEntryServer.port);
|
||||
try {
|
||||
poco_information(Logger_, "Attempting to connect");
|
||||
Socket_->connect(Destination, Poco::Timespan(100, 0));
|
||||
Socket_->completeHandshake();
|
||||
|
||||
if (!Pool_.authConfig.servers[ServerIndex_].allowSelfSigned) {
|
||||
Socket_->verifyPeerCertificate();
|
||||
}
|
||||
|
||||
if (Socket_->havePeerCertificate()) {
|
||||
Peer_Cert_ = std::make_unique<Poco::Crypto::X509Certificate>(
|
||||
Socket_->peerCertificate());
|
||||
}
|
||||
|
||||
Socket_->setBlocking(false);
|
||||
Socket_->setNoDelay(true);
|
||||
Socket_->setKeepAlive(true);
|
||||
Socket_->setReceiveTimeout(Poco::Timespan(1 * 60 * 60, 0));
|
||||
|
||||
Reactor_.addEventHandler(
|
||||
*Socket_,
|
||||
Poco::NObserver<RADIUS_Destination, Poco::Net::ReadableNotification>(
|
||||
*this, &RADIUS_Destination::onData));
|
||||
Reactor_.addEventHandler(
|
||||
*Socket_, Poco::NObserver<RADIUS_Destination, Poco::Net::ErrorNotification>(
|
||||
*this, &RADIUS_Destination::onError));
|
||||
Reactor_.addEventHandler(
|
||||
*Socket_,
|
||||
Poco::NObserver<RADIUS_Destination, Poco::Net::ShutdownNotification>(
|
||||
*this, &RADIUS_Destination::onShutdown));
|
||||
|
||||
Connected_ = true;
|
||||
poco_information(Logger_, fmt::format("Connected. CN={}", CommonName()));
|
||||
return true;
|
||||
} catch (const Poco::Net::NetException &E) {
|
||||
poco_information(Logger_, "Could not connect.");
|
||||
Logger_.log(E);
|
||||
} catch (const Poco::Exception &E) {
|
||||
poco_information(Logger_, "Could not connect.");
|
||||
Logger_.log(E);
|
||||
} catch (...) {
|
||||
poco_information(Logger_, "Could not connect.");
|
||||
}
|
||||
ServerIndex_++;
|
||||
}
|
||||
}
|
||||
ServerIndex_=0;
|
||||
return false;
|
||||
}
|
||||
|
||||
inline bool Connect_Generic() {
|
||||
poco_information(Logger_, fmt::format("Connecting {}", Pool_.name));
|
||||
if (TryAgain_ && !Connected_) {
|
||||
|
||||
std::lock_guard G(LocalMutex_);
|
||||
|
||||
Poco::Net::SocketAddress AuthSockAddrV4(
|
||||
Poco::Net::AddressFamily::IPv4,
|
||||
MicroServiceConfigGetInt("radius.proxy.authentication.port",
|
||||
DEFAULT_RADIUS_AUTHENTICATION_PORT));
|
||||
AuthenticationSocketV4_ =
|
||||
std::make_unique<Poco::Net::DatagramSocket>(AuthSockAddrV4, true, true);
|
||||
|
||||
Poco::Net::SocketAddress AcctSockAddrV4(
|
||||
Poco::Net::AddressFamily::IPv4,
|
||||
MicroServiceConfigGetInt("radius.proxy.accounting.port",
|
||||
DEFAULT_RADIUS_ACCOUNTING_PORT));
|
||||
AccountingSocketV4_ =
|
||||
std::make_unique<Poco::Net::DatagramSocket>(AcctSockAddrV4, true, true);
|
||||
|
||||
Poco::Net::SocketAddress CoASockAddrV4(
|
||||
Poco::Net::AddressFamily::IPv4,
|
||||
MicroServiceConfigGetInt("radius.proxy.coa.port", DEFAULT_RADIUS_CoA_PORT));
|
||||
CoASocketV4_ = std::make_unique<Poco::Net::DatagramSocket>(CoASockAddrV4, true, true);
|
||||
|
||||
Reactor_.addEventHandler(
|
||||
*AuthenticationSocketV4_,
|
||||
Poco::NObserver<RADIUS_Destination, Poco::Net::ReadableNotification>(
|
||||
*this, &RADIUS_Destination::OnAuthenticationSocketReadable));
|
||||
Reactor_.addEventHandler(
|
||||
*AccountingSocketV4_,
|
||||
Poco::NObserver<RADIUS_Destination, Poco::Net::ReadableNotification>(
|
||||
*this, &RADIUS_Destination::OnAccountingSocketReadable));
|
||||
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>(
|
||||
*this, &RADIUS_Destination::OnAuthenticationSocketReadable));
|
||||
Reactor_.addEventHandler(
|
||||
*AccountingSocketV6_,
|
||||
Poco::NObserver<RADIUS_Destination, Poco::Net::ReadableNotification>(
|
||||
*this, &RADIUS_Destination::OnAccountingSocketReadable));
|
||||
|
||||
Reactor_.addEventHandler(
|
||||
*CoASocketV6_, Poco::NObserver<RADIUS_Destination, Poco::Net::ReadableNotification>(
|
||||
*this, &RADIUS_Destination::OnCoASocketReadable));
|
||||
*/
|
||||
Connected_ = true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool Connect_Radsec() {
|
||||
if (TryAgain_) {
|
||||
std::lock_guard G(LocalMutex_);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool Connect() {
|
||||
switch(Type_) {
|
||||
case GWObjects::RadiusEndpointType::orion: return Connect_Orion();
|
||||
case GWObjects::RadiusEndpointType::globalreach: return Connect_GlobalReach();
|
||||
case GWObjects::RadiusEndpointType::radsec: return Connect_Radsec();
|
||||
default:
|
||||
return Connect_Generic();
|
||||
}
|
||||
}
|
||||
|
||||
inline void Disconnect() {
|
||||
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_,
|
||||
Poco::NObserver<RADIUS_Destination, Poco::Net::ReadableNotification>(
|
||||
*this, &RADIUS_Destination::OnAuthenticationSocketReadable));
|
||||
AuthenticationSocketV4_->close();
|
||||
AuthenticationSocketV4_.reset();
|
||||
}
|
||||
|
||||
if(AccountingSocketV4_) {
|
||||
Reactor_.removeEventHandler(
|
||||
*AccountingSocketV4_,
|
||||
Poco::NObserver<RADIUS_Destination, Poco::Net::ReadableNotification>(
|
||||
*this, &RADIUS_Destination::OnAccountingSocketReadable));
|
||||
AccountingSocketV4_->close();
|
||||
AccountingSocketV4_.reset();
|
||||
}
|
||||
|
||||
if(CoASocketV4_) {
|
||||
Reactor_.removeEventHandler(
|
||||
*CoASocketV4_,
|
||||
Poco::NObserver<RADIUS_Destination, Poco::Net::ReadableNotification>(
|
||||
*this, &RADIUS_Destination::OnCoASocketReadable));
|
||||
CoASocketV4_->close();
|
||||
CoASocketV4_.reset();
|
||||
}
|
||||
|
||||
/*
|
||||
if(AuthenticationSocketV6_) {
|
||||
Reactor_.removeEventHandler(
|
||||
*AuthenticationSocketV6_,
|
||||
Poco::NObserver<RADIUS_Destination, Poco::Net::ReadableNotification>(
|
||||
*this, &RADIUS_Destination::OnAuthenticationSocketReadable));
|
||||
AuthenticationSocketV6_->close();
|
||||
AuthenticationSocketV6_.reset();
|
||||
}
|
||||
|
||||
if(AccountingSocketV6_) {
|
||||
Reactor_.removeEventHandler(
|
||||
*AccountingSocketV6_,
|
||||
Poco::NObserver<RADIUS_Destination, Poco::Net::ReadableNotification>(
|
||||
*this, &RADIUS_Destination::OnAccountingSocketReadable));
|
||||
AccountingSocketV6_->close();
|
||||
AccountingSocketV6_.reset();
|
||||
}
|
||||
|
||||
if(CoASocketV6_) {
|
||||
Reactor_.removeEventHandler(
|
||||
*CoASocketV6_,
|
||||
Poco::NObserver<RADIUS_Destination, Poco::Net::ReadableNotification>(
|
||||
*this, &RADIUS_Destination::OnCoASocketReadable));
|
||||
CoASocketV6_->close();
|
||||
CoASocketV6_.reset();
|
||||
}
|
||||
*/
|
||||
} else {
|
||||
if(Socket_!=nullptr) {
|
||||
Reactor_.removeEventHandler(
|
||||
*Socket_, Poco::NObserver<RADIUS_Destination, Poco::Net::ReadableNotification>(
|
||||
*this, &RADIUS_Destination::onData));
|
||||
Reactor_.removeEventHandler(
|
||||
*Socket_, Poco::NObserver<RADIUS_Destination, Poco::Net::ErrorNotification>(
|
||||
*this, &RADIUS_Destination::onError));
|
||||
Reactor_.removeEventHandler(
|
||||
*Socket_,
|
||||
Poco::NObserver<RADIUS_Destination, Poco::Net::ShutdownNotification>(
|
||||
*this, &RADIUS_Destination::onShutdown));
|
||||
Socket_->close();
|
||||
}
|
||||
}
|
||||
Connected_ = false;
|
||||
}
|
||||
poco_information(Logger_, fmt::format("Disconnecting {}", Pool_.name));
|
||||
}
|
||||
|
||||
static void DecodeFile(const std::string &filename, const std::string &s) {
|
||||
std::ofstream sec_file(filename, std::ios_base::out | std::ios_base::trunc |
|
||||
std::ios_base::binary);
|
||||
std::stringstream is(s);
|
||||
Poco::Base64Decoder ds(is);
|
||||
Poco::StreamCopier::copyStream(ds, sec_file);
|
||||
sec_file.close();
|
||||
}
|
||||
|
||||
[[nodiscard]] inline std::string CommonName() {
|
||||
if (Peer_Cert_)
|
||||
return Peer_Cert_->commonName();
|
||||
return "";
|
||||
}
|
||||
|
||||
[[nodiscard]] inline std::string IssuerName() {
|
||||
if (Peer_Cert_)
|
||||
return Peer_Cert_->issuerName();
|
||||
return "";
|
||||
}
|
||||
|
||||
[[nodiscard]] inline std::string SubjectName() {
|
||||
if (Peer_Cert_)
|
||||
return Peer_Cert_->subjectName();
|
||||
return "";
|
||||
}
|
||||
|
||||
const auto &Pool() const { return Pool_; }
|
||||
auto ServerType() const { return Type_; }
|
||||
|
||||
inline bool SendRadiusDataAuthData(const std::string &serialNumber, const unsigned char *buffer, std::size_t size) {
|
||||
poco_trace(Logger_, fmt::format("{}: Sending RADIUS Auth {} bytes.", serialNumber, size));
|
||||
AuthenticationSocketV4_->sendTo(buffer, size, Poco::Net::SocketAddress(Pool_.authConfig.servers[0].ip, Pool_.authConfig.servers[0].port));
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool SendRadiusDataAcctData(const std::string &serialNumber, const unsigned char *buffer, std::size_t size) {
|
||||
poco_trace(Logger_, fmt::format("{}: Sending RADIUS Acct {} bytes.", serialNumber, size));
|
||||
AccountingSocketV4_->sendTo(buffer, size, Poco::Net::SocketAddress(Pool_.acctConfig.servers[0].ip, Pool_.acctConfig.servers[0].port));
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool SendRadiusDataCoAData(const std::string &serialNumber, const unsigned char *buffer, std::size_t size) {
|
||||
poco_trace(Logger_, fmt::format("{}: Sending RADIUS CoA {} bytes.", serialNumber, size));
|
||||
CoASocketV4_->sendTo(buffer, size, Poco::Net::SocketAddress(Pool_.coaConfig.servers[0].ip, Pool_.coaConfig.servers[0].port));
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
std::recursive_mutex LocalMutex_;
|
||||
Poco::Net::SocketReactor &Reactor_;
|
||||
Poco::Logger &Logger_;
|
||||
|
||||
std::unique_ptr<Poco::Net::SecureStreamSocket> Socket_;
|
||||
|
||||
std::unique_ptr<Poco::Net::DatagramSocket> AccountingSocketV4_;
|
||||
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> AccountingSocketV6_;
|
||||
std::unique_ptr<Poco::Net::DatagramSocket> AuthenticationSocketV6_;
|
||||
*/
|
||||
|
||||
Poco::Thread ReconnectThread_;
|
||||
std::unique_ptr<Poco::Crypto::X509Certificate> Peer_Cert_;
|
||||
volatile bool Connected_ = false;
|
||||
volatile bool TryAgain_ = true;
|
||||
enum GWObjects::RadiusEndpointType Type_{GWObjects::RadiusEndpointType::unknown};
|
||||
GWObjects::RadiusProxyPool Pool_;
|
||||
uint64_t ServerIndex_=0;
|
||||
};
|
||||
} // namespace OpenWifi
|
||||
@@ -14,6 +14,8 @@
|
||||
#include "Poco/Net/SocketAddress.h"
|
||||
#include "Poco/StringTokenizer.h"
|
||||
|
||||
#include <framework/utils.h>
|
||||
|
||||
namespace OpenWifi::RADIUS {
|
||||
|
||||
// Packet types
|
||||
@@ -66,6 +68,7 @@ namespace OpenWifi::RADIUS {
|
||||
constexpr std::uint8_t ACCT_INPUT_GIGAWORDS = 52;
|
||||
constexpr std::uint8_t ACCT_OUTPUT_GIGAWORDS = 53;
|
||||
constexpr std::uint8_t EVENT_TIMESTAMP = 55;
|
||||
constexpr std::uint8_t TUNNEL_PRIVATE_GROUP_ID = 81;
|
||||
constexpr std::uint8_t MESSAGE_AUTHENTICATOR = 80;
|
||||
constexpr std::uint8_t CHARGEABLE_USER_IDENTITY = 89;
|
||||
};
|
||||
@@ -406,6 +409,15 @@ namespace OpenWifi::RADIUS {
|
||||
|
||||
friend std::ostream &operator<<(std::ostream &os, RadiusPacket const &P);
|
||||
|
||||
[[nodiscard]] inline std::string PacketTypeToString() const {
|
||||
|
||||
for(auto const &Name:radius_command_values) {
|
||||
if(Name.cmd == P_.code)
|
||||
return Name.name;
|
||||
}
|
||||
return "Unknown";
|
||||
}
|
||||
|
||||
inline bool IsAuthentication() {
|
||||
return (P_.code == RADIUS::Access_Request || P_.code == RADIUS::Access_Accept ||
|
||||
P_.code == RADIUS::Access_Challenge || P_.code == RADIUS::Access_Reject ||
|
||||
@@ -426,6 +438,25 @@ namespace OpenWifi::RADIUS {
|
||||
P_.code == RADIUS::CoA_ACK || P_.code == RADIUS::CoA_NAK);
|
||||
}
|
||||
|
||||
inline bool IsStatusMessageReply(std::string &ReplySource) {
|
||||
std::string Result;
|
||||
for (const auto &attribute : Attrs_) {
|
||||
if (attribute.type == RADIUS::Attributes::PROXY_STATE) {
|
||||
std::string Attr33;
|
||||
// format is statis:server name
|
||||
Attr33.assign((const char *)(const char *)&P_.attributes[attribute.pos],
|
||||
attribute.len);
|
||||
auto Parts = Poco::StringTokenizer(Attr33, ":");
|
||||
if(Parts.count() == 2 && Parts[0] == "status") {
|
||||
ReplySource = Parts[1];
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
DBGLINE
|
||||
return false;
|
||||
}
|
||||
void Log(std::ostream &os) {
|
||||
uint16_t p = 0;
|
||||
|
||||
@@ -622,7 +653,7 @@ namespace OpenWifi::RADIUS {
|
||||
std::string Attr33;
|
||||
// format is serial:IP:port:interface
|
||||
Attr33.assign((const char *)(const char *)&P_.attributes[attribute.pos],
|
||||
attribute.len - 2);
|
||||
attribute.len);
|
||||
auto Parts = Poco::StringTokenizer(Attr33, "|");
|
||||
if (Parts.count() == 4) {
|
||||
return Parts[0];
|
||||
@@ -645,7 +676,7 @@ namespace OpenWifi::RADIUS {
|
||||
// format is
|
||||
|
||||
Attr33.assign((const char *)(const char *)&P_.attributes[attribute.pos],
|
||||
attribute.len - 2);
|
||||
attribute.len);
|
||||
auto Parts = Poco::StringTokenizer(Attr33, "|");
|
||||
if (Parts.count() == 4) {
|
||||
Poco::Net::SocketAddress D(Parts[1], Parts[2]);
|
||||
@@ -662,12 +693,35 @@ namespace OpenWifi::RADIUS {
|
||||
return Result;
|
||||
}
|
||||
|
||||
std::uint32_t ExtractProxyStateDestinationIPint() const {
|
||||
std::string Result;
|
||||
for (const auto &attribute : Attrs_) {
|
||||
if (attribute.type == RADIUS::Attributes::PROXY_STATE && attribute.len > 2) {
|
||||
std::string Attr33;
|
||||
// format is
|
||||
|
||||
Attr33.assign((const char *)(const char *)&P_.attributes[attribute.pos],
|
||||
attribute.len);
|
||||
auto Parts = Poco::StringTokenizer(Attr33, "|");
|
||||
if (Parts.count() == 4) {
|
||||
return Utils::IPtoInt(Parts[1]);
|
||||
}
|
||||
Parts = Poco::StringTokenizer(Attr33, ":");
|
||||
if (Parts.count() == 4) {
|
||||
return Utils::IPtoInt(Parts[1]);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::string ExtractCallingStationID() const {
|
||||
std::string Result;
|
||||
for (const auto &attribute : Attrs_) {
|
||||
if (attribute.type == RADIUS::Attributes::CALLING_STATION_ID && attribute.len > 2) {
|
||||
if (attribute.type == RADIUS::Attributes::CALLING_STATION_ID && attribute.len > 0) {
|
||||
Result.assign((const char *)(const char *)&P_.attributes[attribute.pos],
|
||||
attribute.len - 2);
|
||||
attribute.len);
|
||||
return Result;
|
||||
}
|
||||
}
|
||||
@@ -677,9 +731,21 @@ namespace OpenWifi::RADIUS {
|
||||
std::string ExtractAccountingSessionID() const {
|
||||
std::string Result;
|
||||
for (const auto &attribute : Attrs_) {
|
||||
if (attribute.type == RADIUS::Attributes::ACCT_SESSION_ID && attribute.len > 2) {
|
||||
if (attribute.type == RADIUS::Attributes::ACCT_SESSION_ID && attribute.len > 0) {
|
||||
Result.assign((const char *)(const char *)&P_.attributes[attribute.pos],
|
||||
attribute.len - 2);
|
||||
attribute.len );
|
||||
return Result;
|
||||
}
|
||||
}
|
||||
return Result;
|
||||
}
|
||||
|
||||
std::string ExtractAccountingMultiSessionID() const {
|
||||
std::string Result;
|
||||
for (const auto &attribute : Attrs_) {
|
||||
if (attribute.type == RADIUS::Attributes::ACCT_MULTI_SESSION_ID && attribute.len > 0) {
|
||||
Result.assign((const char *)(const char *)&P_.attributes[attribute.pos],
|
||||
attribute.len );
|
||||
return Result;
|
||||
}
|
||||
}
|
||||
@@ -689,9 +755,9 @@ namespace OpenWifi::RADIUS {
|
||||
std::string ExtractCalledStationID() const {
|
||||
std::string Result;
|
||||
for (const auto &attribute : Attrs_) {
|
||||
if (attribute.type == RADIUS::Attributes::CALLED_STATION_ID && attribute.len > 2) {
|
||||
if (attribute.type == RADIUS::Attributes::CALLED_STATION_ID && attribute.len > 0) {
|
||||
Result.assign((const char *)(const char *)&P_.attributes[attribute.pos],
|
||||
attribute.len - 2);
|
||||
attribute.len);
|
||||
return Result;
|
||||
}
|
||||
}
|
||||
@@ -949,27 +1015,30 @@ namespace OpenWifi::RADIUS {
|
||||
public:
|
||||
explicit RadiusOutputPacket(const std::string &Secret) : Secret_(Secret) {}
|
||||
|
||||
inline void MakeStatusMessage() {
|
||||
inline void MakeStatusMessage(const std::string &Source) {
|
||||
P_.code = RADIUS::Status_Server;
|
||||
P_.identifier = std::rand() & 0x00ff;
|
||||
MakeRadiusAuthenticator(P_.authenticator);
|
||||
unsigned char MessageAuthenticator[16]{0};
|
||||
std::string FullSource = "status:" + Source;
|
||||
AddAttribute(RADIUS::Attributes::PROXY_STATE, FullSource.size(), (const unsigned char *)FullSource.c_str());
|
||||
AddAttribute(RADIUS::Attributes::MESSAGE_AUTHENTICATOR, sizeof(MessageAuthenticator),
|
||||
MessageAuthenticator);
|
||||
int PktLen = 1 + 1 + 2 + 16 + 1 + 1 + 16;
|
||||
// int PktLen = 1 + 1 + 2 + 16 + 1 + 1 + 16 ;
|
||||
int PktLen = 1 + 1 + 2 + 16 + AttributesLen_;
|
||||
P_.rawlen = htons(PktLen);
|
||||
|
||||
Poco::HMACEngine<Poco::MD5Engine> H(Secret_);
|
||||
H.update((const unsigned char *)&P_, PktLen);
|
||||
auto digest = H.digest();
|
||||
int p = 0;
|
||||
int p = 0, offset = (int)FullSource.size() + 2 ;
|
||||
for (const auto &i : digest)
|
||||
P_.attributes[1 + 1 + p++] = i;
|
||||
P_.attributes[offset + 1 + 1 + p++] = i;
|
||||
}
|
||||
|
||||
inline void AddAttribute(unsigned char attr, uint8_t len, const unsigned char *data) {
|
||||
P_.attributes[AttributesLen_++] = attr;
|
||||
P_.attributes[AttributesLen_++] = len;
|
||||
P_.attributes[AttributesLen_++] = len+2;
|
||||
memcpy(&P_.attributes[AttributesLen_], data, len);
|
||||
AttributesLen_ += len;
|
||||
}
|
||||
|
||||
@@ -13,12 +13,12 @@
|
||||
|
||||
namespace OpenWifi {
|
||||
|
||||
const int SMALLEST_RADIUS_PACKET = 20 + 19 + 4;
|
||||
/*
|
||||
const int SMALLEST_RADIUS_PACKET = 20 + 19 + 4;
|
||||
const int DEFAULT_RADIUS_AUTHENTICATION_PORT = 1812;
|
||||
const int DEFAULT_RADIUS_ACCOUNTING_PORT = 1813;
|
||||
const int DEFAULT_RADIUS_CoA_PORT = 3799;
|
||||
|
||||
|
||||
*/
|
||||
|
||||
int RADIUS_proxy_server::Start() {
|
||||
|
||||
@@ -27,7 +27,7 @@ namespace OpenWifi {
|
||||
|
||||
Enabled_ = MicroServiceConfigGetBool("radius.proxy.enable", false);
|
||||
if (!Enabled_ && !Config.exists()) {
|
||||
StopRADSECServers();
|
||||
StopRADIUSDestinations();
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -35,278 +35,81 @@ namespace OpenWifi {
|
||||
|
||||
Enabled_ = true;
|
||||
|
||||
Poco::Net::SocketAddress AuthSockAddrV4(
|
||||
Poco::Net::AddressFamily::IPv4,
|
||||
MicroServiceConfigGetInt("radius.proxy.authentication.port",
|
||||
DEFAULT_RADIUS_AUTHENTICATION_PORT));
|
||||
AuthenticationSocketV4_ =
|
||||
std::make_unique<Poco::Net::DatagramSocket>(AuthSockAddrV4, true, true);
|
||||
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 AcctSockAddrV4(
|
||||
Poco::Net::AddressFamily::IPv4,
|
||||
MicroServiceConfigGetInt("radius.proxy.accounting.port",
|
||||
DEFAULT_RADIUS_ACCOUNTING_PORT));
|
||||
AccountingSocketV4_ =
|
||||
std::make_unique<Poco::Net::DatagramSocket>(AcctSockAddrV4, true, true);
|
||||
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 CoASockAddrV4(
|
||||
Poco::Net::AddressFamily::IPv4,
|
||||
MicroServiceConfigGetInt("radius.proxy.coa.port", DEFAULT_RADIUS_CoA_PORT));
|
||||
CoASocketV4_ = std::make_unique<Poco::Net::DatagramSocket>(CoASockAddrV4, 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);
|
||||
|
||||
RadiusReactor_.reset();
|
||||
RadiusReactor_ = std::make_unique<Poco::Net::SocketReactor>();
|
||||
RadiusReactor_->addEventHandler(
|
||||
*AuthenticationSocketV4_,
|
||||
Poco::NObserver<RADIUS_proxy_server, Poco::Net::ReadableNotification>(
|
||||
*this, &RADIUS_proxy_server::OnAuthenticationSocketReadable));
|
||||
RadiusReactor_->addEventHandler(
|
||||
*AuthenticationSocketV6_,
|
||||
Poco::NObserver<RADIUS_proxy_server, Poco::Net::ReadableNotification>(
|
||||
*this, &RADIUS_proxy_server::OnAuthenticationSocketReadable));
|
||||
|
||||
RadiusReactor_->addEventHandler(
|
||||
*AccountingSocketV4_,
|
||||
Poco::NObserver<RADIUS_proxy_server, Poco::Net::ReadableNotification>(
|
||||
*this, &RADIUS_proxy_server::OnAccountingSocketReadable));
|
||||
RadiusReactor_->addEventHandler(
|
||||
*AccountingSocketV6_,
|
||||
Poco::NObserver<RADIUS_proxy_server, Poco::Net::ReadableNotification>(
|
||||
*this, &RADIUS_proxy_server::OnAccountingSocketReadable));
|
||||
|
||||
RadiusReactor_->addEventHandler(
|
||||
*CoASocketV4_, Poco::NObserver<RADIUS_proxy_server, Poco::Net::ReadableNotification>(
|
||||
*this, &RADIUS_proxy_server::OnCoASocketReadable));
|
||||
RadiusReactor_->addEventHandler(
|
||||
*CoASocketV6_, Poco::NObserver<RADIUS_proxy_server, Poco::Net::ReadableNotification>(
|
||||
*this, &RADIUS_proxy_server::OnCoASocketReadable));
|
||||
|
||||
ParseConfig();
|
||||
StartRADSECServers();
|
||||
RadiusReactorThread_.start(*RadiusReactor_);
|
||||
StartRADIUSDestinations();
|
||||
RadiusReactorThread_.start(RadiusReactor_);
|
||||
Utils::SetThreadName(RadiusReactorThread_, "rad:reactor");
|
||||
Running_ = true;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void RADIUS_proxy_server::Stop() {
|
||||
if (Enabled_ && Running_) {
|
||||
poco_information(Logger(), "Stopping...");
|
||||
RadiusReactor_->removeEventHandler(
|
||||
*AuthenticationSocketV4_,
|
||||
Poco::NObserver<RADIUS_proxy_server, Poco::Net::ReadableNotification>(
|
||||
*this, &RADIUS_proxy_server::OnAuthenticationSocketReadable));
|
||||
RadiusReactor_->removeEventHandler(
|
||||
*AuthenticationSocketV6_,
|
||||
Poco::NObserver<RADIUS_proxy_server, Poco::Net::ReadableNotification>(
|
||||
*this, &RADIUS_proxy_server::OnAuthenticationSocketReadable));
|
||||
|
||||
RadiusReactor_->removeEventHandler(
|
||||
*AccountingSocketV4_,
|
||||
Poco::NObserver<RADIUS_proxy_server, Poco::Net::ReadableNotification>(
|
||||
*this, &RADIUS_proxy_server::OnAccountingSocketReadable));
|
||||
RadiusReactor_->removeEventHandler(
|
||||
*AccountingSocketV6_,
|
||||
Poco::NObserver<RADIUS_proxy_server, Poco::Net::ReadableNotification>(
|
||||
*this, &RADIUS_proxy_server::OnAccountingSocketReadable));
|
||||
|
||||
RadiusReactor_->removeEventHandler(
|
||||
*CoASocketV4_,
|
||||
Poco::NObserver<RADIUS_proxy_server, Poco::Net::ReadableNotification>(
|
||||
*this, &RADIUS_proxy_server::OnCoASocketReadable));
|
||||
RadiusReactor_->removeEventHandler(
|
||||
*CoASocketV6_,
|
||||
Poco::NObserver<RADIUS_proxy_server, Poco::Net::ReadableNotification>(
|
||||
*this, &RADIUS_proxy_server::OnCoASocketReadable));
|
||||
|
||||
AuthenticationSocketV4_->close();
|
||||
AuthenticationSocketV6_->close();
|
||||
AccountingSocketV4_->close();
|
||||
AccountingSocketV6_->close();
|
||||
CoASocketV4_->close();
|
||||
CoASocketV6_->close();
|
||||
|
||||
AuthenticationSocketV4_.reset();
|
||||
AuthenticationSocketV6_.reset();
|
||||
AccountingSocketV4_.reset();
|
||||
AccountingSocketV6_.reset();
|
||||
CoASocketV4_.reset();
|
||||
CoASocketV6_.reset();
|
||||
|
||||
StopRADSECServers();
|
||||
RadiusReactor_->stop();
|
||||
StopRADIUSDestinations();
|
||||
RadiusReactor_.stop();
|
||||
RadiusReactorThread_.join();
|
||||
Running_ = false;
|
||||
poco_information(Logger(), "Stopped...");
|
||||
}
|
||||
}
|
||||
|
||||
void RADIUS_proxy_server::StartRADSECServers() {
|
||||
/* inline static bool isRadsec(const GWObjects::RadiusProxyPool &Cfg) {
|
||||
return Cfg.radsecPoolType=="orion" || Cfg.radsecPoolType=="globalreach" || Cfg.radsecPoolType=="radsec";
|
||||
}
|
||||
*/
|
||||
|
||||
void RADIUS_proxy_server::StartRADIUSDestinations() {
|
||||
std::lock_guard G(Mutex_);
|
||||
for (const auto &pool : PoolList_.pools) {
|
||||
for (const auto &entry : pool.authConfig.servers) {
|
||||
if (entry.radsec) {
|
||||
RADSECservers_[Poco::Net::SocketAddress(entry.ip, 0)] =
|
||||
std::make_unique<RADSEC_server>(*RadiusReactor_, entry);
|
||||
}
|
||||
if(pool.enabled) {
|
||||
RADIUS_Destinations_[Utils::IPtoInt(pool.poolProxyIp)] =
|
||||
std::make_unique<RADIUS_Destination>(RadiusReactor_, pool);
|
||||
} else {
|
||||
poco_information(Logger(),fmt::format("Pool {} is not enabled.", pool.name));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RADIUS_proxy_server::StopRADSECServers() {
|
||||
void RADIUS_proxy_server::StopRADIUSDestinations() {
|
||||
std::lock_guard G(Mutex_);
|
||||
RADSECservers_.clear();
|
||||
RADIUS_Destinations_.clear();
|
||||
}
|
||||
|
||||
void RADIUS_proxy_server::OnAccountingSocketReadable(
|
||||
const Poco::AutoPtr<Poco::Net::ReadableNotification> &pNf) {
|
||||
Poco::Net::SocketAddress Sender;
|
||||
RADIUS::RadiusPacket P;
|
||||
|
||||
auto ReceiveSize = pNf->socket().impl()->receiveBytes(P.Buffer(), P.BufferLen());
|
||||
if (ReceiveSize < SMALLEST_RADIUS_PACKET) {
|
||||
poco_warning(Logger(), "Accounting: bad packet received.");
|
||||
return;
|
||||
}
|
||||
P.Evaluate(ReceiveSize);
|
||||
// P.Log(std::cout);
|
||||
auto SerialNumber = P.ExtractSerialNumberFromProxyState();
|
||||
if (SerialNumber.empty()) {
|
||||
poco_warning(Logger(), "Accounting: missing serial number.");
|
||||
return;
|
||||
}
|
||||
auto CallingStationID = P.ExtractCallingStationID();
|
||||
auto CalledStationID = P.ExtractCalledStationID();
|
||||
|
||||
poco_debug(
|
||||
Logger(),
|
||||
fmt::format(
|
||||
"Accounting Packet received for {}, CalledStationID: {}, CallingStationID:{}",
|
||||
SerialNumber, CalledStationID, CallingStationID));
|
||||
AP_WS_Server()->SendRadiusAccountingData(SerialNumber, P.Buffer(), P.Size());
|
||||
}
|
||||
|
||||
void RADIUS_proxy_server::OnAuthenticationSocketReadable(
|
||||
const Poco::AutoPtr<Poco::Net::ReadableNotification> &pNf) {
|
||||
Poco::Net::SocketAddress Sender;
|
||||
RADIUS::RadiusPacket P;
|
||||
|
||||
auto ReceiveSize = pNf->socket().impl()->receiveBytes(P.Buffer(), P.BufferLen());
|
||||
if (ReceiveSize < SMALLEST_RADIUS_PACKET) {
|
||||
poco_warning(Logger(), "Authentication: bad packet received.");
|
||||
return;
|
||||
}
|
||||
P.Evaluate(ReceiveSize);
|
||||
// P.Log(std::cout);
|
||||
auto SerialNumber = P.ExtractSerialNumberFromProxyState();
|
||||
if (SerialNumber.empty()) {
|
||||
poco_warning(Logger(), "Authentication: missing serial number.");
|
||||
return;
|
||||
}
|
||||
auto CallingStationID = P.ExtractCallingStationID();
|
||||
auto CalledStationID = P.ExtractCalledStationID();
|
||||
|
||||
poco_debug(
|
||||
Logger(),
|
||||
fmt::format(
|
||||
"Authentication Packet received for {}, CalledStationID: {}, CallingStationID:{}",
|
||||
SerialNumber, CalledStationID, CallingStationID));
|
||||
AP_WS_Server()->SendRadiusAuthenticationData(SerialNumber, P.Buffer(), P.Size());
|
||||
}
|
||||
|
||||
void RADIUS_proxy_server::OnCoASocketReadable(
|
||||
const Poco::AutoPtr<Poco::Net::ReadableNotification> &pNf) {
|
||||
Poco::Net::SocketAddress Sender;
|
||||
RADIUS::RadiusPacket P;
|
||||
|
||||
auto ReceiveSize = pNf.get()->socket().impl()->receiveBytes(P.Buffer(), P.BufferLen());
|
||||
if (ReceiveSize < SMALLEST_RADIUS_PACKET) {
|
||||
poco_warning(Logger(), "CoA/DM: bad packet received.");
|
||||
return;
|
||||
}
|
||||
// P.Log(std::cout);
|
||||
|
||||
P.Evaluate(ReceiveSize);
|
||||
auto SerialNumber = P.ExtractSerialNumberTIP();
|
||||
if (SerialNumber.empty()) {
|
||||
poco_warning(Logger(), "CoA/DM: missing serial number.");
|
||||
return;
|
||||
}
|
||||
auto CallingStationID = P.ExtractCallingStationID();
|
||||
auto CalledStationID = P.ExtractCalledStationID();
|
||||
|
||||
poco_debug(
|
||||
Logger(),
|
||||
fmt::format("CoA Packet received for {}, CalledStationID: {}, CallingStationID:{}",
|
||||
SerialNumber, CalledStationID, CallingStationID));
|
||||
AP_WS_Server()->SendRadiusCoAData(SerialNumber, P.Buffer(), P.Size());
|
||||
}
|
||||
|
||||
void RADIUS_proxy_server::RouteAndSendAccountingPacket(const std::string &Destination, const std::string &serialNumber, RADIUS::RadiusPacket &P, bool RecomputeAuthenticator, std::string & secret) {
|
||||
void RADIUS_proxy_server::RouteAndSendAccountingPacket(const std::string &Destination,const std::string &serialNumber, RADIUS::RadiusPacket &P, bool RecomputeAuthenticator, std::string &Secret) {
|
||||
try{
|
||||
auto CallingStationID = P.ExtractCallingStationID();
|
||||
auto CalledStationID = P.ExtractCalledStationID();
|
||||
Poco::Net::SocketAddress Dst(Destination);
|
||||
|
||||
// are we sending this to a pool?
|
||||
auto DstParts = Utils::Split(Destination, ':');
|
||||
std::uint32_t DtsIp = Utils::IPtoInt(DstParts[0]);
|
||||
|
||||
std::lock_guard G(Mutex_);
|
||||
bool UseRADSEC = false;
|
||||
auto FinalDestination = Route(radius_type::acct, Dst, P, UseRADSEC, secret);
|
||||
if (UseRADSEC) {
|
||||
Poco::Net::SocketAddress RSP(FinalDestination.host(), 0);
|
||||
auto DestinationServer = RADSECservers_.find(RSP);
|
||||
if (DestinationServer != end(RADSECservers_)) {
|
||||
|
||||
auto DestinationServer = RADIUS_Destinations_.find(DtsIp);
|
||||
if (DestinationServer != end(RADIUS_Destinations_)) {
|
||||
if(Logger().trace()) {
|
||||
auto CallingStationID = P.ExtractCallingStationID();
|
||||
auto CalledStationID = P.ExtractCalledStationID();
|
||||
auto SessionID = P.ExtractAccountingSessionID();
|
||||
auto MultiSessionID = P.ExtractAccountingMultiSessionID();
|
||||
Logger().trace(
|
||||
fmt::format("{}: Sending Accounting {} bytes to {}. CalledStationID={} CallingStationID={} SessionID={}:{}",
|
||||
serialNumber, P.Size(),
|
||||
DestinationServer->second->Pool().authConfig.servers[0].ip,
|
||||
CalledStationID, CallingStationID, SessionID, MultiSessionID));
|
||||
}
|
||||
if(DestinationServer->second->ServerType()!=GWObjects::RadiusEndpointType::generic) {
|
||||
Secret = DestinationServer->second->Pool().acctConfig.servers[0].secret;
|
||||
if(RecomputeAuthenticator) {
|
||||
P.RecomputeAuthenticator("radsec");
|
||||
P.RecomputeAuthenticator(Secret);
|
||||
}
|
||||
DestinationServer->second->SendData(serialNumber, P.Buffer(), P.Size());
|
||||
DestinationServer->second->SendData(serialNumber, (const unsigned char *)P.Buffer(),
|
||||
P.Size());
|
||||
} else {
|
||||
DestinationServer->second->SendRadiusDataAcctData(
|
||||
serialNumber, (const unsigned char *)P.Buffer(), P.Size());
|
||||
}
|
||||
} else {
|
||||
if ((Dst.family() == Poco::Net::SocketAddress::IPv4 &&
|
||||
AccountingSocketV4_ == nullptr) ||
|
||||
(Dst.family() == Poco::Net::SocketAddress::IPv6 &&
|
||||
AccountingSocketV6_ == nullptr)) {
|
||||
poco_debug(
|
||||
Logger(),
|
||||
fmt::format(
|
||||
"ACCT: Trying to use RADIUS GW PROXY but not configured. Device={}",
|
||||
serialNumber));
|
||||
return;
|
||||
}
|
||||
|
||||
if(RecomputeAuthenticator) {
|
||||
P.RecomputeAuthenticator(secret);
|
||||
}
|
||||
|
||||
auto AllSent =
|
||||
SendData(Dst.family() == Poco::Net::SocketAddress::IPv4 ? *AccountingSocketV4_
|
||||
: *AccountingSocketV6_
|
||||
, P.Buffer(), P.Size(), FinalDestination);
|
||||
if (!AllSent)
|
||||
poco_error(Logger(),
|
||||
fmt::format("{}: Could not send Accounting packet packet to {}.",
|
||||
serialNumber, Destination));
|
||||
else
|
||||
poco_debug(Logger(), fmt::format("{}: Sending Accounting Packet to {}, "
|
||||
"CalledStationID: {}, CallingStationID:{}",
|
||||
serialNumber, FinalDestination.toString(),
|
||||
CalledStationID, CallingStationID));
|
||||
}
|
||||
} catch (const Poco::Exception &E) {
|
||||
Logger().log(E);
|
||||
@@ -326,22 +129,18 @@ namespace OpenWifi {
|
||||
ofs.close();
|
||||
}
|
||||
|
||||
void RADIUS_proxy_server::SendAccountingData(const std::string &serialNumber,
|
||||
const char *buffer, std::size_t size, std::string & secret) {
|
||||
void RADIUS_proxy_server::SendAccountingData( const std::string &serialNumber,
|
||||
const char *buffer, std::size_t size) {
|
||||
|
||||
if (!Continue())
|
||||
return;
|
||||
|
||||
try {
|
||||
RADIUS::RadiusPacket P((unsigned char *)buffer, size);
|
||||
|
||||
// P.Log(std::cout);
|
||||
|
||||
auto Destination = P.ExtractProxyStateDestination();
|
||||
// store_packet(serialNumber, buffer, size);
|
||||
RouteAndSendAccountingPacket(Destination, serialNumber, P, false, secret);
|
||||
RADIUSSessionTracker()->AddAccountingSession(Destination, serialNumber, P, secret);
|
||||
|
||||
std::string Secret;
|
||||
RouteAndSendAccountingPacket(Destination, serialNumber, P, false, Secret);
|
||||
RADIUSSessionTracker()->AddAccountingSession(Destination, serialNumber, P, Secret);
|
||||
} catch (const Poco::Exception &E) {
|
||||
Logger().log(E);
|
||||
} catch (...) {
|
||||
@@ -356,58 +155,38 @@ namespace OpenWifi {
|
||||
}
|
||||
|
||||
void RADIUS_proxy_server::SendAuthenticationData(const std::string &serialNumber,
|
||||
const char *buffer, std::size_t size, std::string & secret) {
|
||||
const char *buffer, std::size_t size) {
|
||||
|
||||
if (!Continue())
|
||||
return;
|
||||
|
||||
try {
|
||||
RADIUS::RadiusPacket P((unsigned char *)buffer, size);
|
||||
auto Destination = P.ExtractProxyStateDestination();
|
||||
auto CallingStationID = P.ExtractCallingStationID();
|
||||
auto CalledStationID = P.ExtractCalledStationID();
|
||||
Poco::Net::SocketAddress Dst(Destination);
|
||||
|
||||
// P.Log(std::cout);
|
||||
|
||||
std::lock_guard G(Mutex_);
|
||||
bool UseRADSEC = false;
|
||||
auto FinalDestination = Route(radius_type::auth, Dst, P, UseRADSEC, secret);
|
||||
RADIUSSessionTracker()->AddAuthenticationSession(Destination, serialNumber, P, secret);
|
||||
|
||||
// std::cout << "Authentication secret: " << secret << std::endl;
|
||||
if (UseRADSEC) {
|
||||
Poco::Net::SocketAddress RSP(FinalDestination.host(), 0);
|
||||
auto DestinationServer = RADSECservers_.find(RSP);
|
||||
if (DestinationServer != end(RADSECservers_)) {
|
||||
DestinationServer->second->SendData(serialNumber, (const unsigned char *)buffer,
|
||||
size);
|
||||
std::uint32_t DstIp = P.ExtractProxyStateDestinationIPint();
|
||||
auto DestinationServer = RADIUS_Destinations_.find(DstIp);
|
||||
if (DestinationServer != end(RADIUS_Destinations_)) {
|
||||
if(Logger().trace()) {
|
||||
auto CallingStationID = P.ExtractCallingStationID();
|
||||
auto CalledStationID = P.ExtractCalledStationID();
|
||||
auto SessionID = P.ExtractAccountingSessionID();
|
||||
auto MultiSessionID = P.ExtractAccountingMultiSessionID();
|
||||
Logger().trace(
|
||||
fmt::format("{}: Sending Authentication {} bytes to {}. CalledStationID={} CallingStationID={} SessionID={}:{}",
|
||||
serialNumber, P.Size(),
|
||||
DestinationServer->second->Pool().authConfig.servers[0].ip,
|
||||
CalledStationID, CallingStationID, SessionID, MultiSessionID));
|
||||
}
|
||||
} else {
|
||||
if ((Dst.family() == Poco::Net::SocketAddress::IPv4 &&
|
||||
AuthenticationSocketV4_ == nullptr) ||
|
||||
(Dst.family() == Poco::Net::SocketAddress::IPv6 &&
|
||||
AuthenticationSocketV6_ == nullptr)) {
|
||||
poco_debug(
|
||||
Logger(),
|
||||
fmt::format(
|
||||
"AUTH: Trying to use RADIUS GW PROXY but not configured. Device={}",
|
||||
serialNumber));
|
||||
return;
|
||||
if(DestinationServer->second->ServerType()!=GWObjects::RadiusEndpointType::generic) {
|
||||
DestinationServer->second->SendData(serialNumber,
|
||||
(const unsigned char *)buffer, size);
|
||||
}
|
||||
else {
|
||||
DestinationServer->second->SendRadiusDataAuthData(
|
||||
serialNumber, (const unsigned char *)buffer, size);
|
||||
}
|
||||
auto AllSent = SendData(Dst.family() == Poco::Net::SocketAddress::IPv4
|
||||
? *AuthenticationSocketV4_
|
||||
: *AuthenticationSocketV6_,
|
||||
(const unsigned char *)buffer, size, FinalDestination);
|
||||
if (!AllSent)
|
||||
poco_error(Logger(),
|
||||
fmt::format("{}: Could not send Authentication packet packet to {}.",
|
||||
serialNumber, Destination));
|
||||
else
|
||||
poco_debug(Logger(), fmt::format("{}: Sending Authentication Packet to {}, "
|
||||
"CalledStationID: {}, CallingStationID:{}",
|
||||
serialNumber, FinalDestination.toString(),
|
||||
CalledStationID, CallingStationID));
|
||||
}
|
||||
} catch (const Poco::Exception &E) {
|
||||
Logger().log(E);
|
||||
@@ -418,64 +197,42 @@ namespace OpenWifi {
|
||||
}
|
||||
|
||||
void RADIUS_proxy_server::SendCoAData(const std::string &serialNumber, const char *buffer,
|
||||
std::size_t size, std::string & secret) {
|
||||
std::size_t size) {
|
||||
|
||||
if (!Continue())
|
||||
return;
|
||||
|
||||
try {
|
||||
RADIUS::RadiusPacket P((unsigned char *)buffer, size);
|
||||
auto Destination = P.ExtractProxyStateDestination();
|
||||
|
||||
if (Destination.empty()) {
|
||||
Destination = "0.0.0.0:0";
|
||||
}
|
||||
|
||||
P.Log(std::cout);
|
||||
|
||||
auto CallingStationID = P.ExtractCallingStationID();
|
||||
auto CalledStationID = P.ExtractCalledStationID();
|
||||
Poco::Net::SocketAddress Dst(Destination);
|
||||
|
||||
std::lock_guard G(Mutex_);
|
||||
bool UseRADSEC = false;
|
||||
auto FinalDestination = Route(radius_type::coa, Dst, P, UseRADSEC, secret);
|
||||
std::cout << "CoA secret: " << secret << std::endl;
|
||||
if (UseRADSEC) {
|
||||
Poco::Net::SocketAddress RSP(FinalDestination.host(), 0);
|
||||
auto DestinationServer = RADSECservers_.find(RSP);
|
||||
if (DestinationServer != end(RADSECservers_)) {
|
||||
std::uint32_t DstIp = P.ExtractProxyStateDestinationIPint();
|
||||
auto DestinationServer = RADIUS_Destinations_.find(DstIp);
|
||||
if (DestinationServer != end(RADIUS_Destinations_)) {
|
||||
poco_trace(Logger(),fmt::format("{}: Sending CoA {} bytes to {}", serialNumber, P.Size(), DestinationServer->second->Pool().coaConfig.servers[0].ip));
|
||||
if(DestinationServer->second->ServerType()!=GWObjects::RadiusEndpointType::generic) {
|
||||
DestinationServer->second->SendData(serialNumber, (const unsigned char *)buffer,
|
||||
size);
|
||||
} else {
|
||||
DestinationServer->second->SendRadiusDataCoAData(
|
||||
serialNumber, (const unsigned char *)buffer, size);
|
||||
}
|
||||
} else {
|
||||
if ((Dst.family() == Poco::Net::SocketAddress::IPv4 && CoASocketV4_ == nullptr) ||
|
||||
(Dst.family() == Poco::Net::SocketAddress::IPv6 && CoASocketV6_ == nullptr)) {
|
||||
poco_debug(
|
||||
Logger(),
|
||||
fmt::format(
|
||||
"CoA: Trying to use RADIUS GW PROXY but not configured. Device={}",
|
||||
serialNumber));
|
||||
return;
|
||||
}
|
||||
auto AllSent = SendData(
|
||||
Dst.family() == Poco::Net::SocketAddress::IPv4 ? *CoASocketV4_ : *CoASocketV6_,
|
||||
(const unsigned char *)buffer, size, FinalDestination);
|
||||
if (!AllSent)
|
||||
poco_error(Logger(), fmt::format("{}: Could not send CoA packet packet to {}.",
|
||||
serialNumber, Destination));
|
||||
else
|
||||
poco_debug(Logger(), fmt::format("{}: Sending CoA Packet to {}", serialNumber,
|
||||
FinalDestination.toString()));
|
||||
}
|
||||
} catch (const Poco::Exception &E) {
|
||||
Logger().log(E);
|
||||
} catch (...) {
|
||||
poco_warning(Logger(),
|
||||
fmt::format("Bad RADIUS CoA/DM Packet from {}. Dropped.", serialNumber));
|
||||
fmt::format("Bad RADIUS AUTH Packet from {}. Dropped.", serialNumber));
|
||||
}
|
||||
}
|
||||
|
||||
void RADIUS_proxy_server::ParseServerList(const GWObjects::RadiusProxyServerConfig &Config,
|
||||
std::vector<Destination> &V4,
|
||||
std::vector<Destination> &V6, bool setAsDefault) {
|
||||
std::vector<Destination> &V6, bool setAsDefault,
|
||||
const std::string &poolProxyIp) {
|
||||
uint64_t TotalV4 = 0, TotalV6 = 0;
|
||||
|
||||
for (const auto &server : Config.servers) {
|
||||
@@ -499,7 +256,8 @@ namespace OpenWifi {
|
||||
.useAsDefault = setAsDefault,
|
||||
.useRADSEC = server.radsec,
|
||||
.realms = server.radsecRealms,
|
||||
.secret = server.secret };
|
||||
.secret = server.secret,
|
||||
.poolProxyIp = poolProxyIp};
|
||||
|
||||
if (setAsDefault && D.useRADSEC)
|
||||
DefaultIsRADSEC_ = true;
|
||||
@@ -548,11 +306,11 @@ namespace OpenWifi {
|
||||
for (const auto &pool : RPC.pools) {
|
||||
RadiusPool NewPool;
|
||||
ParseServerList(pool.authConfig, NewPool.AuthV4, NewPool.AuthV6,
|
||||
pool.useByDefault);
|
||||
pool.useByDefault, pool.poolProxyIp);
|
||||
ParseServerList(pool.acctConfig, NewPool.AcctV4, NewPool.AcctV6,
|
||||
pool.useByDefault);
|
||||
pool.useByDefault, pool.poolProxyIp);
|
||||
ParseServerList(pool.coaConfig, NewPool.CoaV4, NewPool.CoaV6,
|
||||
pool.useByDefault);
|
||||
pool.useByDefault, pool.poolProxyIp);
|
||||
Pools_.push_back(NewPool);
|
||||
}
|
||||
} else {
|
||||
@@ -571,6 +329,7 @@ namespace OpenWifi {
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
static bool RealmMatch(const std::string &user_realm, const std::string &realm) {
|
||||
if (realm.find_first_of('*') == std::string::npos)
|
||||
return user_realm == realm;
|
||||
@@ -582,6 +341,7 @@ namespace OpenWifi {
|
||||
const Poco::Net::SocketAddress &RequestedAddress,
|
||||
const RADIUS::RadiusPacket &P, bool &UseRADSEC,
|
||||
std::string &Secret) {
|
||||
|
||||
bool IsV4 = RequestedAddress.family() == Poco::Net::SocketAddress::IPv4;
|
||||
|
||||
// find the realm...
|
||||
@@ -596,7 +356,6 @@ namespace OpenWifi {
|
||||
if (!server.realms.empty()) {
|
||||
for (const auto &realm : server.realms) {
|
||||
if (RealmMatch(UserRealm, realm)) {
|
||||
// std::cout << "Realm match..." << std::endl;
|
||||
UseRADSEC = true;
|
||||
return server.Addr;
|
||||
}
|
||||
@@ -618,17 +377,17 @@ namespace OpenWifi {
|
||||
: Pools_[DefaultPoolIndex_].AuthV6,
|
||||
RequestedAddress, Secret);
|
||||
}
|
||||
case radius_type::coa: {
|
||||
return ChooseAddress(IsV4 ? Pools_[DefaultPoolIndex_].CoaV4
|
||||
: Pools_[DefaultPoolIndex_].CoaV6,
|
||||
RequestedAddress, Secret);
|
||||
}
|
||||
case radius_type::acct:
|
||||
default: {
|
||||
return ChooseAddress(IsV4 ? Pools_[DefaultPoolIndex_].AcctV4
|
||||
: Pools_[DefaultPoolIndex_].AcctV6,
|
||||
RequestedAddress, Secret);
|
||||
}
|
||||
case radius_type::coa: {
|
||||
return ChooseAddress(IsV4 ? Pools_[DefaultPoolIndex_].CoaV4
|
||||
: Pools_[DefaultPoolIndex_].CoaV6,
|
||||
RequestedAddress, Secret);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -637,7 +396,6 @@ namespace OpenWifi {
|
||||
const Poco::Net::SocketAddress &RequestedAddress,
|
||||
const RADIUS::RadiusPacket &P, bool &UseRADSEC,
|
||||
std::string &Secret) {
|
||||
std::lock_guard G(Mutex_);
|
||||
|
||||
if (Pools_.empty()) {
|
||||
UseRADSEC = false;
|
||||
@@ -646,6 +404,7 @@ namespace OpenWifi {
|
||||
|
||||
bool IsV4 = RequestedAddress.family() == Poco::Net::SocketAddress::IPv4;
|
||||
bool useDefault;
|
||||
|
||||
useDefault = IsV4 ? RequestedAddress.host() ==
|
||||
Poco::Net::IPAddress::wildcard(Poco::Net::IPAddress::IPv4)
|
||||
: RequestedAddress.host() ==
|
||||
@@ -656,29 +415,36 @@ namespace OpenWifi {
|
||||
}
|
||||
|
||||
auto isAddressInPool = [&](const std::vector<Destination> &D, bool &UseRADSEC) -> bool {
|
||||
for (const auto &entry : D)
|
||||
for (const auto &entry : D) {
|
||||
if (!entry.poolProxyIp.empty() &&
|
||||
entry.poolProxyIp == RequestedAddress.host().toString()) {
|
||||
UseRADSEC = entry.useRADSEC;
|
||||
return true;
|
||||
}
|
||||
if (entry.Addr.host() == RequestedAddress.host()) {
|
||||
UseRADSEC = entry.useRADSEC;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
for (auto &i : Pools_) {
|
||||
for (auto &pool : Pools_) {
|
||||
// try and match the pool's address to the destination
|
||||
switch (rtype) {
|
||||
case radius_type::coa: {
|
||||
if (isAddressInPool((IsV4 ? i.CoaV4 : i.CoaV6), UseRADSEC)) {
|
||||
return ChooseAddress(IsV4 ? i.CoaV4 : i.CoaV6, RequestedAddress, Secret);
|
||||
if (isAddressInPool((IsV4 ? pool.CoaV4 : pool.CoaV6), UseRADSEC)) {
|
||||
return ChooseAddress(IsV4 ? pool.CoaV4 : pool.CoaV6, RequestedAddress, Secret);
|
||||
}
|
||||
} break;
|
||||
case radius_type::auth: {
|
||||
if (isAddressInPool((IsV4 ? i.AuthV4 : i.AuthV6), UseRADSEC)) {
|
||||
return ChooseAddress(IsV4 ? i.AuthV4 : i.AuthV6, RequestedAddress, Secret);
|
||||
if (isAddressInPool((IsV4 ? pool.AuthV4 : pool.AuthV6), UseRADSEC)) {
|
||||
return ChooseAddress(IsV4 ? pool.AuthV4 : pool.AuthV6, RequestedAddress, Secret);
|
||||
}
|
||||
} break;
|
||||
case radius_type::acct: {
|
||||
if (isAddressInPool((IsV4 ? i.AcctV4 : i.AcctV6), UseRADSEC)) {
|
||||
return ChooseAddress(IsV4 ? i.AcctV4 : i.AcctV6, RequestedAddress, Secret);
|
||||
if (isAddressInPool((IsV4 ? pool.AcctV4 : pool.AcctV6), UseRADSEC)) {
|
||||
return ChooseAddress(IsV4 ? pool.AcctV4 : pool.AcctV6, RequestedAddress, Secret);
|
||||
}
|
||||
} break;
|
||||
}
|
||||
@@ -695,7 +461,8 @@ namespace OpenWifi {
|
||||
|
||||
if (Pool.size() == 1) {
|
||||
Secret = Pool[0].secret;
|
||||
return Pool[0].Addr;
|
||||
auto A = Pool[0].Addr;
|
||||
return A;
|
||||
}
|
||||
|
||||
if (Pool[0].strategy == "weighted") {
|
||||
@@ -741,7 +508,7 @@ namespace OpenWifi {
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
return OriginalAddress;
|
||||
// return OriginalAddress;
|
||||
}
|
||||
|
||||
Pool[index].state += 1;
|
||||
@@ -757,7 +524,7 @@ namespace OpenWifi {
|
||||
}
|
||||
return OriginalAddress;
|
||||
}
|
||||
|
||||
*/
|
||||
void RADIUS_proxy_server::SetConfig(const GWObjects::RadiusProxyPoolList &C) {
|
||||
std::lock_guard G(Mutex_);
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
|
||||
#include "framework/SubSystemServer.h"
|
||||
|
||||
#include "RADSEC_server.h"
|
||||
#include "RADIUS_Destination.h"
|
||||
|
||||
namespace OpenWifi {
|
||||
|
||||
@@ -28,25 +28,19 @@ namespace OpenWifi {
|
||||
void Stop() final;
|
||||
inline bool Enabled() const { return Enabled_; }
|
||||
|
||||
void OnAccountingSocketReadable(const Poco::AutoPtr<Poco::Net::ReadableNotification> &pNf);
|
||||
void
|
||||
OnAuthenticationSocketReadable(const Poco::AutoPtr<Poco::Net::ReadableNotification> &pNf);
|
||||
void OnCoASocketReadable(const Poco::AutoPtr<Poco::Net::ReadableNotification> &pNf);
|
||||
|
||||
void SendAccountingData(const std::string &serialNumber, const char *buffer,
|
||||
std::size_t size, std::string & secret);
|
||||
void SendAccountingData(const std::string &serialNumber, const char *buffer, std::size_t size);
|
||||
void SendAuthenticationData(const std::string &serialNumber, const char *buffer,
|
||||
std::size_t size, std::string & secret);
|
||||
void SendCoAData(const std::string &serialNumber, const char *buffer, std::size_t size, std::string & secret);
|
||||
std::size_t size);
|
||||
void SendCoAData(const std::string &serialNumber, const char *buffer, std::size_t size);
|
||||
|
||||
void RouteAndSendAccountingPacket(const std::string &Destination, const std::string &serialNumber, RADIUS::RadiusPacket &P, bool reComputeAuthenticator, std::string & secret);
|
||||
void RouteAndSendAccountingPacket(const std::string &Destination, const std::string &serialNumber, RADIUS::RadiusPacket &P, bool reComputeAuthenticator, std::string &Secret);
|
||||
|
||||
void SetConfig(const GWObjects::RadiusProxyPoolList &C);
|
||||
void DeleteConfig();
|
||||
void GetConfig(GWObjects::RadiusProxyPoolList &C);
|
||||
|
||||
void StartRADSECServers();
|
||||
void StopRADSECServers();
|
||||
void StartRADIUSDestinations();
|
||||
void StopRADIUSDestinations();
|
||||
|
||||
struct Destination {
|
||||
Poco::Net::SocketAddress Addr;
|
||||
@@ -62,24 +56,19 @@ namespace OpenWifi {
|
||||
bool useRADSEC = false;
|
||||
std::vector<std::string> realms;
|
||||
std::string secret;
|
||||
std::string poolProxyIp;
|
||||
};
|
||||
|
||||
inline bool Continue() const { return Running_ && Enabled_ && !Pools_.empty(); }
|
||||
|
||||
private:
|
||||
std::unique_ptr<Poco::Net::DatagramSocket> AccountingSocketV4_;
|
||||
std::unique_ptr<Poco::Net::DatagramSocket> AccountingSocketV6_;
|
||||
std::unique_ptr<Poco::Net::DatagramSocket> AuthenticationSocketV4_;
|
||||
std::unique_ptr<Poco::Net::DatagramSocket> AuthenticationSocketV6_;
|
||||
std::unique_ptr<Poco::Net::DatagramSocket> CoASocketV4_;
|
||||
std::unique_ptr<Poco::Net::DatagramSocket> CoASocketV6_;
|
||||
std::unique_ptr<Poco::Net::SocketReactor> RadiusReactor_;
|
||||
Poco::Thread RadiusReactorThread_;
|
||||
Poco::Net::SocketReactor RadiusReactor_;
|
||||
Poco::Thread RadiusReactorThread_;
|
||||
|
||||
GWObjects::RadiusProxyPoolList PoolList_;
|
||||
std::string ConfigFilename_;
|
||||
|
||||
std::map<Poco::Net::SocketAddress, std::unique_ptr<RADSEC_server>> RADSECservers_;
|
||||
std::map<std::uint32_t, std::unique_ptr<RADIUS_Destination>> RADIUS_Destinations_;
|
||||
|
||||
struct RadiusPool {
|
||||
std::vector<Destination> AuthV4;
|
||||
@@ -104,19 +93,21 @@ namespace OpenWifi {
|
||||
|
||||
void ParseConfig();
|
||||
void ResetConfig();
|
||||
Poco::Net::SocketAddress Route(radius_type rtype, const Poco::Net::SocketAddress &A,
|
||||
const RADIUS::RadiusPacket &P, bool &UseRADSEC, std::string &secret);
|
||||
// Poco::Net::SocketAddress Route(radius_type rtype, const Poco::Net::SocketAddress &A,
|
||||
// const RADIUS::RadiusPacket &P, bool &UseRADSEC, std::string &secret);
|
||||
|
||||
void ParseServerList(const GWObjects::RadiusProxyServerConfig &Config,
|
||||
std::vector<Destination> &V4, std::vector<Destination> &V6,
|
||||
bool setAsDefault);
|
||||
static Poco::Net::SocketAddress
|
||||
std::vector<Destination> &V4,
|
||||
std::vector<Destination> &V6, bool setAsDefault,
|
||||
const std::string &poolProxyIp);
|
||||
/* static Poco::Net::SocketAddress
|
||||
ChooseAddress(std::vector<Destination> &Pool,
|
||||
const Poco::Net::SocketAddress &OriginalAddress, std::string &Secret);
|
||||
Poco::Net::SocketAddress DefaultRoute([[maybe_unused]] radius_type rtype,
|
||||
const Poco::Net::SocketAddress &RequestedAddress,
|
||||
const RADIUS::RadiusPacket &P, bool &UseRADSEC,
|
||||
std::string &Secret);
|
||||
};
|
||||
*/ };
|
||||
|
||||
inline auto RADIUS_proxy_server() { return RADIUS_proxy_server::instance(); }
|
||||
|
||||
|
||||
@@ -1,304 +0,0 @@
|
||||
//
|
||||
// Created by stephane bourque on 2022-08-15.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
|
||||
#include "RESTObjects/RESTAPI_GWobjects.h"
|
||||
|
||||
#include "Poco/Crypto/X509Certificate.h"
|
||||
#include "Poco/Net/Context.h"
|
||||
#include "Poco/Net/NetException.h"
|
||||
#include "Poco/Net/SecureStreamSocket.h"
|
||||
#include "Poco/Net/SocketReactor.h"
|
||||
#include "Poco/TemporaryFile.h"
|
||||
|
||||
#include "framework/MicroServiceFuncs.h"
|
||||
|
||||
#include "fmt/format.h"
|
||||
|
||||
#include "AP_WS_Server.h"
|
||||
#include "RADIUS_helpers.h"
|
||||
|
||||
namespace OpenWifi {
|
||||
|
||||
class RADSEC_server : public Poco::Runnable {
|
||||
public:
|
||||
RADSEC_server(Poco::Net::SocketReactor &R, GWObjects::RadiusProxyServerEntry E)
|
||||
: Reactor_(R), Server_(std::move(E)),
|
||||
Logger_(Poco::Logger::get(
|
||||
fmt::format("RADSEC: {}@{}:{}", Server_.name, Server_.ip, Server_.port))) {
|
||||
Start();
|
||||
}
|
||||
|
||||
~RADSEC_server() { Stop(); }
|
||||
|
||||
inline int Start() {
|
||||
ReconnectThread_.start(*this);
|
||||
return 0;
|
||||
}
|
||||
|
||||
inline void Stop() {
|
||||
TryAgain_ = false;
|
||||
Disconnect();
|
||||
ReconnectThread_.wakeUp();
|
||||
ReconnectThread_.join();
|
||||
}
|
||||
|
||||
inline void run() final {
|
||||
Poco::Thread::trySleep(3000);
|
||||
std::uint64_t LastStatus = 0;
|
||||
auto RadSecKeepAlive = MicroServiceConfigGetInt("radsec.keepalive", 120);
|
||||
while (TryAgain_) {
|
||||
if (!Connected_) {
|
||||
std::lock_guard G(LocalMutex_);
|
||||
LastStatus = Utils::Now();
|
||||
Connect();
|
||||
} else if ((Utils::Now() - LastStatus) > RadSecKeepAlive) {
|
||||
RADIUS::RadiusOutputPacket P(Server_.radsecSecret);
|
||||
P.MakeStatusMessage();
|
||||
poco_information(Logger_, "Keep-Alive message.");
|
||||
Socket_->sendBytes(P.Data(), P.Len());
|
||||
LastStatus = Utils::Now();
|
||||
}
|
||||
Poco::Thread::trySleep(!Connected_ ? 3000 : 10000);
|
||||
}
|
||||
}
|
||||
|
||||
inline bool SendData(const std::string &serial_number, const unsigned char *buffer,
|
||||
int length) {
|
||||
try {
|
||||
if (Connected_) {
|
||||
RADIUS::RadiusPacket P(buffer, length);
|
||||
int sent_bytes;
|
||||
if (P.VerifyMessageAuthenticator(Server_.radsecSecret)) {
|
||||
poco_debug(Logger_, fmt::format("{}: {} Sending {} bytes", serial_number,
|
||||
P.PacketType(), length));
|
||||
sent_bytes = Socket_->sendBytes(buffer, length);
|
||||
} else {
|
||||
poco_debug(Logger_, fmt::format("{}: {} Sending {} bytes", serial_number,
|
||||
P.PacketType(), length));
|
||||
P.ComputeMessageAuthenticator(Server_.radsecSecret);
|
||||
sent_bytes = Socket_->sendBytes(P.Buffer(), length);
|
||||
}
|
||||
return (sent_bytes == length);
|
||||
}
|
||||
} catch (const Poco::Exception &E) {
|
||||
Logger_.log(E);
|
||||
} catch (...) {
|
||||
poco_warning(Logger_, "Exception occurred: while sending data.");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
inline void
|
||||
onData([[maybe_unused]] const Poco::AutoPtr<Poco::Net::ReadableNotification> &pNf) {
|
||||
unsigned char Buffer[4096];
|
||||
|
||||
try {
|
||||
auto NumberOfReceivedBytes = Socket_->receiveBytes(Buffer, sizeof(Buffer));
|
||||
if (NumberOfReceivedBytes >= 20) {
|
||||
RADIUS::RadiusPacket P(Buffer, NumberOfReceivedBytes);
|
||||
if (P.IsAuthentication()) {
|
||||
auto SerialNumber = P.ExtractSerialNumberFromProxyState();
|
||||
if (!SerialNumber.empty()) {
|
||||
poco_debug(Logger_,
|
||||
fmt::format("{}: {} Received {} bytes.", SerialNumber,
|
||||
P.PacketType(), NumberOfReceivedBytes));
|
||||
AP_WS_Server()->SendRadiusAuthenticationData(SerialNumber, Buffer,
|
||||
NumberOfReceivedBytes);
|
||||
} else {
|
||||
poco_debug(Logger_, "AUTH packet dropped.");
|
||||
}
|
||||
} else if (P.IsAccounting()) {
|
||||
auto SerialNumber = P.ExtractSerialNumberFromProxyState();
|
||||
if (!SerialNumber.empty()) {
|
||||
poco_debug(Logger_,
|
||||
fmt::format("{}: {} Received {} bytes.", SerialNumber,
|
||||
P.PacketType(), NumberOfReceivedBytes));
|
||||
AP_WS_Server()->SendRadiusAccountingData(SerialNumber, Buffer,
|
||||
NumberOfReceivedBytes);
|
||||
} else {
|
||||
poco_debug(Logger_, "ACCT packet dropped.");
|
||||
}
|
||||
} else if (P.IsAuthority()) {
|
||||
auto SerialNumber = P.ExtractSerialNumberTIP();
|
||||
if (!SerialNumber.empty()) {
|
||||
poco_debug(Logger_,
|
||||
fmt::format("{}: {} Received {} bytes.", SerialNumber,
|
||||
P.PacketType(), NumberOfReceivedBytes));
|
||||
AP_WS_Server()->SendRadiusCoAData(SerialNumber, Buffer,
|
||||
NumberOfReceivedBytes);
|
||||
} else {
|
||||
poco_debug(Logger_, "CoA/DM packet dropped.");
|
||||
}
|
||||
} else {
|
||||
poco_warning(Logger_,
|
||||
fmt::format("Unknown packet: Type: {} (type={}) Length={}",
|
||||
P.PacketType(), P.PacketTypeInt(), P.BufferLen()));
|
||||
}
|
||||
} 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.");
|
||||
}
|
||||
}
|
||||
|
||||
inline void
|
||||
onError([[maybe_unused]] const Poco::AutoPtr<Poco::Net::ErrorNotification> &pNf) {
|
||||
poco_warning(Logger_, "Socker error. Terminating connection.");
|
||||
Disconnect();
|
||||
}
|
||||
|
||||
inline void
|
||||
onShutdown([[maybe_unused]] const Poco::AutoPtr<Poco::Net::ShutdownNotification> &pNf) {
|
||||
poco_warning(Logger_, "Socker socket shutdown. Terminating connection.");
|
||||
Disconnect();
|
||||
}
|
||||
|
||||
inline bool Connect() {
|
||||
if (TryAgain_) {
|
||||
std::lock_guard G(LocalMutex_);
|
||||
|
||||
Poco::TemporaryFile CertFile_(MicroServiceDataDirectory());
|
||||
Poco::TemporaryFile KeyFile_(MicroServiceDataDirectory());
|
||||
std::vector<std::unique_ptr<Poco::TemporaryFile>> CaCertFiles_;
|
||||
|
||||
DecodeFile(CertFile_.path(), Server_.radsecCert);
|
||||
DecodeFile(KeyFile_.path(), Server_.radsecKey);
|
||||
|
||||
for (auto &cert : Server_.radsecCacerts) {
|
||||
CaCertFiles_.emplace_back(
|
||||
std::make_unique<Poco::TemporaryFile>(MicroServiceDataDirectory()));
|
||||
DecodeFile(CaCertFiles_[CaCertFiles_.size() - 1]->path(), cert);
|
||||
}
|
||||
|
||||
Poco::Net::Context::Ptr SecureContext =
|
||||
Poco::AutoPtr<Poco::Net::Context>(new Poco::Net::Context(
|
||||
Poco::Net::Context::TLS_CLIENT_USE, KeyFile_.path(), CertFile_.path(), ""));
|
||||
if (Server_.allowSelfSigned) {
|
||||
SecureContext->setSecurityLevel(Poco::Net::Context::SECURITY_LEVEL_NONE);
|
||||
SecureContext->enableExtendedCertificateVerification(false);
|
||||
}
|
||||
|
||||
for (const auto &ca : CaCertFiles_) {
|
||||
Poco::Crypto::X509Certificate cert(ca->path());
|
||||
SecureContext->addCertificateAuthority(cert);
|
||||
}
|
||||
|
||||
Socket_ = std::make_unique<Poco::Net::SecureStreamSocket>(SecureContext);
|
||||
|
||||
Poco::Net::SocketAddress Destination(Server_.ip, Server_.port);
|
||||
|
||||
try {
|
||||
poco_information(Logger_, "Attempting to connect");
|
||||
Socket_->connect(Destination, Poco::Timespan(100, 0));
|
||||
Socket_->completeHandshake();
|
||||
|
||||
if (!Server_.allowSelfSigned) {
|
||||
Socket_->verifyPeerCertificate();
|
||||
}
|
||||
|
||||
if (Socket_->havePeerCertificate()) {
|
||||
Peer_Cert_ = std::make_unique<Poco::Crypto::X509Certificate>(
|
||||
Socket_->peerCertificate());
|
||||
}
|
||||
|
||||
Socket_->setBlocking(false);
|
||||
Socket_->setNoDelay(true);
|
||||
Socket_->setKeepAlive(true);
|
||||
Socket_->setReceiveTimeout(Poco::Timespan(1 * 60 * 60, 0));
|
||||
|
||||
Reactor_.addEventHandler(
|
||||
*Socket_, Poco::NObserver<RADSEC_server, Poco::Net::ReadableNotification>(
|
||||
*this, &RADSEC_server::onData));
|
||||
Reactor_.addEventHandler(
|
||||
*Socket_, Poco::NObserver<RADSEC_server, Poco::Net::ErrorNotification>(
|
||||
*this, &RADSEC_server::onError));
|
||||
Reactor_.addEventHandler(
|
||||
*Socket_, Poco::NObserver<RADSEC_server, Poco::Net::ShutdownNotification>(
|
||||
*this, &RADSEC_server::onShutdown));
|
||||
|
||||
Connected_ = true;
|
||||
poco_information(Logger_, fmt::format("Connected. CN={}", CommonName()));
|
||||
return true;
|
||||
} catch (const Poco::Net::NetException &E) {
|
||||
poco_information(Logger_, "Could not connect.");
|
||||
Logger_.log(E);
|
||||
} catch (const Poco::Exception &E) {
|
||||
poco_information(Logger_, "Could not connect.");
|
||||
Logger_.log(E);
|
||||
} catch (...) {
|
||||
poco_information(Logger_, "Could not connect.");
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
inline void Disconnect() {
|
||||
if (Connected_) {
|
||||
std::lock_guard G(LocalMutex_);
|
||||
|
||||
Reactor_.removeEventHandler(
|
||||
*Socket_, Poco::NObserver<RADSEC_server, Poco::Net::ReadableNotification>(
|
||||
*this, &RADSEC_server::onData));
|
||||
Reactor_.removeEventHandler(
|
||||
*Socket_, Poco::NObserver<RADSEC_server, Poco::Net::ErrorNotification>(
|
||||
*this, &RADSEC_server::onError));
|
||||
Reactor_.removeEventHandler(
|
||||
*Socket_, Poco::NObserver<RADSEC_server, Poco::Net::ShutdownNotification>(
|
||||
*this, &RADSEC_server::onShutdown));
|
||||
Socket_->close();
|
||||
Connected_ = false;
|
||||
}
|
||||
poco_information(Logger_, "Disconnecting.");
|
||||
}
|
||||
|
||||
static void DecodeFile(const std::string &filename, const std::string &s) {
|
||||
std::ofstream sec_file(filename, std::ios_base::out | std::ios_base::trunc |
|
||||
std::ios_base::binary);
|
||||
std::stringstream is(s);
|
||||
Poco::Base64Decoder ds(is);
|
||||
Poco::StreamCopier::copyStream(ds, sec_file);
|
||||
sec_file.close();
|
||||
}
|
||||
|
||||
[[nodiscard]] inline std::string CommonName() {
|
||||
if (Peer_Cert_)
|
||||
return Peer_Cert_->commonName();
|
||||
return "";
|
||||
}
|
||||
|
||||
[[nodiscard]] inline std::string IssuerName() {
|
||||
if (Peer_Cert_)
|
||||
return Peer_Cert_->issuerName();
|
||||
return "";
|
||||
}
|
||||
|
||||
[[nodiscard]] inline std::string SubjectName() {
|
||||
if (Peer_Cert_)
|
||||
return Peer_Cert_->subjectName();
|
||||
return "";
|
||||
}
|
||||
|
||||
private:
|
||||
std::recursive_mutex LocalMutex_;
|
||||
Poco::Net::SocketReactor &Reactor_;
|
||||
GWObjects::RadiusProxyServerEntry Server_;
|
||||
Poco::Logger &Logger_;
|
||||
std::unique_ptr<Poco::Net::SecureStreamSocket> Socket_;
|
||||
Poco::Thread ReconnectThread_;
|
||||
std::unique_ptr<Poco::Crypto::X509Certificate> Peer_Cert_;
|
||||
volatile bool Connected_ = false;
|
||||
volatile bool TryAgain_ = true;
|
||||
};
|
||||
} // namespace OpenWifi
|
||||
@@ -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,12 +181,29 @@ 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)) {
|
||||
if (Params.has(uCentralProtocol::CONFIG) && Params.isObject(uCentralProtocol::CONFIG)) {
|
||||
auto Config = Params.get(uCentralProtocol::CONFIG)
|
||||
.extract<Poco::JSON::Object::Ptr>();
|
||||
DeviceConfigurationChangeKafkaEvent KEvent(
|
||||
Utils::SerialNumberToInt(Cmd.SerialNumber), Utils::Now(),
|
||||
Params.get(uCentralProtocol::CONFIG).toString());
|
||||
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;
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
//
|
||||
|
||||
#include "Poco/Array.h"
|
||||
#include "Poco/JSON/Stringifier.h"
|
||||
|
||||
#include "RESTAPI_default_configurations.h"
|
||||
#include "StorageService.h"
|
||||
|
||||
117
src/RESTAPI/RESTAPI_default_firmware.cpp
Normal file
117
src/RESTAPI/RESTAPI_default_firmware.cpp
Normal file
@@ -0,0 +1,117 @@
|
||||
//
|
||||
// License type: BSD 3-Clause License
|
||||
// License copy: https://github.com/Telecominfraproject/wlan-cloud-ucentralgw/blob/master/LICENSE
|
||||
//
|
||||
// Created by stephane bourque on 2023-07-11.
|
||||
// Arilia Wireless Inc.
|
||||
//
|
||||
|
||||
#include "RESTAPI/RESTAPI_default_firmware.h"
|
||||
|
||||
#include "RESTObjects/RESTAPI_GWobjects.h"
|
||||
#include "StorageService.h"
|
||||
#include "framework/orm.h"
|
||||
#include "framework/ow_constants.h"
|
||||
#include "framework/utils.h"
|
||||
|
||||
namespace OpenWifi {
|
||||
void RESTAPI_default_firmware::DoGet() {
|
||||
std::string deviceType = ORM::Escape(GetBinding(RESTAPI::Protocol::DEVICETYPE, ""));
|
||||
GWObjects::DefaultFirmware Firmware;
|
||||
if (StorageService()->GetDefaultFirmware(deviceType, Firmware)) {
|
||||
return Object(Firmware);
|
||||
}
|
||||
NotFound();
|
||||
}
|
||||
|
||||
void RESTAPI_default_firmware::DoDelete() {
|
||||
std::string deviceType = ORM::Escape(GetBinding(RESTAPI::Protocol::DEVICETYPE, ""));
|
||||
if (deviceType.empty()) {
|
||||
return BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
|
||||
}
|
||||
|
||||
if (StorageService()->DeleteDefaultFirmware(deviceType)) {
|
||||
return OK();
|
||||
}
|
||||
BadRequest(RESTAPI::Errors::CouldNotBeDeleted);
|
||||
}
|
||||
|
||||
void RESTAPI_default_firmware::DoPost() {
|
||||
std::string deviceType = GetBinding(RESTAPI::Protocol::DEVICETYPE, "");
|
||||
|
||||
if (deviceType.empty()) {
|
||||
return BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
|
||||
}
|
||||
|
||||
if (StorageService()->DefaultFirmwareAlreadyExists(deviceType)) {
|
||||
return BadRequest(RESTAPI::Errors::DefFirmwareNameExists);
|
||||
}
|
||||
|
||||
const auto &Obj = ParsedBody_;
|
||||
GWObjects::DefaultFirmware Firmware;
|
||||
if (!Firmware.from_json(Obj)) {
|
||||
return BadRequest(RESTAPI::Errors::InvalidJSONDocument);
|
||||
}
|
||||
|
||||
if(Firmware.uri.empty() || Firmware.revision.empty()) {
|
||||
return BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
|
||||
}
|
||||
|
||||
try {
|
||||
Poco::URI FirmwareURI(Firmware.uri);
|
||||
} catch (...) {
|
||||
return BadRequest(RESTAPI::Errors::InvalidURI);
|
||||
}
|
||||
|
||||
Firmware.Created = Firmware.LastModified = Utils::Now();
|
||||
if (StorageService()->CreateDefaultFirmware(Firmware)) {
|
||||
GWObjects::DefaultFirmware ModifiedFirmware;
|
||||
StorageService()->GetDefaultFirmware(deviceType, ModifiedFirmware);
|
||||
return Object(ModifiedFirmware);
|
||||
}
|
||||
BadRequest(RESTAPI::Errors::RecordNotCreated);
|
||||
}
|
||||
|
||||
void RESTAPI_default_firmware::DoPut() {
|
||||
std::string deviceType = GetBinding(RESTAPI::Protocol::DEVICETYPE, "");
|
||||
|
||||
const auto &Obj = ParsedBody_;
|
||||
GWObjects::DefaultFirmware NewFirmware;
|
||||
if (!NewFirmware.from_json(Obj)) {
|
||||
return BadRequest(RESTAPI::Errors::InvalidJSONDocument);
|
||||
}
|
||||
|
||||
GWObjects::DefaultFirmware Existing;
|
||||
if (!StorageService()->GetDefaultFirmware(deviceType, Existing)) {
|
||||
return NotFound();
|
||||
}
|
||||
|
||||
Existing.LastModified = Utils::Now();
|
||||
AssignIfPresent(Obj, "description", Existing.Description);
|
||||
AssignIfPresent(Obj, "imageCreationDate", Existing.imageCreationDate);
|
||||
AssignIfPresent(Obj, "revision", Existing.revision);
|
||||
|
||||
|
||||
if (Obj->has("uri")) {
|
||||
if(NewFirmware.uri.empty()) {
|
||||
return BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
|
||||
}
|
||||
try {
|
||||
Poco::URI FirmwareURI(NewFirmware.uri);
|
||||
} catch (...) {
|
||||
return BadRequest(RESTAPI::Errors::InvalidURI);
|
||||
}
|
||||
Existing.uri = NewFirmware.uri;
|
||||
}
|
||||
|
||||
|
||||
if (StorageService()->UpdateDefaultFirmware(Existing)) {
|
||||
GWObjects::DefaultFirmware ModifiedFirmware;
|
||||
|
||||
StorageService()->GetDefaultFirmware(deviceType, ModifiedFirmware);
|
||||
return Object(ModifiedFirmware);
|
||||
}
|
||||
|
||||
BadRequest(RESTAPI::Errors::RecordNotUpdated);
|
||||
}
|
||||
} // namespace OpenWifi
|
||||
30
src/RESTAPI/RESTAPI_default_firmware.h
Normal file
30
src/RESTAPI/RESTAPI_default_firmware.h
Normal file
@@ -0,0 +1,30 @@
|
||||
//
|
||||
// Created by stephane bourque on 2023-07-11.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "framework/RESTAPI_Handler.h"
|
||||
|
||||
namespace OpenWifi {
|
||||
class RESTAPI_default_firmware : public RESTAPIHandler {
|
||||
public:
|
||||
RESTAPI_default_firmware(const RESTAPIHandler::BindingMap &bindings, Poco::Logger &L,
|
||||
RESTAPI_GenericServerAccounting &Server,
|
||||
uint64_t TransactionId, bool Internal)
|
||||
: RESTAPIHandler(bindings, L,
|
||||
std::vector<std::string>{Poco::Net::HTTPRequest::HTTP_GET,
|
||||
Poco::Net::HTTPRequest::HTTP_POST,
|
||||
Poco::Net::HTTPRequest::HTTP_PUT,
|
||||
Poco::Net::HTTPRequest::HTTP_DELETE,
|
||||
Poco::Net::HTTPRequest::HTTP_OPTIONS},
|
||||
Server, TransactionId, Internal) {}
|
||||
static auto PathName() {
|
||||
return std::list<std::string>{"/api/v1/default_firmware/{deviceType}"};
|
||||
}
|
||||
void DoGet() final;
|
||||
void DoDelete() final;
|
||||
void DoPost() final;
|
||||
void DoPut() final;
|
||||
};
|
||||
} // namespace OpenWifi
|
||||
25
src/RESTAPI/RESTAPI_default_firmwares.cpp
Normal file
25
src/RESTAPI/RESTAPI_default_firmwares.cpp
Normal file
@@ -0,0 +1,25 @@
|
||||
//
|
||||
// Created by stephane bourque on 2023-07-11.
|
||||
//
|
||||
|
||||
#include "RESTAPI_default_firmwares.h"
|
||||
|
||||
#include "Poco/Array.h"
|
||||
|
||||
#include "RESTAPI_default_firmwares.h"
|
||||
#include "StorageService.h"
|
||||
#include "framework/ow_constants.h"
|
||||
|
||||
namespace OpenWifi {
|
||||
void RESTAPI_default_firmwares::DoGet() {
|
||||
|
||||
if (QB_.CountOnly) {
|
||||
auto Count = StorageService()->GetDefaultFirmwaresCount();
|
||||
return ReturnCountOnly(Count);
|
||||
}
|
||||
|
||||
std::vector<GWObjects::DefaultFirmware> Firmwares;
|
||||
StorageService()->GetDefaultFirmwares(QB_.Offset, QB_.Limit, Firmwares);
|
||||
return Object(RESTAPI::Protocol::FIRMWARES, Firmwares);
|
||||
}
|
||||
} // namespace OpenWifi
|
||||
25
src/RESTAPI/RESTAPI_default_firmwares.h
Normal file
25
src/RESTAPI/RESTAPI_default_firmwares.h
Normal file
@@ -0,0 +1,25 @@
|
||||
//
|
||||
// Created by stephane bourque on 2023-07-11.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "framework/RESTAPI_Handler.h"
|
||||
|
||||
namespace OpenWifi {
|
||||
class RESTAPI_default_firmwares : public RESTAPIHandler {
|
||||
public:
|
||||
RESTAPI_default_firmwares(const RESTAPIHandler::BindingMap &bindings, Poco::Logger &L,
|
||||
RESTAPI_GenericServerAccounting &Server,
|
||||
uint64_t TransactionId, bool Internal)
|
||||
: RESTAPIHandler(bindings, L,
|
||||
std::vector<std::string>{Poco::Net::HTTPRequest::HTTP_GET,
|
||||
Poco::Net::HTTPRequest::HTTP_OPTIONS},
|
||||
Server, TransactionId, Internal){};
|
||||
static auto PathName() { return std::list<std::string>{"/api/v1/default_firmwares"}; }
|
||||
void DoGet() final;
|
||||
void DoDelete() final{};
|
||||
void DoPost() final{};
|
||||
void DoPut() final{};
|
||||
};
|
||||
} // namespace OpenWifi
|
||||
@@ -87,7 +87,7 @@ 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);
|
||||
};
|
||||
@@ -163,8 +163,15 @@ namespace OpenWifi {
|
||||
{APCommands::Commands::telemetry, false, true, &RESTAPI_device_commandHandler::Telemetry,
|
||||
30000ms},
|
||||
{APCommands::Commands::ping, false, true, &RESTAPI_device_commandHandler::Ping, 60000ms},
|
||||
{APCommands::Commands::script, false, true, &RESTAPI_device_commandHandler::Script,
|
||||
300000ms}};
|
||||
{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::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},
|
||||
|
||||
};
|
||||
|
||||
void RESTAPI_device_commandHandler::DoPost() {
|
||||
if (!ValidateParameters()) {
|
||||
@@ -650,13 +657,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);
|
||||
@@ -682,9 +694,32 @@ 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;
|
||||
Cmd.Details.append(" (compressed: " + CompressedBase64Data + ")");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 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) {
|
||||
@@ -1024,7 +1059,7 @@ namespace OpenWifi {
|
||||
RESTAPI_RPC::WaitForCommand(CMD_RPC, APCommands::Commands::wifiscan, false, Cmd, Params,
|
||||
*Request, *Response, timeout, nullptr, this, Logger_);
|
||||
if (Cmd.ErrorCode == 0) {
|
||||
KafkaManager()->PostMessage(KafkaTopics::WIFISCAN, SerialNumber_, std::make_shared<std::string>(Cmd.Results));
|
||||
KafkaManager()->PostMessage(KafkaTopics::WIFISCAN, SerialNumber_, Cmd.Results);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1069,7 +1104,7 @@ namespace OpenWifi {
|
||||
Logger_);
|
||||
if (Cmd.ErrorCode == 0) {
|
||||
KafkaManager()->PostMessage(KafkaTopics::DEVICE_EVENT_QUEUE, SerialNumber_,
|
||||
std::make_shared<std::string>(Cmd.Results));
|
||||
Cmd.Results);
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -1126,9 +1161,6 @@ namespace OpenWifi {
|
||||
BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
|
||||
}
|
||||
|
||||
#define DBGLINE \
|
||||
{ std::cout << __LINE__ << std::endl; }
|
||||
|
||||
void RESTAPI_device_commandHandler::Rtty(
|
||||
const std::string &CMD_UUID, uint64_t CMD_RPC, std::chrono::milliseconds timeout,
|
||||
[[maybe_unused]] const GWObjects::DeviceRestrictions &Restrictions) {
|
||||
@@ -1169,7 +1201,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(),
|
||||
@@ -1342,4 +1374,276 @@ namespace OpenWifi {
|
||||
}
|
||||
return BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
|
||||
}
|
||||
|
||||
void RESTAPI_device_commandHandler::RRM(
|
||||
const std::string &CMD_UUID, uint64_t CMD_RPC,
|
||||
[[maybe_unused]] std::chrono::milliseconds timeout,
|
||||
[[maybe_unused]] const GWObjects::DeviceRestrictions &Restrictions) {
|
||||
|
||||
poco_debug(Logger_, fmt::format("RRM({},{}): 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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
if(!ParsedBody_->has("actions") || !ParsedBody_->isArray("actions")) {
|
||||
return BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
|
||||
}
|
||||
|
||||
const auto &Actions = *ParsedBody_->getArray("actions");
|
||||
// perform some validation on the commands.
|
||||
for(const auto &action:Actions) {
|
||||
auto ActionDetails = action.extract<Poco::JSON::Object::Ptr>();
|
||||
if(!ActionDetails->has("action")) {
|
||||
return BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
|
||||
}
|
||||
auto ActionStr = ActionDetails->get("action").toString();
|
||||
if( ActionStr != "kick"
|
||||
&& ActionStr != "channel_switch"
|
||||
&& ActionStr != "tx_power"
|
||||
&& ActionStr != "beacon_request"
|
||||
&& ActionStr != "bss_transition"
|
||||
&& ActionStr != "neighbors" ) {
|
||||
return BadRequest(RESTAPI::Errors::InvalidRRMAction);
|
||||
}
|
||||
}
|
||||
|
||||
Poco::JSON::Object Params;
|
||||
Params.set(uCentralProtocol::SERIAL, SerialNumber_);
|
||||
Params.set(uCentralProtocol::ACTIONS, Actions);
|
||||
|
||||
GWObjects::CommandDetails Cmd;
|
||||
Cmd.SerialNumber = SerialNumber_;
|
||||
Cmd.SubmittedBy = Requester();
|
||||
Cmd.UUID = CMD_UUID;
|
||||
Cmd.Command = uCentralProtocol::RRM;
|
||||
std::ostringstream os;
|
||||
Params.stringify(os);
|
||||
Cmd.Details = os.str();
|
||||
Cmd.RunAt = 0;
|
||||
Cmd.ErrorCode = 0;
|
||||
Cmd.WaitingForFile = 0;
|
||||
Cmd.Status= "completed";
|
||||
if(CommandManager()->FireAndForget(SerialNumber_, uCentralProtocol::RRM, Params)) {
|
||||
Cmd.Status= "completed";
|
||||
StorageService()->AddCommand(SerialNumber_, Cmd,
|
||||
Storage::CommandExecutionType::COMMAND_COMPLETED);
|
||||
return OK();
|
||||
}
|
||||
Cmd.Status= "failed"; // should never happen
|
||||
StorageService()->AddCommand(SerialNumber_, Cmd,
|
||||
Storage::CommandExecutionType::COMMAND_COMPLETED);
|
||||
return BadRequest(RESTAPI::Errors::CouldNotPerformCommand);
|
||||
}
|
||||
|
||||
void RESTAPI_device_commandHandler::Transfer(
|
||||
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("TRANSFER({},{}): 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::DeviceTransferRequest TR;
|
||||
if(!TR.from_json(ParsedBody_)) {
|
||||
return BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
|
||||
}
|
||||
|
||||
GWObjects::CommandDetails Cmd;
|
||||
Cmd.SerialNumber = SerialNumber_;
|
||||
Cmd.SubmittedBy = Requester();
|
||||
Cmd.UUID = CMD_UUID;
|
||||
Cmd.Command = uCentralProtocol::TRANSFER;
|
||||
std::ostringstream os;
|
||||
ParsedBody_->stringify(os);
|
||||
Cmd.Details = os.str();
|
||||
Cmd.RunAt = 0;
|
||||
Cmd.ErrorCode = 0;
|
||||
Cmd.WaitingForFile = 0;
|
||||
|
||||
return RESTAPI_RPC::WaitForCommand(CMD_RPC, APCommands::Commands::transfer, false, Cmd,
|
||||
*ParsedBody_, *Request, *Response, timeout, nullptr, this,
|
||||
Logger_);
|
||||
}
|
||||
|
||||
void RESTAPI_device_commandHandler::CertUpdate(
|
||||
const std::string &CMD_UUID, uint64_t CMD_RPC,
|
||||
[[maybe_unused]] std::chrono::milliseconds timeout,
|
||||
[[maybe_unused]] const GWObjects::DeviceRestrictions &Restrictions) {
|
||||
|
||||
poco_debug(Logger_, fmt::format("CERTUPDATE({},{}): TID={} user={} serial={}", CMD_UUID,
|
||||
CMD_RPC, TransactionId_, Requester(), SerialNumber_));
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
if(IsDeviceSimulated(SerialNumber_)) {
|
||||
CallCanceled("RRM", CMD_UUID, CMD_RPC, RESTAPI::Errors::SimulatedDeviceNotSupported);
|
||||
return BadRequest(RESTAPI::Errors::SimulatedDeviceNotSupported);
|
||||
}
|
||||
|
||||
GWObjects::DeviceCertificateUpdateRequest CR;
|
||||
if(!CR.from_json(ParsedBody_)) {
|
||||
return BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
|
||||
}
|
||||
|
||||
GWObjects::DeviceTransferRequest TR;
|
||||
if(!TR.from_json(ParsedBody_)) {
|
||||
return BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
|
||||
}
|
||||
|
||||
GWObjects::CommandDetails Cmd;
|
||||
Cmd.SerialNumber = SerialNumber_;
|
||||
Cmd.SubmittedBy = Requester();
|
||||
Cmd.UUID = CMD_UUID;
|
||||
Cmd.Command = uCentralProtocol::CERTUPDATE;
|
||||
std::ostringstream os;
|
||||
ParsedBody_->stringify(os);
|
||||
Cmd.Details = os.str();
|
||||
Cmd.RunAt = 0;
|
||||
Cmd.ErrorCode = 0;
|
||||
Cmd.WaitingForFile = 0;
|
||||
|
||||
return RESTAPI_RPC::WaitForCommand(CMD_RPC, APCommands::Commands::certupdate, false, Cmd,
|
||||
*ParsedBody_, *Request, *Response, timeout, nullptr, this,
|
||||
Logger_);
|
||||
|
||||
|
||||
}
|
||||
|
||||
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_);
|
||||
}
|
||||
|
||||
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_));
|
||||
if(IsDeviceSimulated(SerialNumber_)) {
|
||||
CallCanceled("FIXEDCONFIG", CMD_UUID, CMD_RPC, RESTAPI::Errors::SimulatedDeviceNotSupported);
|
||||
return BadRequest(RESTAPI::Errors::SimulatedDeviceNotSupported);
|
||||
}
|
||||
|
||||
GWObjects::FixedConfig fixed_config;
|
||||
if(!fixed_config.from_json(ParsedBody_)) {
|
||||
return BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
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_);
|
||||
}
|
||||
} // namespace OpenWifi
|
||||
|
||||
@@ -62,6 +62,18 @@ namespace OpenWifi {
|
||||
const GWObjects::DeviceRestrictions &R);
|
||||
void Script(const std::string &UUID, uint64_t RPC, std::chrono::milliseconds timeout,
|
||||
const GWObjects::DeviceRestrictions &R);
|
||||
void RRM(const std::string &UUID, uint64_t RPC, std::chrono::milliseconds timeout,
|
||||
const GWObjects::DeviceRestrictions &R);
|
||||
void CertUpdate(const std::string &UUID, uint64_t RPC, std::chrono::milliseconds timeout,
|
||||
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);
|
||||
|
||||
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, includeProvisioned)) {
|
||||
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;
|
||||
@@ -174,6 +183,15 @@ namespace OpenWifi {
|
||||
return UnAuthorized(RESTAPI::Errors::ACCESS_DENIED);
|
||||
}
|
||||
|
||||
if(GetBoolParameter("simulatedDevices",false)) {
|
||||
auto F = []() ->void {
|
||||
StorageService()->DeleteSimulatedDevice("");
|
||||
};
|
||||
std::thread T(F);
|
||||
T.detach();
|
||||
return OK();
|
||||
}
|
||||
|
||||
if(!QB_.Select.empty() && !Utils::ValidSerialNumbers(QB_.Select)) {
|
||||
return BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -8,6 +8,11 @@
|
||||
|
||||
namespace OpenWifi {
|
||||
|
||||
static bool ValidRadiusPoolServerType(const std::string &T) {
|
||||
static std::set<std::string> Types{ "radsec", "generic", "orion", "globalreach"};
|
||||
return Types.find(T)!=Types.end();
|
||||
}
|
||||
|
||||
void RESTAPI_radiusProxyConfig_handler::DoGet() {
|
||||
Logger_.information(fmt::format("GET-RADIUS-PROXY-CONFIG: TID={} user={} thr_id={}",
|
||||
TransactionId_, Requester(),
|
||||
@@ -44,10 +49,22 @@ namespace OpenWifi {
|
||||
}
|
||||
|
||||
// Logically validate the config.
|
||||
for (const auto &pool : C.pools) {
|
||||
for (auto &pool : C.pools) {
|
||||
if (pool.name.empty()) {
|
||||
return BadRequest(RESTAPI::Errors::PoolNameInvalid);
|
||||
}
|
||||
if (pool.radsecPoolType.empty()) {
|
||||
pool.radsecPoolType = "generic";
|
||||
}
|
||||
|
||||
if(!ValidRadiusPoolServerType(pool.radsecPoolType)) {
|
||||
return BadRequest(RESTAPI::Errors::NotAValidRadiusPoolType);
|
||||
}
|
||||
|
||||
if(pool.radsecKeepAlive==0) {
|
||||
pool.radsecKeepAlive=25;
|
||||
}
|
||||
|
||||
for (const auto &config : {pool.acctConfig, pool.authConfig, pool.coaConfig}) {
|
||||
if (config.servers.empty())
|
||||
continue;
|
||||
|
||||
@@ -110,14 +110,26 @@ namespace OpenWifi {
|
||||
return BadRequest(RESTAPI::Errors::InvalidJSONDocument);
|
||||
}
|
||||
|
||||
if(Parameters.callingStationId.empty() || Parameters.accountingSessionId.empty() || Parameters.accountingMultiSessionId.empty()) {
|
||||
return BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
|
||||
}
|
||||
|
||||
auto Command = GetParameter("operation","");
|
||||
|
||||
if(Command=="coadm") {
|
||||
if(RADIUSSessionTracker()->SendCoADM(SerialNumber, Parameters.accountingSessionId)) {
|
||||
if(Parameters.callingStationId.empty() || Parameters.accountingSessionId.empty() || Parameters.accountingMultiSessionId.empty()) {
|
||||
return BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
|
||||
}
|
||||
auto Index = Parameters.accountingSessionId + Parameters.accountingMultiSessionId;
|
||||
poco_information(Logger(), fmt::format("Disconnecting session {},{}", Parameters.accountingSessionId, Parameters.accountingMultiSessionId ));
|
||||
if(RADIUSSessionTracker()->SendCoADM(SerialNumber, Index)) {
|
||||
return OK();
|
||||
}
|
||||
return BadRequest(RESTAPI::Errors::CouldNotPerformCommand);
|
||||
}
|
||||
|
||||
if(Command=="disconnectUser" && !Parameters.userName.empty()) {
|
||||
if(Parameters.userName.empty()) {
|
||||
return BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
|
||||
}
|
||||
poco_information(Logger(), fmt::format("Disconnecting sessions for user: {}", Parameters.userName ));
|
||||
if(RADIUSSessionTracker()->DisconnectUser(Parameters.userName)) {
|
||||
return OK();
|
||||
}
|
||||
return BadRequest(RESTAPI::Errors::CouldNotPerformCommand);
|
||||
|
||||
@@ -22,6 +22,8 @@
|
||||
#include "RESTAPI/RESTAPI_scripts_handler.h"
|
||||
#include "RESTAPI/RESTAPI_telemetryWebSocket.h"
|
||||
#include "RESTAPI/RESTAPI_radiussessions_handler.h"
|
||||
#include "RESTAPI/RESTAPI_default_firmware.h"
|
||||
#include "RESTAPI/RESTAPI_default_firmwares.h"
|
||||
|
||||
#include "framework/RESTAPI_SystemCommand.h"
|
||||
#include "framework/RESTAPI_SystemConfiguration.h"
|
||||
@@ -41,7 +43,8 @@ namespace OpenWifi {
|
||||
RESTAPI_blacklist, RESTAPI_blacklist_list, RESTAPI_iptocountry_handler,
|
||||
RESTAPI_radiusProxyConfig_handler, RESTAPI_scripts_handler, RESTAPI_script_handler,
|
||||
RESTAPI_capabilities_handler, RESTAPI_telemetryWebSocket, RESTAPI_radiussessions_handler,
|
||||
RESTAPI_regulatory>(Path, Bindings, L, S,
|
||||
RESTAPI_regulatory, RESTAPI_default_firmwares,
|
||||
RESTAPI_default_firmware>(Path, Bindings, L, S,
|
||||
TransactionId);
|
||||
}
|
||||
|
||||
@@ -55,6 +58,7 @@ namespace OpenWifi {
|
||||
RESTAPI_commands, RESTAPI_ouis, RESTAPI_file, RESTAPI_blacklist,
|
||||
RESTAPI_iptocountry_handler, RESTAPI_radiusProxyConfig_handler, RESTAPI_scripts_handler,
|
||||
RESTAPI_script_handler, RESTAPI_blacklist_list, RESTAPI_radiussessions_handler,
|
||||
RESTAPI_regulatory>(Path, Bindings, L, S, TransactionId);
|
||||
RESTAPI_regulatory, RESTAPI_default_firmwares,
|
||||
RESTAPI_default_firmware>(Path, Bindings, L, S, TransactionId);
|
||||
}
|
||||
} // namespace OpenWifi
|
||||
@@ -23,8 +23,8 @@ namespace OpenWifi {
|
||||
void RESTAPI_script_handler::DoDelete() {
|
||||
std::string UUID = GetBinding("uuid", "");
|
||||
|
||||
if (UserInfo_.userinfo.userRole != SecurityObjects::ROOT) {
|
||||
return BadRequest(RESTAPI::Errors::ACCESS_DENIED);
|
||||
if (!UserInfo_.userinfo.userPermissions[SecurityObjects::PM_SCRIPTS_GW][SecurityObjects::PT_DELETE]) {
|
||||
return UnAuthorized(RESTAPI::Errors::ACCESS_DENIED);
|
||||
}
|
||||
|
||||
if (UUID.empty()) {
|
||||
@@ -40,8 +40,8 @@ namespace OpenWifi {
|
||||
void RESTAPI_script_handler::DoPost() {
|
||||
std::string UUID = GetBinding("uuid", "");
|
||||
|
||||
if (UserInfo_.userinfo.userRole != SecurityObjects::ROOT) {
|
||||
return BadRequest(RESTAPI::Errors::ACCESS_DENIED);
|
||||
if (!UserInfo_.userinfo.userPermissions[SecurityObjects::PM_SCRIPTS_GW][SecurityObjects::PT_CREATE]) {
|
||||
return UnAuthorized(RESTAPI::Errors::ACCESS_DENIED);
|
||||
}
|
||||
|
||||
if (UUID.empty()) {
|
||||
@@ -86,8 +86,8 @@ namespace OpenWifi {
|
||||
void RESTAPI_script_handler::DoPut() {
|
||||
std::string UUID = GetBinding("uuid", "");
|
||||
|
||||
if (UserInfo_.userinfo.userRole != SecurityObjects::ROOT) {
|
||||
return BadRequest(RESTAPI::Errors::ACCESS_DENIED);
|
||||
if (!UserInfo_.userinfo.userPermissions[SecurityObjects::PM_SCRIPTS_GW][SecurityObjects::PT_UPDATE]) {
|
||||
return UnAuthorized(RESTAPI::Errors::ACCESS_DENIED);
|
||||
}
|
||||
|
||||
if (UUID.empty()) {
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include "RESTAPI_ProvObjects.h"
|
||||
#include "framework/utils.h"
|
||||
#include <vector>
|
||||
#include "framework/ow_constants.h"
|
||||
|
||||
namespace OpenWifi {
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#include "Daemon.h"
|
||||
#ifdef TIP_GATEWAY_SERVICE
|
||||
#include "AP_WS_Server.h"
|
||||
#include "StorageService.h"
|
||||
#include "CapabilitiesCache.h"
|
||||
#include "RADIUSSessionTracker.h"
|
||||
#endif
|
||||
@@ -29,8 +30,8 @@ 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);
|
||||
@@ -59,6 +60,8 @@ namespace OpenWifi::GWObjects {
|
||||
field_to_json(Obj, "pendingUUID", pendingUUID);
|
||||
field_to_json(Obj, "simulated", simulated);
|
||||
field_to_json(Obj, "lastRecordedContact", lastRecordedContact);
|
||||
field_to_json(Obj, "certificateExpiryDate", certificateExpiryDate);
|
||||
field_to_json(Obj, "connectReason", connectReason);
|
||||
}
|
||||
|
||||
void Device::to_json_with_status(Poco::JSON::Object &Obj) const {
|
||||
@@ -66,9 +69,14 @@ namespace OpenWifi::GWObjects {
|
||||
|
||||
#ifdef TIP_GATEWAY_SERVICE
|
||||
ConnectionState ConState;
|
||||
|
||||
if (AP_WS_Server()->GetState(SerialNumber, 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);
|
||||
#endif
|
||||
} else {
|
||||
field_to_json(Obj, "ipAddress", "");
|
||||
field_to_json(Obj, "txBytes", (uint64_t)0);
|
||||
@@ -122,6 +130,8 @@ namespace OpenWifi::GWObjects {
|
||||
field_from_json(Obj, "pendingUUID", pendingUUID);
|
||||
field_from_json(Obj, "simulated", simulated);
|
||||
field_from_json(Obj, "lastRecordedContact", lastRecordedContact);
|
||||
field_from_json(Obj, "certificateExpiryDate", certificateExpiryDate);
|
||||
field_from_json(Obj, "connectReason", connectReason);
|
||||
return true;
|
||||
} catch (const Poco::Exception &E) {
|
||||
}
|
||||
@@ -162,15 +172,43 @@ 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);
|
||||
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 {
|
||||
field_to_json(Obj, "deviceType", deviceType);
|
||||
field_to_json(Obj, "description", Description);
|
||||
field_to_json(Obj, "uri", uri);
|
||||
field_to_json(Obj, "revision", revision);
|
||||
field_to_json(Obj, "imageCreationDate", imageCreationDate);
|
||||
field_to_json(Obj, "created", Created);
|
||||
field_to_json(Obj, "lastModified", LastModified);
|
||||
}
|
||||
|
||||
bool DefaultFirmware::from_json(const Poco::JSON::Object::Ptr &Obj) {
|
||||
try {
|
||||
field_from_json(Obj, "deviceType", deviceType);
|
||||
field_from_json(Obj, "description", Description);
|
||||
field_from_json(Obj, "uri", uri);
|
||||
field_from_json(Obj, "revision", revision);
|
||||
field_from_json(Obj, "imageCreationDate", imageCreationDate);
|
||||
field_from_json(Obj, "created", Created);
|
||||
field_from_json(Obj, "lastModified", LastModified);
|
||||
return true;
|
||||
} catch (const Poco::Exception &E) {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void CommandDetails::to_json(Poco::JSON::Object &Obj) const {
|
||||
EmbedDocument("details", Obj, Details);
|
||||
EmbedDocument("results", Obj, Results);
|
||||
@@ -193,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) {
|
||||
}
|
||||
@@ -244,16 +295,14 @@ namespace OpenWifi::GWObjects {
|
||||
field_to_json(Obj, "started", started);
|
||||
field_to_json(Obj, "sessionId", sessionId);
|
||||
field_to_json(Obj, "connectionCompletionTime", connectionCompletionTime);
|
||||
field_to_json(Obj, "totalConnectionTime", Utils::Now() - started);
|
||||
field_to_json(Obj, "totalConnectionTime", started ? Utils::Now() - started : 0);
|
||||
field_to_json(Obj, "certificateExpiryDate", certificateExpiryDate);
|
||||
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, "hasGPS", hasGPS);
|
||||
@@ -285,6 +334,45 @@ 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, "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);
|
||||
@@ -405,6 +493,10 @@ namespace OpenWifi::GWObjects {
|
||||
field_to_json(Obj, "acctConfig", acctConfig);
|
||||
field_to_json(Obj, "coaConfig", coaConfig);
|
||||
field_to_json(Obj, "useByDefault", useByDefault);
|
||||
field_to_json(Obj, "radsecKeepAlive", radsecKeepAlive);
|
||||
field_to_json(Obj, "poolProxyIp", poolProxyIp);
|
||||
field_to_json(Obj, "radsecPoolType", radsecPoolType);
|
||||
field_to_json(Obj, "enabled", enabled);
|
||||
}
|
||||
|
||||
bool RadiusProxyPool::from_json(const Poco::JSON::Object::Ptr &Obj) {
|
||||
@@ -415,6 +507,10 @@ namespace OpenWifi::GWObjects {
|
||||
field_from_json(Obj, "acctConfig", acctConfig);
|
||||
field_from_json(Obj, "coaConfig", coaConfig);
|
||||
field_from_json(Obj, "useByDefault", useByDefault);
|
||||
field_from_json(Obj, "radsecKeepAlive", radsecKeepAlive);
|
||||
field_from_json(Obj, "poolProxyIp", poolProxyIp);
|
||||
field_from_json(Obj, "radsecPoolType", radsecPoolType);
|
||||
field_from_json(Obj, "enabled", enabled);
|
||||
return true;
|
||||
} catch (const Poco::Exception &E) {
|
||||
}
|
||||
@@ -633,22 +729,94 @@ namespace OpenWifi::GWObjects {
|
||||
field_to_json(Obj, "interface", interface);
|
||||
field_to_json(Obj, "secret", secret);
|
||||
field_to_json(Obj, "nasId", nasId);
|
||||
field_to_json(Obj, "calledStationId", calledStationId);
|
||||
}
|
||||
|
||||
void RADIUSSessionList::to_json(Poco::JSON::Object &Obj) const {
|
||||
field_to_json(Obj, "sessions", sessions);
|
||||
}
|
||||
|
||||
void RadiusCoADMParameters::to_json(Poco::JSON::Object &Obj) const {
|
||||
field_to_json(Obj, "accountingSessionId", accountingSessionId);
|
||||
field_to_json(Obj, "accountingMultiSessionId", accountingMultiSessionId);
|
||||
field_to_json(Obj, "callingStationId", callingStationId);
|
||||
field_to_json(Obj, "chargeableUserIdentity", chargeableUserIdentity);
|
||||
field_to_json(Obj, "userName", userName);
|
||||
}
|
||||
|
||||
bool RadiusCoADMParameters::from_json(const Poco::JSON::Object::Ptr &Obj) {
|
||||
try {
|
||||
field_from_json(Obj, "accountingSessionId", accountingSessionId);
|
||||
field_from_json(Obj, "accountingMultiSessionId", accountingMultiSessionId);
|
||||
field_from_json(Obj, "callingStationId", callingStationId);
|
||||
field_from_json(Obj, "chargeableUserIdentity", chargeableUserIdentity);
|
||||
field_from_json(Obj, "userName", userName);
|
||||
return true;
|
||||
} catch (const Poco::Exception &E) {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool DeviceTransferRequest::from_json(const Poco::JSON::Object::Ptr &Obj) {
|
||||
try {
|
||||
field_from_json(Obj, "serialNumber", serialNumber);
|
||||
field_from_json(Obj, "server", server);
|
||||
field_from_json(Obj, "port", port);
|
||||
return true;
|
||||
} catch (const Poco::Exception &E) {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool DeviceCertificateUpdateRequest::from_json(const Poco::JSON::Object::Ptr &Obj) {
|
||||
try {
|
||||
field_from_json(Obj, "serial", serialNumber);
|
||||
field_from_json(Obj, "encodedCertificate", encodedCertificate);
|
||||
return true;
|
||||
} catch (const Poco::Exception &E) {
|
||||
}
|
||||
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;
|
||||
}
|
||||
} // namespace OpenWifi::GWObjects
|
||||
|
||||
@@ -49,8 +49,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 {
|
||||
@@ -109,7 +112,10 @@ namespace OpenWifi::GWObjects {
|
||||
DeviceRestrictions restrictionDetails;
|
||||
std::uint64_t pendingUUID = 0;
|
||||
bool simulated=false;
|
||||
std::uint64_t lastRecordedContact=0;
|
||||
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;
|
||||
@@ -135,13 +141,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;
|
||||
@@ -172,12 +180,33 @@ namespace OpenWifi::GWObjects {
|
||||
};
|
||||
|
||||
struct DefaultConfiguration {
|
||||
std::string Name;
|
||||
std::string Configuration;
|
||||
Types::StringVec Models;
|
||||
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);
|
||||
};
|
||||
|
||||
struct DefaultFirmware {
|
||||
std::string deviceType;
|
||||
std::string Description;
|
||||
std::string uri;
|
||||
std::string revision;
|
||||
uint64_t imageCreationDate;
|
||||
uint64_t Created;
|
||||
uint64_t LastModified;
|
||||
|
||||
void to_json(Poco::JSON::Object &Obj) const;
|
||||
bool from_json(const Poco::JSON::Object::Ptr &Obj);
|
||||
};
|
||||
|
||||
struct DefaultFirmwareList {
|
||||
std::vector<DefaultFirmware> firmwares;
|
||||
|
||||
void to_json(Poco::JSON::Object &Obj) const;
|
||||
bool from_json(const Poco::JSON::Object::Ptr &Obj);
|
||||
};
|
||||
@@ -340,6 +369,10 @@ namespace OpenWifi::GWObjects {
|
||||
RadiusProxyServerConfig acctConfig;
|
||||
RadiusProxyServerConfig coaConfig;
|
||||
bool useByDefault = false;
|
||||
std::string radsecPoolType;
|
||||
std::string poolProxyIp;
|
||||
std::uint64_t radsecKeepAlive=25;
|
||||
bool enabled=true;
|
||||
|
||||
void to_json(Poco::JSON::Object &Obj) const;
|
||||
bool from_json(const Poco::JSON::Object::Ptr &Obj);
|
||||
@@ -403,6 +436,7 @@ namespace OpenWifi::GWObjects {
|
||||
inputGigaWords = 0,
|
||||
outputGigaWords = 0;
|
||||
std::uint32_t sessionTime = 0;
|
||||
std::string calledStationId;
|
||||
|
||||
#ifdef TIP_GATEWAY_SERVICE
|
||||
RADIUS::RadiusPacket accountingPacket;
|
||||
@@ -420,9 +454,97 @@ namespace OpenWifi::GWObjects {
|
||||
std::string accountingSessionId,
|
||||
accountingMultiSessionId,
|
||||
callingStationId,
|
||||
chargeableUserIdentity;
|
||||
chargeableUserIdentity,
|
||||
userName;
|
||||
|
||||
bool from_json(const Poco::JSON::Object::Ptr &Obj);
|
||||
void to_json(Poco::JSON::Object &Obj) const;
|
||||
};
|
||||
|
||||
enum class RadiusPoolStrategy {
|
||||
round_robin, random, weighted, unknown
|
||||
};
|
||||
|
||||
enum class RadiusEndpointType {
|
||||
generic, radsec, globalreach, orion, unknown
|
||||
};
|
||||
|
||||
static inline RadiusEndpointType RadiusEndpointType(const std::string &T) {
|
||||
if(T=="generic") return RadiusEndpointType::generic;
|
||||
if(T=="radsec") return RadiusEndpointType::radsec;
|
||||
if(T=="globalreach") return RadiusEndpointType::globalreach;
|
||||
if(T=="orion") return RadiusEndpointType::orion;
|
||||
return RadiusEndpointType::unknown;
|
||||
}
|
||||
|
||||
static inline RadiusPoolStrategy RadiusPoolStrategy(const std::string &T) {
|
||||
if(T=="round_robin") return RadiusPoolStrategy::round_robin;
|
||||
if(T=="random") return RadiusPoolStrategy::random;
|
||||
if(T=="weighted") return RadiusPoolStrategy::weighted;
|
||||
return RadiusPoolStrategy::unknown;
|
||||
}
|
||||
|
||||
static inline std::string to_string(enum RadiusEndpointType T) {
|
||||
switch(T) {
|
||||
case RadiusEndpointType::generic: return "generic";
|
||||
case RadiusEndpointType::radsec: return "radsec";
|
||||
case RadiusEndpointType::globalreach: return "globalreach";
|
||||
case RadiusEndpointType::orion: return "orion";
|
||||
default:
|
||||
return "unknown";
|
||||
}
|
||||
}
|
||||
|
||||
static inline std::string to_string(enum RadiusPoolStrategy T) {
|
||||
switch(T) {
|
||||
case RadiusPoolStrategy::round_robin: return "round_robin";
|
||||
case RadiusPoolStrategy::random: return "random";
|
||||
case RadiusPoolStrategy::weighted: return "weighted";
|
||||
default:
|
||||
return "unknown";
|
||||
}
|
||||
}
|
||||
|
||||
struct DeviceTransferRequest {
|
||||
std::string serialNumber;
|
||||
std::string server;
|
||||
std::uint64_t port;
|
||||
|
||||
bool from_json(const Poco::JSON::Object::Ptr &Obj);
|
||||
};
|
||||
|
||||
struct DeviceCertificateUpdateRequest {
|
||||
std::string serialNumber;
|
||||
std::string encodedCertificate;
|
||||
|
||||
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);
|
||||
};
|
||||
} // namespace OpenWifi::GWObjects
|
||||
|
||||
@@ -78,21 +78,22 @@ namespace OpenWifi::OWLSObjects {
|
||||
return false;
|
||||
}
|
||||
|
||||
void SimulationStatus::to_json(Poco::JSON::Object &Obj) const {
|
||||
field_to_json(Obj, "id", id);
|
||||
field_to_json(Obj, "simulationId", simulationId);
|
||||
field_to_json(Obj, "state", state);
|
||||
field_to_json(Obj, "tx", tx);
|
||||
field_to_json(Obj, "rx", rx);
|
||||
field_to_json(Obj, "msgsTx", msgsTx);
|
||||
field_to_json(Obj, "msgsRx", msgsRx);
|
||||
field_to_json(Obj, "liveDevices", liveDevices);
|
||||
field_to_json(Obj, "timeToFullDevices", timeToFullDevices);
|
||||
field_to_json(Obj, "startTime", startTime);
|
||||
field_to_json(Obj, "endTime", endTime);
|
||||
field_to_json(Obj, "errorDevices", errorDevices);
|
||||
field_to_json(Obj, "owner", owner);
|
||||
}
|
||||
void SimulationStatus::to_json(Poco::JSON::Object &Obj) const {
|
||||
field_to_json(Obj, "id", id);
|
||||
field_to_json(Obj, "simulationId", simulationId);
|
||||
field_to_json(Obj, "state", state);
|
||||
field_to_json(Obj, "tx", tx);
|
||||
field_to_json(Obj, "rx", rx);
|
||||
field_to_json(Obj, "msgsTx", msgsTx);
|
||||
field_to_json(Obj, "msgsRx", msgsRx);
|
||||
field_to_json(Obj, "liveDevices", liveDevices);
|
||||
field_to_json(Obj, "timeToFullDevices", timeToFullDevices);
|
||||
field_to_json(Obj, "startTime", startTime);
|
||||
field_to_json(Obj, "endTime", endTime);
|
||||
field_to_json(Obj, "errorDevices", errorDevices);
|
||||
field_to_json(Obj, "owner", owner);
|
||||
field_to_json(Obj, "expectedDevices", expectedDevices);
|
||||
}
|
||||
|
||||
void Dashboard::to_json([[maybe_unused]] Poco::JSON::Object &Obj) const {}
|
||||
|
||||
|
||||
@@ -43,23 +43,24 @@ namespace OpenWifi::OWLSObjects {
|
||||
bool from_json(const Poco::JSON::Object::Ptr &Obj);
|
||||
};
|
||||
|
||||
struct SimulationStatus {
|
||||
std::string id;
|
||||
std::string simulationId;
|
||||
std::string state;
|
||||
uint64_t tx;
|
||||
uint64_t rx;
|
||||
uint64_t msgsTx;
|
||||
uint64_t msgsRx;
|
||||
uint64_t liveDevices;
|
||||
uint64_t timeToFullDevices;
|
||||
uint64_t startTime;
|
||||
uint64_t endTime;
|
||||
uint64_t errorDevices;
|
||||
std::string owner;
|
||||
struct SimulationStatus {
|
||||
std::string id;
|
||||
std::string simulationId;
|
||||
std::string state;
|
||||
uint64_t tx;
|
||||
uint64_t rx;
|
||||
uint64_t msgsTx;
|
||||
uint64_t msgsRx;
|
||||
uint64_t liveDevices;
|
||||
uint64_t timeToFullDevices;
|
||||
uint64_t startTime;
|
||||
uint64_t endTime;
|
||||
uint64_t errorDevices;
|
||||
std::string owner;
|
||||
uint64_t expectedDevices;
|
||||
|
||||
void to_json(Poco::JSON::Object &Obj) const;
|
||||
};
|
||||
void to_json(Poco::JSON::Object &Obj) const;
|
||||
};
|
||||
|
||||
struct Dashboard {
|
||||
int O;
|
||||
|
||||
@@ -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 (...) {
|
||||
}
|
||||
@@ -1194,4 +1200,243 @@ namespace OpenWifi::ProvObjects {
|
||||
return false;
|
||||
}
|
||||
|
||||
void GLBLRAccountInfo::to_json(Poco::JSON::Object &Obj) const {
|
||||
info.to_json(Obj);
|
||||
field_to_json(Obj, "privateKey", privateKey);
|
||||
field_to_json(Obj, "country", country);
|
||||
field_to_json(Obj, "province", province);
|
||||
field_to_json(Obj, "city", city);
|
||||
field_to_json(Obj, "organization", organization);
|
||||
field_to_json(Obj, "commonName", commonName);
|
||||
field_to_json(Obj, "CSR", CSR);
|
||||
field_to_json(Obj, "CSRPrivateKey", CSRPrivateKey);
|
||||
field_to_json(Obj, "CSRPublicKey", CSRPublicKey);
|
||||
field_to_json(Obj, "GlobalReachAcctId", GlobalReachAcctId);
|
||||
}
|
||||
|
||||
bool GLBLRAccountInfo::from_json(const Poco::JSON::Object::Ptr &Obj) {
|
||||
try {
|
||||
info.from_json(Obj);
|
||||
field_from_json(Obj, "privateKey", privateKey);
|
||||
field_from_json(Obj, "country", country);
|
||||
field_from_json(Obj, "province", province);
|
||||
field_from_json(Obj, "city", city);
|
||||
field_from_json(Obj, "organization", organization);
|
||||
field_from_json(Obj, "commonName", commonName);
|
||||
field_from_json(Obj, "CSR", CSR);
|
||||
field_from_json(Obj, "CSRPrivateKey", CSRPrivateKey);
|
||||
field_from_json(Obj, "CSRPublicKey", CSRPublicKey);
|
||||
field_from_json(Obj, "GlobalReachAcctId", GlobalReachAcctId);
|
||||
return true;
|
||||
} catch (const Poco::Exception &E) {
|
||||
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void GLBLRCertificateInfo::to_json(Poco::JSON::Object &Obj) const {
|
||||
field_to_json(Obj, "id", id);
|
||||
field_to_json(Obj, "name", name);
|
||||
field_to_json(Obj, "accountId", accountId);
|
||||
field_to_json(Obj, "csr", csr);
|
||||
field_to_json(Obj, "certificate", certificate);
|
||||
field_to_json(Obj, "certificateChain", certificateChain);
|
||||
field_to_json(Obj, "certificateId", certificateId);
|
||||
field_to_json(Obj, "expiresAt", expiresAt);
|
||||
field_to_json(Obj, "created", created);
|
||||
}
|
||||
|
||||
bool GLBLRCertificateInfo::from_json(const Poco::JSON::Object::Ptr &Obj) {
|
||||
try {
|
||||
field_from_json(Obj, "id", id);
|
||||
field_from_json(Obj, "name", name);
|
||||
field_from_json(Obj, "accountId", accountId);
|
||||
field_from_json(Obj, "csr", csr);
|
||||
field_from_json(Obj, "certificate", certificate);
|
||||
field_from_json(Obj, "certificateChain", certificateChain);
|
||||
field_from_json(Obj, "certificateId", certificateId);
|
||||
field_from_json(Obj, "expiresAt", expiresAt);
|
||||
field_from_json(Obj, "created", created);
|
||||
return true;
|
||||
} catch (const Poco::Exception &E) {
|
||||
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void GooglOrionAccountInfo::to_json(Poco::JSON::Object &Obj) const {
|
||||
info.to_json(Obj);
|
||||
field_to_json(Obj, "privateKey", privateKey);
|
||||
field_to_json(Obj, "certificate", certificate);
|
||||
field_to_json(Obj, "cacerts", cacerts);
|
||||
}
|
||||
|
||||
bool GooglOrionAccountInfo::from_json(const Poco::JSON::Object::Ptr &Obj) {
|
||||
try {
|
||||
info.from_json(Obj);
|
||||
field_from_json(Obj, "privateKey", privateKey);
|
||||
field_from_json(Obj, "certificate", certificate);
|
||||
field_from_json(Obj, "cacerts", cacerts);
|
||||
return true;
|
||||
} catch (const Poco::Exception &E) {
|
||||
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void RADIUSServer::to_json(Poco::JSON::Object &Obj) const {
|
||||
field_to_json(Obj, "Hostname", Hostname);
|
||||
field_to_json(Obj, "IP", IP);
|
||||
field_to_json(Obj, "Port", Port);
|
||||
field_to_json(Obj, "Secret", Secret);
|
||||
}
|
||||
|
||||
bool RADIUSServer::from_json(const Poco::JSON::Object::Ptr &Obj) {
|
||||
try {
|
||||
field_from_json(Obj, "Hostname", Hostname);
|
||||
field_from_json(Obj, "IP", IP);
|
||||
field_from_json(Obj, "Port", Port);
|
||||
field_from_json(Obj, "Secret", Secret);
|
||||
return true;
|
||||
} catch (const Poco::Exception &E) {
|
||||
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void RADIUSEndPointRadiusType::to_json(Poco::JSON::Object &Obj) const {
|
||||
field_to_json(Obj, "Authentication", Authentication);
|
||||
field_to_json(Obj, "Accounting", Accounting);
|
||||
field_to_json(Obj, "CoA", CoA);
|
||||
field_to_json(Obj, "AccountingInterval", AccountingInterval);
|
||||
}
|
||||
|
||||
bool RADIUSEndPointRadiusType::from_json(const Poco::JSON::Object::Ptr &Obj) {
|
||||
try {
|
||||
field_from_json(Obj, "Authentication", Authentication);
|
||||
field_from_json(Obj, "Accounting", Accounting);
|
||||
field_from_json(Obj, "CoA", CoA);
|
||||
field_from_json(Obj, "AccountingInterval", AccountingInterval);
|
||||
return true;
|
||||
} catch (const Poco::Exception &E) {
|
||||
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void RADIUSEndPointRadsecType::to_json(Poco::JSON::Object &Obj) const {
|
||||
field_to_json(Obj, "Hostname", Hostname);
|
||||
field_to_json(Obj, "IP", IP);
|
||||
field_to_json(Obj, "Port", Port);
|
||||
field_to_json(Obj, "Secret", Secret);
|
||||
field_to_json(Obj, "OpenRoamingType", OpenRoamingType);
|
||||
field_to_json(Obj, "UseOpenRoamingAccount", UseOpenRoamingAccount);
|
||||
field_to_json(Obj, "Weight", Weight);
|
||||
field_to_json(Obj, "Certificate", Certificate);
|
||||
field_to_json(Obj, "PrivateKey", PrivateKey);
|
||||
field_to_json(Obj, "CaCerts", CaCerts);
|
||||
field_to_json(Obj, "AllowSelfSigned", AllowSelfSigned);
|
||||
}
|
||||
|
||||
bool RADIUSEndPointRadsecType::from_json(const Poco::JSON::Object::Ptr &Obj) {
|
||||
try {
|
||||
field_from_json(Obj, "Hostname", Hostname);
|
||||
field_from_json(Obj, "IP", IP);
|
||||
field_from_json(Obj, "Port", Port);
|
||||
field_from_json(Obj, "Secret", Secret);
|
||||
field_from_json(Obj, "OpenRoamingType", OpenRoamingType);
|
||||
field_from_json(Obj, "UseOpenRoamingAccount", UseOpenRoamingAccount);
|
||||
field_from_json(Obj, "Weight", Weight);
|
||||
field_from_json(Obj, "Certificate", Certificate);
|
||||
field_from_json(Obj, "PrivateKey", PrivateKey);
|
||||
field_from_json(Obj, "CaCerts", CaCerts);
|
||||
field_from_json(Obj, "AllowSelfSigned", AllowSelfSigned);
|
||||
return true;
|
||||
} catch (const Poco::Exception &E) {
|
||||
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void RADIUSEndPoint::to_json(Poco::JSON::Object &Obj) const {
|
||||
info.to_json(Obj);
|
||||
field_to_json(Obj, "Type", Type);
|
||||
field_to_json(Obj, "RadsecServers", RadsecServers);
|
||||
field_to_json(Obj, "RadiusServers", RadiusServers);
|
||||
field_to_json(Obj, "PoolStrategy", PoolStrategy);
|
||||
field_to_json(Obj, "Index", Index);
|
||||
field_to_json(Obj, "UsedBy", UsedBy);
|
||||
field_to_json(Obj, "UseGWProxy", UseGWProxy);
|
||||
field_to_json(Obj, "NasIdentifier", NasIdentifier);
|
||||
field_to_json(Obj, "AccountingInterval", AccountingInterval);
|
||||
}
|
||||
|
||||
bool RADIUSEndPoint::from_json(const Poco::JSON::Object::Ptr &Obj) {
|
||||
try {
|
||||
info.from_json(Obj);
|
||||
field_from_json(Obj, "Type", Type);
|
||||
field_from_json(Obj, "RadsecServers", RadsecServers);
|
||||
field_from_json(Obj, "RadiusServers", RadiusServers);
|
||||
field_from_json(Obj, "PoolStrategy", PoolStrategy);
|
||||
field_from_json(Obj, "Index", Index);
|
||||
field_from_json(Obj, "UsedBy", UsedBy);
|
||||
field_from_json(Obj, "UseGWProxy", UseGWProxy);
|
||||
field_from_json(Obj, "NasIdentifier", NasIdentifier);
|
||||
field_from_json(Obj, "AccountingInterval", AccountingInterval);
|
||||
return true;
|
||||
} catch (const Poco::Exception &E) {
|
||||
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void RADIUSEndpointUpdateStatus::to_json(Poco::JSON::Object &Obj) const {
|
||||
field_to_json(Obj, "lastUpdate", lastUpdate);
|
||||
field_to_json(Obj, "lastConfigurationChange", lastConfigurationChange);
|
||||
}
|
||||
|
||||
bool RADIUSEndpointUpdateStatus::from_json(const Poco::JSON::Object::Ptr &Obj) {
|
||||
try {
|
||||
field_from_json(Obj, "lastUpdate", lastUpdate);
|
||||
field_from_json(Obj, "lastConfigurationChange", lastConfigurationChange);
|
||||
return true;
|
||||
} catch (const Poco::Exception &E) {
|
||||
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool RADIUSEndpointUpdateStatus::Read() {
|
||||
Poco::File F(OpenWifi::MicroServiceDataDirectory()+"/RADIUSEndpointUpdateStatus.json");
|
||||
try {
|
||||
if (F.exists()) {
|
||||
Poco::JSON::Parser P;
|
||||
std::ifstream ifs(F.path(), std::ios_base::in | std::ios_base::binary);
|
||||
auto Obj = P.parse(ifs);
|
||||
return from_json(Obj.extract<Poco::JSON::Object::Ptr>());
|
||||
}
|
||||
} catch (...) {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool RADIUSEndpointUpdateStatus::Save() {
|
||||
Poco::File F(OpenWifi::MicroServiceDataDirectory()+"/RADIUSEndpointUpdateStatus.json");
|
||||
try {
|
||||
Poco::JSON::Object Obj;
|
||||
to_json(Obj);
|
||||
std::ofstream O(F.path(), std::ios_base::out | std::ios_base::trunc | std::ios_base::binary);
|
||||
Poco::JSON::Stringifier::stringify(Obj, O);
|
||||
return true;
|
||||
} catch (...) {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool RADIUSEndpointUpdateStatus::ChangeConfiguration() {
|
||||
Read();
|
||||
lastConfigurationChange = Utils::Now();
|
||||
return Save();
|
||||
}
|
||||
|
||||
} // namespace OpenWifi::ProvObjects
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -12,6 +12,8 @@
|
||||
#include "RESTAPI_SecurityObjects.h"
|
||||
#include "framework/RESTAPI_utils.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
using OpenWifi::RESTAPI_utils::field_from_json;
|
||||
using OpenWifi::RESTAPI_utils::field_to_json;
|
||||
|
||||
@@ -282,6 +284,7 @@ namespace OpenWifi::SecurityObjects {
|
||||
field_to_json(Obj, "oauthUserInfo", oauthUserInfo);
|
||||
field_to_json(Obj, "modified", modified);
|
||||
field_to_json(Obj, "signingUp", signingUp);
|
||||
Obj.set("userPermissions", permissions_to_json(userPermissions));
|
||||
};
|
||||
|
||||
bool UserInfo::from_json(const Poco::JSON::Object::Ptr &Obj) {
|
||||
@@ -318,6 +321,7 @@ namespace OpenWifi::SecurityObjects {
|
||||
field_from_json(Obj, "oauthUserInfo", oauthUserInfo);
|
||||
field_from_json(Obj, "modified", modified);
|
||||
field_from_json(Obj, "signingUp", signingUp);
|
||||
userPermissions = permissions_from_json(Obj->getObject("userPermissions"));
|
||||
return true;
|
||||
} catch (const Poco::Exception &E) {
|
||||
std::cout << "Cannot parse: UserInfo" << std::endl;
|
||||
@@ -737,4 +741,218 @@ namespace OpenWifi::SecurityObjects {
|
||||
return false;
|
||||
}
|
||||
|
||||
PERMISSION_TYPE PermTypeFromString(const std::string &U) {
|
||||
if (!Poco::icompare(U, "create"))
|
||||
return PT_CREATE;
|
||||
else if (!Poco::icompare(U, "update"))
|
||||
return PT_UPDATE;
|
||||
else if (!Poco::icompare(U, "delete"))
|
||||
return PT_DELETE;
|
||||
else if (!Poco::icompare(U, "readonly"))
|
||||
return PT_READ_ONLY;
|
||||
return PT_UNKNOWN;
|
||||
}
|
||||
|
||||
std::string PermTypeToString(PERMISSION_TYPE U) {
|
||||
switch (U) {
|
||||
case PT_CREATE:
|
||||
return "create";
|
||||
case PT_UPDATE:
|
||||
return "update";
|
||||
case PT_DELETE:
|
||||
return "delete";
|
||||
case PT_READ_ONLY:
|
||||
return "readonly";
|
||||
case PT_UNKNOWN:
|
||||
default:
|
||||
return "unknown";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
PERMISSION_MODEL PermModelFromString(const std::string &U) {
|
||||
if (!Poco::icompare(U, "permissions"))
|
||||
return PM_PERMISSIONS;
|
||||
else if (!Poco::icompare(U, "venues"))
|
||||
return PM_VENUES_PROV;
|
||||
else if (!Poco::icompare(U, "venues_list"))
|
||||
return PM_VENUES_LIST_PROV;
|
||||
else if (!Poco::icompare(U, "entities"))
|
||||
return PM_ENTITIES_PROV;
|
||||
else if (!Poco::icompare(U, "entities_list"))
|
||||
return PM_ENTITIES_LIST_PROV;
|
||||
else if (!Poco::icompare(U, "inventory"))
|
||||
return PM_INVENTORY_PROV;
|
||||
else if (!Poco::icompare(U, "inventory_list"))
|
||||
return PM_INVENTORY_LIST_PROV;
|
||||
else if (!Poco::icompare(U, "managementpolicy"))
|
||||
return PM_MANAGEMENTPOLICY_PROV;
|
||||
else if (!Poco::icompare(U, "managementpolicy_list"))
|
||||
return PM_MANAGEMENTPOLICY_LIST_PROV;
|
||||
else if (!Poco::icompare(U, "managementrole"))
|
||||
return PM_MANAGEMENTROLE_PROV;
|
||||
else if (!Poco::icompare(U, "managementrole_list"))
|
||||
return PM_MANAGEMENTROLE_LIST_PROV;
|
||||
//GW
|
||||
else if (!Poco::icompare(U, "scripts"))
|
||||
return PM_SCRIPTS_GW;
|
||||
else if (!Poco::icompare(U, "configure"))
|
||||
return PM_DEVICE_CONFIGURE_GW;
|
||||
else if (!Poco::icompare(U, "upgrade"))
|
||||
return PM_DEVICE_UPGRADE_GW;
|
||||
else if (!Poco::icompare(U, "factoryreset"))
|
||||
return PM_DEVICE_FACTORY_GW;
|
||||
else if (!Poco::icompare(U, "leds"))
|
||||
return PM_DEVICE_LEDS_GW;
|
||||
else if (!Poco::icompare(U, "trace"))
|
||||
return PM_DEVICE_TRACE_GW;
|
||||
else if (!Poco::icompare(U, "request"))
|
||||
return PM_DEVICE_REQUEST_GW;
|
||||
else if (!Poco::icompare(U, "wifiscan"))
|
||||
return PM_DEVICE_WIFISCAN_GW;
|
||||
else if (!Poco::icompare(U, "eventqueue"))
|
||||
return PM_DEVICE_EVENTQUEUE_GW;
|
||||
else if (!Poco::icompare(U, "telemetry"))
|
||||
return PM_DEVICE_TELEMETRY_GW;
|
||||
else if (!Poco::icompare(U, "ping"))
|
||||
return PM_DEVICE_PING_GW;
|
||||
else if (!Poco::icompare(U, "ap_script"))
|
||||
return PM_DEVICE_SCRIPT_GW;
|
||||
else if (!Poco::icompare(U, "rrm"))
|
||||
return PM_DEVICE_RRM_GW;
|
||||
else if (!Poco::icompare(U, "transfer"))
|
||||
return PM_DEVICE_TRANSFER_GW;
|
||||
else if (!Poco::icompare(U, "certupdate"))
|
||||
return PM_DEVICE_CERTUPDATE_GW;
|
||||
else if (!Poco::icompare(U, "powercycle"))
|
||||
return PM_DEVICE_POWERCYCLE_GW;
|
||||
else if (!Poco::icompare(U, "ap_logs"))
|
||||
return PM_DEVICE_LOGS_GW;
|
||||
else if (!Poco::icompare(U, "healthchecks"))
|
||||
return PM_DEVICE_HEALTHCHECKS_GW;
|
||||
else if (!Poco::icompare(U, "ap_capabilities"))
|
||||
return PM_DEVICE_CAPABILITIES_GW;
|
||||
else if (!Poco::icompare(U, "ap_statistics"))
|
||||
return PM_DEVICE_STATISTICS_GW;
|
||||
else if (!Poco::icompare(U, "ap_status"))
|
||||
return PM_DEVICE_STATUS_GW;
|
||||
else if (!Poco::icompare(U, "ap_rtty"))
|
||||
return PM_DEVICE_RTTY_GW;
|
||||
|
||||
return PM_UNKNOWN;
|
||||
}
|
||||
|
||||
std::string PermModelToString(PERMISSION_MODEL U) {
|
||||
switch (U) {
|
||||
case PM_PERMISSIONS:
|
||||
return "permissions";
|
||||
case PM_VENUES_PROV:
|
||||
return "venues";
|
||||
case PM_VENUES_LIST_PROV:
|
||||
return "venues_list";
|
||||
case PM_ENTITIES_PROV:
|
||||
return "entities";
|
||||
case PM_ENTITIES_LIST_PROV:
|
||||
return "entities_list";
|
||||
case PM_INVENTORY_PROV:
|
||||
return "inventory";
|
||||
case PM_INVENTORY_LIST_PROV:
|
||||
return "inventory_list";
|
||||
case PM_MANAGEMENTPOLICY_PROV:
|
||||
return "managementpolicy";
|
||||
case PM_MANAGEMENTPOLICY_LIST_PROV:
|
||||
return "managementpolicy_list";
|
||||
case PM_MANAGEMENTROLE_PROV:
|
||||
return "managementrole";
|
||||
case PM_MANAGEMENTROLE_LIST_PROV:
|
||||
return "managementrole_list";
|
||||
|
||||
//Gateway
|
||||
case PM_SCRIPTS_GW:
|
||||
return "scripts";
|
||||
case PM_DEVICE_CONFIGURE_GW:
|
||||
return "configure";
|
||||
case PM_DEVICE_UPGRADE_GW:
|
||||
return "upgrade";
|
||||
case PM_DEVICE_FACTORY_GW:
|
||||
return "factoryreset";
|
||||
case PM_DEVICE_LEDS_GW:
|
||||
return "leds";
|
||||
case PM_DEVICE_TRACE_GW:
|
||||
return "trace";
|
||||
case PM_DEVICE_REQUEST_GW:
|
||||
return "request";
|
||||
case PM_DEVICE_WIFISCAN_GW:
|
||||
return "wifiscan";
|
||||
case PM_DEVICE_EVENTQUEUE_GW:
|
||||
return "eventqueue";
|
||||
case PM_DEVICE_TELEMETRY_GW:
|
||||
return "telemetry";
|
||||
case PM_DEVICE_PING_GW:
|
||||
return "ping";
|
||||
case PM_DEVICE_SCRIPT_GW:
|
||||
return "ap_script";
|
||||
case PM_DEVICE_RRM_GW:
|
||||
return "rrm";
|
||||
case PM_DEVICE_TRANSFER_GW:
|
||||
return "transfer";
|
||||
case PM_DEVICE_CERTUPDATE_GW:
|
||||
return "certupdate";
|
||||
case PM_DEVICE_POWERCYCLE_GW:
|
||||
return "powercycle";
|
||||
case PM_DEVICE_LOGS_GW:
|
||||
return "ap_logs";
|
||||
case PM_DEVICE_HEALTHCHECKS_GW:
|
||||
return "healthchecks";
|
||||
case PM_DEVICE_CAPABILITIES_GW:
|
||||
return "ap_capabilities";
|
||||
case PM_DEVICE_STATISTICS_GW:
|
||||
return "ap_statistics";
|
||||
case PM_DEVICE_STATUS_GW:
|
||||
return "ap_status";
|
||||
case PM_DEVICE_RTTY_GW:
|
||||
return "ap_rtty";
|
||||
case PM_UNKNOWN:
|
||||
default:
|
||||
return "unknown";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert PermissionMap into a JSON object and return it
|
||||
*/
|
||||
Poco::JSON::Object permissions_to_json(const PermissionMap &Map) {
|
||||
Poco::JSON::Object MapObj;
|
||||
for (auto &[Model, Permissions] : Map) {
|
||||
Poco::JSON::Object ModelObject;
|
||||
for (auto &[Permission, Allowed] : Permissions) {
|
||||
ModelObject.set(PermTypeToString(Permission), Allowed);
|
||||
}
|
||||
MapObj.set(PermModelToString(Model), ModelObject);
|
||||
}
|
||||
return MapObj;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert JSON object into a PermissionMap and return it
|
||||
*/
|
||||
PermissionMap permissions_from_json(const Poco::JSON::Object::Ptr &Obj) {
|
||||
PermissionMap permissions;
|
||||
if (Obj == nullptr) {
|
||||
return permissions;
|
||||
}
|
||||
Poco::JSON::Object::ConstIterator it1;
|
||||
for(it1 = Obj->begin(); it1 != Obj->end(); it1++) {
|
||||
std::string model = it1->first;
|
||||
Poco::JSON::Object::Ptr modelObj = it1->second.extract<Poco::JSON::Object::Ptr>();
|
||||
Poco::JSON::Object::ConstIterator it2;
|
||||
for(it2 = modelObj->begin(); it2 != modelObj->end(); it2++) {
|
||||
std::string permission = it2->first;
|
||||
bool allowed = it2->second;
|
||||
permissions[PermModelFromString(model)]
|
||||
[PermTypeFromString(permission)] = allowed;
|
||||
}
|
||||
}
|
||||
return permissions;
|
||||
}
|
||||
} // namespace OpenWifi::SecurityObjects
|
||||
|
||||
@@ -11,10 +11,15 @@
|
||||
#include "Poco/Data/LOB.h"
|
||||
#include "Poco/Data/LOBStream.h"
|
||||
#include "Poco/JSON/Object.h"
|
||||
#include "Poco/Net/HTTPRequest.h"
|
||||
#include "framework/OpenWifiTypes.h"
|
||||
#include "framework/utils.h"
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <map>
|
||||
#include <set>
|
||||
|
||||
namespace OpenWifi {
|
||||
uint64_t Now();
|
||||
@@ -55,6 +60,10 @@ namespace OpenWifi {
|
||||
bool from_json(const Poco::JSON::Object::Ptr &Obj);
|
||||
};
|
||||
|
||||
// example entry {"/api/v1/device", {Poco::Net::HTTPRequest::HTTP_POST, Poco::Net::HTTPRequest::HTTP_PUT, Poco::Net::HTTPRequest::HTTP_DELETE}}
|
||||
const std::map<std::string, std::set<std::string>> API_WHITELIST = {
|
||||
};
|
||||
|
||||
enum USER_ROLE {
|
||||
UNKNOWN,
|
||||
ROOT,
|
||||
@@ -125,6 +134,72 @@ namespace OpenWifi {
|
||||
bool from_json(const Poco::JSON::Object::Ptr &Obj);
|
||||
};
|
||||
|
||||
// Represents particular permissions, i.e. what are you doing do the model
|
||||
enum PERMISSION_TYPE {
|
||||
PT_CREATE,
|
||||
PT_DELETE,
|
||||
PT_UPDATE,
|
||||
PT_READ_ONLY,
|
||||
PT_UNKNOWN
|
||||
};
|
||||
PERMISSION_TYPE PermTypeFromString(const std::string &U);
|
||||
std::string PermTypeToString(PERMISSION_TYPE U);
|
||||
|
||||
// Represents a model that can be operated on
|
||||
enum PERMISSION_MODEL {
|
||||
//Security
|
||||
PM_PERMISSIONS,
|
||||
|
||||
//Provisioning
|
||||
PM_VENUES_PROV,
|
||||
PM_VENUES_LIST_PROV,
|
||||
PM_ENTITIES_PROV,
|
||||
PM_ENTITIES_LIST_PROV,
|
||||
PM_INVENTORY_PROV,
|
||||
PM_INVENTORY_LIST_PROV,
|
||||
PM_MANAGEMENTPOLICY_PROV,
|
||||
PM_MANAGEMENTPOLICY_LIST_PROV,
|
||||
PM_MANAGEMENTROLE_PROV,
|
||||
PM_MANAGEMENTROLE_LIST_PROV,
|
||||
|
||||
//Gateway
|
||||
PM_DEVICE_CONFIGURE_GW,
|
||||
PM_DEVICE_UPGRADE_GW,
|
||||
PM_DEVICE_REBOOT_GW,
|
||||
PM_DEVICE_FACTORY_GW,
|
||||
PM_DEVICE_LEDS_GW,
|
||||
PM_DEVICE_TRACE_GW,
|
||||
PM_DEVICE_REQUEST_GW,
|
||||
PM_DEVICE_WIFISCAN_GW,
|
||||
PM_DEVICE_EVENTQUEUE_GW,
|
||||
PM_DEVICE_TELEMETRY_GW,
|
||||
PM_DEVICE_PING_GW,
|
||||
PM_DEVICE_SCRIPT_GW,
|
||||
PM_DEVICE_RRM_GW,
|
||||
PM_DEVICE_TRANSFER_GW,
|
||||
PM_DEVICE_CERTUPDATE_GW,
|
||||
PM_DEVICE_POWERCYCLE_GW,
|
||||
PM_DEVICE_LOGS_GW,
|
||||
PM_DEVICE_HEALTHCHECKS_GW,
|
||||
PM_DEVICE_CAPABILITIES_GW,
|
||||
PM_DEVICE_STATISTICS_GW,
|
||||
PM_DEVICE_STATUS_GW,
|
||||
PM_DEVICE_RTTY_GW,
|
||||
|
||||
PM_SCRIPTS_GW,
|
||||
|
||||
PM_UNKNOWN
|
||||
};
|
||||
PERMISSION_MODEL PermModelFromString(const std::string &U);
|
||||
std::string PermModelToString(PERMISSION_MODEL U);
|
||||
|
||||
// Map a permission (e.g. create, delete) to true/false
|
||||
typedef std::map<PERMISSION_TYPE, bool> ModelPermissionMap;
|
||||
// Map a model (e.g. venues, devices) to permissions
|
||||
typedef std::map<PERMISSION_MODEL, ModelPermissionMap> PermissionMap;
|
||||
Poco::JSON::Object permissions_to_json(const SecurityObjects::PermissionMap &Map);
|
||||
PermissionMap permissions_from_json(const Poco::JSON::Object::Ptr &Obj);
|
||||
|
||||
struct UserInfo {
|
||||
std::string id;
|
||||
std::string name;
|
||||
@@ -149,6 +224,7 @@ namespace OpenWifi {
|
||||
bool suspended = false;
|
||||
bool blackListed = false;
|
||||
USER_ROLE userRole;
|
||||
PermissionMap userPermissions;
|
||||
UserLoginLoginExtensions userTypeProprietaryInfo;
|
||||
std::string securityPolicy;
|
||||
uint64_t securityPolicyChange = 0;
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <fstream>
|
||||
#include <shared_mutex>
|
||||
#include <mutex>
|
||||
|
||||
#include "framework/MicroServiceFuncs.h"
|
||||
#include "framework/SubSystemServer.h"
|
||||
@@ -38,7 +38,7 @@ namespace OpenWifi {
|
||||
inline int Start() final {
|
||||
poco_notice(Logger(), "Starting...");
|
||||
|
||||
std::shared_lock L(KeyMutex_);
|
||||
std::lock_guard L(KeyMutex_);
|
||||
|
||||
CacheFilename_ = MicroServiceDataDirectory() + "/signature_cache";
|
||||
Poco::File CacheFile(CacheFilename_);
|
||||
@@ -91,7 +91,7 @@ namespace OpenWifi {
|
||||
|
||||
inline std::string Sign(const GWObjects::DeviceRestrictions &Restrictions,
|
||||
const std::string &Data) const {
|
||||
std::shared_lock L(KeyMutex_);
|
||||
std::lock_guard L(KeyMutex_);
|
||||
try {
|
||||
if (Restrictions.key_info.algo == "static") {
|
||||
return "aaaaaaaaaa";
|
||||
@@ -120,7 +120,7 @@ namespace OpenWifi {
|
||||
|
||||
inline std::string Sign(const GWObjects::DeviceRestrictions &Restrictions,
|
||||
const Poco::URI &uri) {
|
||||
std::shared_lock L(KeyMutex_);
|
||||
std::lock_guard L(KeyMutex_);
|
||||
try {
|
||||
if (Restrictions.key_info.algo == "static") {
|
||||
return "aaaaaaaaaa";
|
||||
@@ -172,7 +172,7 @@ namespace OpenWifi {
|
||||
}
|
||||
|
||||
private:
|
||||
mutable std::shared_mutex KeyMutex_;
|
||||
mutable std::mutex KeyMutex_;
|
||||
std::map<std::string, Poco::SharedPtr<Poco::Crypto::RSAKey>> Keys_;
|
||||
std::map<std::string, std::string> SignatureCache_;
|
||||
std::string CacheFilename_;
|
||||
|
||||
@@ -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 includeProvisioned = true);
|
||||
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,10 +203,24 @@ 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);
|
||||
|
||||
bool UpdateDefaultFirmware(GWObjects::DefaultFirmware &DefFirmware);
|
||||
bool CreateDefaultFirmware(GWObjects::DefaultFirmware &DefConfig);
|
||||
bool DeleteDefaultFirmware(std::string &name);
|
||||
bool GetDefaultFirmware(std::string &name, GWObjects::DefaultFirmware &DefConfig);
|
||||
bool GetDefaultFirmwares(uint64_t From, uint64_t HowMany,
|
||||
std::vector<GWObjects::DefaultFirmware> &Devices);
|
||||
bool FindDefaultFirmwareForModel(const std::string &Model,
|
||||
GWObjects::DefaultFirmware &DefConfig);
|
||||
uint64_t GetDefaultFirmwaresCount();
|
||||
bool DefaultFirmwareAlreadyExists(std::string &Name);
|
||||
|
||||
|
||||
|
||||
bool AddCommand(std::string &SerialNumber, GWObjects::CommandDetails &Command,
|
||||
CommandExecutionType Type);
|
||||
bool GetCommands(std::string &SerialNumber, uint64_t FromDate, uint64_t ToDate,
|
||||
@@ -197,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,
|
||||
@@ -209,28 +255,32 @@ 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);
|
||||
bool UpdateBlackListDevice(std::string &SerialNumber, GWObjects::BlackListedDevice &Device);
|
||||
uint64_t GetBlackListDeviceCount();
|
||||
|
||||
bool DeleteSimulatedDevice(const std::string &SerialNumber);
|
||||
|
||||
bool RemoveHealthChecksRecordsOlderThan(uint64_t Date);
|
||||
bool RemoveDeviceLogsRecordsOlderThan(uint64_t Date);
|
||||
bool RemoveStatisticsRecordsOlderThan(uint64_t Date);
|
||||
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();
|
||||
@@ -242,17 +292,29 @@ namespace OpenWifi {
|
||||
int Create_CommandList();
|
||||
int Create_BlackList();
|
||||
int Create_FileUploads();
|
||||
int Create_DefaultFirmwares();
|
||||
|
||||
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
|
||||
|
||||
@@ -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 {
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user