mirror of
https://github.com/Telecominfraproject/wlan-cloud-ucentralgw.git
synced 2025-11-02 11:47:47 +00:00
Compare commits
289 Commits
gh-pages
...
release/v2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
70299b0238 | ||
|
|
3101cb1205 | ||
|
|
cb5613ce7f | ||
|
|
45b25c4e75 | ||
|
|
ea311f70a0 | ||
|
|
e3265c86a5 | ||
|
|
e537259208 | ||
|
|
b9c7990344 | ||
|
|
d5c1cfe2f1 | ||
|
|
1a4f27cbbf | ||
|
|
11ad381534 | ||
|
|
0b548a40f3 | ||
|
|
28e5463196 | ||
|
|
37ea632ac7 | ||
|
|
2f641077e6 | ||
|
|
78318f47c6 | ||
|
|
c83c73a3ae | ||
|
|
6305be8c55 | ||
|
|
4b325ef22c | ||
|
|
a422dff7ae | ||
|
|
271ff4f6c4 | ||
|
|
4cdd275d0b | ||
|
|
9a36e86949 | ||
|
|
fa806ed16c | ||
|
|
57c270973e | ||
|
|
17ebfb24f2 | ||
|
|
26072691ab | ||
|
|
e8b3ea56e0 | ||
|
|
2b1a72b838 | ||
|
|
352afc487a | ||
|
|
6fae29981a | ||
|
|
9569de1b21 | ||
|
|
1a952946b2 | ||
|
|
3b52cf6111 | ||
|
|
74197e2aee | ||
|
|
7152067b09 | ||
|
|
ac3d061eee | ||
|
|
8ee67713bf | ||
|
|
e57cd4fea2 | ||
|
|
5e3a71a6e7 | ||
|
|
a602b8f844 | ||
|
|
89da7d187a | ||
|
|
6c5533aa8b | ||
|
|
66249b258c | ||
|
|
e03512ebf3 | ||
|
|
b152c8477a | ||
|
|
a298c4254b | ||
|
|
b8f04c6d4a | ||
|
|
753dc5c068 | ||
|
|
bf70d6b512 | ||
|
|
760f11ca70 | ||
|
|
2bcd0ccbcb | ||
|
|
0aee258af4 | ||
|
|
9e879f306c | ||
|
|
fb4a4d935a | ||
|
|
282552cdfa | ||
|
|
1d316ff28a | ||
|
|
1da866a7da | ||
|
|
1c628c28fa | ||
|
|
a350b30a9c | ||
|
|
cf6c3f9337 | ||
|
|
2388eac41d | ||
|
|
f0e0f2ba5b | ||
|
|
0c8b9caaf3 | ||
|
|
c0edeb8b23 | ||
|
|
fdcf74788d | ||
|
|
df9c82a4ae | ||
|
|
2963cec1fb | ||
|
|
8053e32c9c | ||
|
|
1750ac5fb5 | ||
|
|
b4d775db0c | ||
|
|
3031483209 | ||
|
|
97b990581d | ||
|
|
98fa4799cc | ||
|
|
95a853fc0e | ||
|
|
7a14cadbf5 | ||
|
|
ab5efcc8c1 | ||
|
|
bb71ff2bad | ||
|
|
c1a2efd32c | ||
|
|
ca4d92fd66 | ||
|
|
efb354031a | ||
|
|
180d01c89d | ||
|
|
f6c1a5e97f | ||
|
|
54e7caafc1 | ||
|
|
e76c97540c | ||
|
|
3f01ef6d5e | ||
|
|
8e118c7f7b | ||
|
|
6dc5622bf2 | ||
|
|
27a9ef01b6 | ||
|
|
9390b9a646 | ||
|
|
871f3c3436 | ||
|
|
a41095a797 | ||
|
|
bb94c9a813 | ||
|
|
fcd991b8d6 | ||
|
|
2df43cfd62 | ||
|
|
014aafbd3d | ||
|
|
d1d058a848 | ||
|
|
d492396182 | ||
|
|
2c710412a1 | ||
|
|
7dcade3d79 | ||
|
|
dc73a2d54b | ||
|
|
6c2bb5b395 | ||
|
|
fccf99cca5 | ||
|
|
0d91dd9a6e | ||
|
|
d84af0f18e | ||
|
|
6b6c9ce0ae | ||
|
|
5a31d6427f | ||
|
|
8b3ff4a560 | ||
|
|
53c81d2c76 | ||
|
|
518bfc0b2c | ||
|
|
c6851819d4 | ||
|
|
d5851753c2 | ||
|
|
379b1446f6 | ||
|
|
86a254e1b3 | ||
|
|
de260ecddc | ||
|
|
6d50ef72b7 | ||
|
|
f0954081c1 | ||
|
|
9653d0affb | ||
|
|
dd626461e8 | ||
|
|
048b33e134 | ||
|
|
eff7a70f6b | ||
|
|
5f73966010 | ||
|
|
911c9ac210 | ||
|
|
f59c369b61 | ||
|
|
526d239fe9 | ||
|
|
939d704460 | ||
|
|
b7e8da5e76 | ||
|
|
ad20736a14 | ||
|
|
c5d68e5397 | ||
|
|
a2bbe71e53 | ||
|
|
1c0cf65145 | ||
|
|
60d41e8569 | ||
|
|
76698476b6 | ||
|
|
4e4ac89401 | ||
|
|
e3e6a27348 | ||
|
|
b419472fd7 | ||
|
|
8f43f5945d | ||
|
|
bd2af4df1d | ||
|
|
bbbb4cd4fe | ||
|
|
445568152c | ||
|
|
ce70ff0f21 | ||
|
|
6dbf16793e | ||
|
|
eba69c8c35 | ||
|
|
ae2e6c5ce6 | ||
|
|
5a2a0cd074 | ||
|
|
9c3a23a8a1 | ||
|
|
b6f0f07bec | ||
|
|
e060e11cd2 | ||
|
|
883245de68 | ||
|
|
9cfc411a51 | ||
|
|
fb3a785227 | ||
|
|
3fe8958323 | ||
|
|
117f0e1637 | ||
|
|
b09b1d5690 | ||
|
|
e073e2b713 | ||
|
|
8343443bd7 | ||
|
|
c5ed66c40c | ||
|
|
de65b2396c | ||
|
|
c85cef57c8 | ||
|
|
6c9bae518a | ||
|
|
7232168037 | ||
|
|
9da06d8384 | ||
|
|
296a4721db | ||
|
|
f2badf7b6d | ||
|
|
766be1aa3c | ||
|
|
4812219e0d | ||
|
|
7b4e39aad2 | ||
|
|
fbff951e22 | ||
|
|
09198d5ec2 | ||
|
|
3666995f7f | ||
|
|
0572674279 | ||
|
|
19f2265161 | ||
|
|
f613449dff | ||
|
|
a1291b1b16 | ||
|
|
39ebc28396 | ||
|
|
6017714363 | ||
|
|
bff7092ce1 | ||
|
|
1741742617 | ||
|
|
b4a6bea1b4 | ||
|
|
57e06b2d2f | ||
|
|
0bc7363dae | ||
|
|
44b2140230 | ||
|
|
49bc934066 | ||
|
|
53d337f462 | ||
|
|
66e7791b95 | ||
|
|
2180c5ff23 | ||
|
|
2f4fa7572e | ||
|
|
5923506237 | ||
|
|
b9600654f8 | ||
|
|
6b0a082ac9 | ||
|
|
c5a108d672 | ||
|
|
23c2925baf | ||
|
|
fa4c72d59c | ||
|
|
d66d901204 | ||
|
|
b09eaf98cc | ||
|
|
7f9bf85958 | ||
|
|
d1d89fcd74 | ||
|
|
bc3f5700d4 | ||
|
|
3a938fd615 | ||
|
|
dc3729aec2 | ||
|
|
dd214ae5d1 | ||
|
|
8f7f8c5736 | ||
|
|
00701a8de4 | ||
|
|
fc41c9aa2f | ||
|
|
a5442eee0d | ||
|
|
9dcf5b5320 | ||
|
|
28b5295a6e | ||
|
|
8261ae34bd | ||
|
|
02baa9329c | ||
|
|
7f01c7b861 | ||
|
|
8d0f0c227a | ||
|
|
c8170bc9f3 | ||
|
|
83003b66b9 | ||
|
|
cbdb15bc32 | ||
|
|
712e15407d | ||
|
|
e424e19d1c | ||
|
|
546d8dee98 | ||
|
|
60b9fc679a | ||
|
|
79a4f24bc2 | ||
|
|
02b8ecf300 | ||
|
|
bdbc5a7a9d | ||
|
|
680fe18bac | ||
|
|
dd08b2e426 | ||
|
|
285b1630ee | ||
|
|
fdcaf9054f | ||
|
|
65b5585797 | ||
|
|
b31fdb202c | ||
|
|
d13d906d11 | ||
|
|
6a403ac916 | ||
|
|
eff54e3202 | ||
|
|
0a7dd7c3f7 | ||
|
|
cf7f962ed1 | ||
|
|
f412df29b5 | ||
|
|
31204bae6a | ||
|
|
a57cf08c00 | ||
|
|
c0171156fa | ||
|
|
a456e95139 | ||
|
|
7f8e2d0f7f | ||
|
|
d80aa68c40 | ||
|
|
81c9090ec9 | ||
|
|
0fa5c46f4b | ||
|
|
d75977140a | ||
|
|
b65440ba4e | ||
|
|
ee15f8b8c2 | ||
|
|
aebf8ba783 | ||
|
|
9f2436b123 | ||
|
|
cd774ea2df | ||
|
|
007f54bc26 | ||
|
|
9c03f3a9e3 | ||
|
|
292365a837 | ||
|
|
1091478e11 | ||
|
|
47b94b3c5a | ||
|
|
7cd62e7b26 | ||
|
|
3397f2407a | ||
|
|
52799659c8 | ||
|
|
86e88942b0 | ||
|
|
11592ebb98 | ||
|
|
83f4bfc53d | ||
|
|
43ed818015 | ||
|
|
fd7f5b991a | ||
|
|
feebcb339a | ||
|
|
0368d4e435 | ||
|
|
a57bad5bb9 | ||
|
|
1ef20f232a | ||
|
|
78deaf8b38 | ||
|
|
a1aec29ffd | ||
|
|
07dc8617a4 | ||
|
|
34cef1ae0a | ||
|
|
144841d88d | ||
|
|
b46a713968 | ||
|
|
4ec7c30e28 | ||
|
|
16c5825e3a | ||
|
|
0f1129e51e | ||
|
|
3e54201be8 | ||
|
|
c34fba4c22 | ||
|
|
625f8c7a2b | ||
|
|
41a4a98c0a | ||
|
|
c858d954a9 | ||
|
|
aa0410edb3 | ||
|
|
97cb61b7cf | ||
|
|
0408d98538 | ||
|
|
69e2f9640e | ||
|
|
efd20dc370 | ||
|
|
7a42598150 | ||
|
|
7a45d96d9a | ||
|
|
a4f7ccdba1 | ||
|
|
a0b47aa4b3 | ||
|
|
ee6dd54ab3 | ||
|
|
518ca7cc9d |
1
.github/workflows/openapi-pages.yml
vendored
1
.github/workflows/openapi-pages.yml
vendored
@@ -34,6 +34,7 @@ jobs:
|
||||
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'
|
||||
|
||||
@@ -165,10 +165,6 @@ add_executable( owgw
|
||||
src/CapabilitiesCache.h src/FindCountry.h
|
||||
src/rttys/RTTYS_server.cpp
|
||||
src/rttys/RTTYS_server.h
|
||||
src/rttys/RTTYS_device.cpp
|
||||
src/rttys/RTTYS_device.h
|
||||
src/rttys/RTTYS_ClientConnection.cpp
|
||||
src/rttys/RTTYS_ClientConnection.h
|
||||
src/rttys/RTTYS_WebServer.cpp
|
||||
src/rttys/RTTYS_WebServer.h src/RESTAPI/RESTAPI_device_helper.h
|
||||
src/SDKcalls.cpp
|
||||
@@ -199,7 +195,7 @@ add_executable( owgw
|
||||
src/AP_WS_Process_telemetry.cpp
|
||||
src/AP_WS_Process_venuebroadcast.cpp
|
||||
src/RADSEC_server.h
|
||||
src/UI_GW_WebSocketNotifications.cpp src/UI_GW_WebSocketNotifications.h src/framework/RESTAPI_SystemConfiguration.h src/AP_restrictions.h)
|
||||
src/UI_GW_WebSocketNotifications.cpp src/UI_GW_WebSocketNotifications.h src/framework/RESTAPI_SystemConfiguration.h src/ScriptManager.cpp src/ScriptManager.h src/RESTAPI/RESTAPI_scripts_handler.cpp src/RESTAPI/RESTAPI_scripts_handler.h src/RESTAPI/RESTAPI_script_handler.cpp src/RESTAPI/RESTAPI_script_handler.h src/storage/storage_scripts.cpp src/storage/storage_scripts.h src/SignatureMgr.cpp src/SignatureMgr.h)
|
||||
|
||||
if(NOT SMALL_BUILD)
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
ARG DEBIAN_VERSION=11.5-slim
|
||||
ARG POCO_VERSION=poco-tip-v1
|
||||
ARG POCO_VERSION=poco-tip-v2
|
||||
ARG CPPKAFKA_VERSION=tip-v1
|
||||
ARG JSON_VALIDATOR_VERSION=2.1.0
|
||||
|
||||
|
||||
82
RESTRICTED_DEVICES.md
Normal file
82
RESTRICTED_DEVICES.md
Normal file
@@ -0,0 +1,82 @@
|
||||
# Restricted devices
|
||||
|
||||
## What is a restricted device?
|
||||
A restricted device is one that because of regulations or a desire for utmost security, requires signatures to access restricted or blocked
|
||||
features. The restriction process is burnt in the device at manufacturing or later by running a specific command on the device. Once a device
|
||||
is restricted, it cannot be unlocked.
|
||||
|
||||
## Current restrictions
|
||||
Restrictions are stored on the AP in a protected partition. They are contained in a file called `restrictions.json`. Here is a sample:
|
||||
```json
|
||||
{
|
||||
"country": [
|
||||
"US", "CA"
|
||||
],
|
||||
"dfs": true,
|
||||
"rtty": true,
|
||||
"tty": true,
|
||||
"developer": true,
|
||||
"sysupgrade": true,
|
||||
"commands": true,
|
||||
"key_info": {
|
||||
"vendor": "dummy",
|
||||
"algo": "static"
|
||||
}
|
||||
}
|
||||
```
|
||||
- country
|
||||
- List of countries where this device may be used
|
||||
- dfs
|
||||
- Disallow DFS Override during wifi-scan. If set to `true`, device will not allow to override DFS channels
|
||||
- rtty
|
||||
- Disallow the use of the RTTY command for this device
|
||||
- tty
|
||||
- Do not allow the AP to accept `tty` connection
|
||||
- developer
|
||||
- Internal use only.
|
||||
- sysupgrade
|
||||
- If set to `true`, only signed firmware upgrade command will be allowed.
|
||||
- commands
|
||||
- If set to `true`, do not allow commands.
|
||||
- key_info
|
||||
- This structure defines how signatures should be generated and verified in a secure system
|
||||
- vendor
|
||||
- An identified that must match the vendor name provided in the controller
|
||||
- algo
|
||||
- The signature algorithm. Here are the supported algorithms
|
||||
- `static`
|
||||
- A test algorithm that always returns and uses a value of `aaaaaaaaaa`. This should never be used in the field.
|
||||
- `dgst-sha256`
|
||||
- The default OpenSSL RSA signature generation and verification. The controller will use the following command to generate the signature
|
||||
```sh
|
||||
openssl dgst -sha256 -sign private-key.pem -out signature.txt myfile
|
||||
```
|
||||
- The AP will be using the following to verify the signature
|
||||
```sh
|
||||
openssl dgst -sha256 -verify public-key.pem -signature signature.txt myfile
|
||||
```
|
||||
|
||||
## Creating signatures on the controller
|
||||
When a device is restricted and a signature is required, the controller can generate the signature
|
||||
for the specified `vendor`. However, on the controlelr side, you must configure the vendors. In
|
||||
order to do so we suggest the following.
|
||||
- Create a directory called `signatures` under your `certs` directory
|
||||
- Copy the public and private keys for each `vendor` name. We suggest naming them accordingly
|
||||
- `vendor`-private-key.pem
|
||||
- `vendor`-public-key.pem
|
||||
- In the `owgw.properties` file, you need to declare these signatures the following way
|
||||
```properties
|
||||
signature.manager.0.key.public = $OWGW_ROOT/certs/signatures/test1-public-key.pem
|
||||
signature.manager.0.key.private = $OWGW_ROOT/certs/signatures/test1-private-key.pem
|
||||
signature.manager.0.vendor = test1
|
||||
|
||||
signature.manager.1.key.public = $OWGW_ROOT/certs/signatures/test2-public-key.pem
|
||||
signature.manager.1.key.private = $OWGW_ROOT/certs/signatures/test2-private-key.pem
|
||||
signature.manager.1.vendor = test2
|
||||
```
|
||||
|
||||
## How do you use the signatures?
|
||||
There is nothing to do really. Now the controller will use the proper key to create the signatures
|
||||
when it sends commands to the AP. It will use the algorithm that the device understands too. This is transparent
|
||||
to the user. The `vendor` name used in the controller configuration must match the `vendor` name provided in the
|
||||
`restrictions.json` file.
|
||||
@@ -73,6 +73,7 @@ if [[ "$TEMPLATE_CONFIG" = 'true' ]]; then
|
||||
STORAGE_TYPE_MYSQL_PASSWORD=${STORAGE_TYPE_MYSQL_PASSWORD:-"owgw"} \
|
||||
STORAGE_TYPE_MYSQL_DATABASE=${STORAGE_TYPE_MYSQL_DATABASE:-"owgw"} \
|
||||
STORAGE_TYPE_MYSQL_PORT=${STORAGE_TYPE_MYSQL_PORT:-"3306"} \
|
||||
CERTIFICATES_ALLOWMISMATCH=${CERTIFICATES_ALLOWMISMATCH:-"false"} \
|
||||
envsubst < /owgw.properties.tmpl > $OWGW_CONFIG/owgw.properties
|
||||
fi
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ fullnameOverride: ""
|
||||
images:
|
||||
owgw:
|
||||
repository: tip-tip-wlan-cloud-ucentral.jfrog.io/owgw
|
||||
tag: master
|
||||
tag: v2.8.0
|
||||
pullPolicy: Always
|
||||
# regcred:
|
||||
# registry: tip-tip-wlan-cloud-ucentral.jfrog.io
|
||||
@@ -230,6 +230,7 @@ configProperties:
|
||||
openwifi.devicetypes.0: AP:linksys_ea8300,edgecore_eap101,linksys_e8450-ubi
|
||||
openwifi.devicetypes.1: SWITCH:edgecore_ecs4100-12ph
|
||||
openwifi.devicetypes.2: IOT:esp32
|
||||
openwifi.certificates.allowmismatch: "false"
|
||||
oui.download.uri: https://standards-oui.ieee.org/oui/oui.txt
|
||||
firmware.autoupdate.policy.default: auto
|
||||
iptocountry.provider: ipinfo
|
||||
|
||||
@@ -49,6 +49,38 @@ components:
|
||||
- IOT
|
||||
- MESH
|
||||
|
||||
DeviceRestrictionsKeyInfo:
|
||||
type: object
|
||||
properties:
|
||||
vendor:
|
||||
type: string
|
||||
algo:
|
||||
type: string
|
||||
|
||||
DeviceRestrictions:
|
||||
type: object
|
||||
properties:
|
||||
dfs:
|
||||
type: boolean
|
||||
ssh:
|
||||
type: boolean
|
||||
rtty:
|
||||
type: boolean
|
||||
tty:
|
||||
type: boolean
|
||||
developer:
|
||||
type: boolean
|
||||
upgrade:
|
||||
type: boolean
|
||||
commands:
|
||||
type: boolean
|
||||
country:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
key_info:
|
||||
$ref: '#/components/schemas/DeviceRestrictionsKeyInfo'
|
||||
|
||||
Device:
|
||||
type: object
|
||||
description: Definition of uCentral device
|
||||
@@ -107,12 +139,19 @@ components:
|
||||
type: string
|
||||
minLength: 2
|
||||
maxLength: 2
|
||||
FCC:
|
||||
restrictedDevice:
|
||||
type: boolean
|
||||
default: false
|
||||
certificateExpiryDate:
|
||||
type: integer
|
||||
format: int64
|
||||
pendingConfiguration:
|
||||
type: string
|
||||
pendingConfigurationCmd:
|
||||
type: string
|
||||
format: uuid
|
||||
restrictionDetails:
|
||||
$ref: '#/components/schemas/DeviceRestrictions'
|
||||
|
||||
DeviceWithStatus:
|
||||
type: object
|
||||
@@ -214,6 +253,13 @@ components:
|
||||
certificateDate:
|
||||
type: integer
|
||||
format: int64
|
||||
pendingConfiguration:
|
||||
type: string
|
||||
pendingConfigurationCmd:
|
||||
type: string
|
||||
format: uuid
|
||||
restrictionDetails:
|
||||
$ref: '#/components/schemas/DeviceRestrictions'
|
||||
|
||||
DeviceList:
|
||||
type: object
|
||||
@@ -514,8 +560,11 @@ components:
|
||||
enum:
|
||||
- shell
|
||||
- bundle
|
||||
- diagnostic
|
||||
script:
|
||||
type: string
|
||||
scriptId:
|
||||
type: string
|
||||
when:
|
||||
type: integer
|
||||
format: int64
|
||||
@@ -527,6 +576,52 @@ components:
|
||||
uri:
|
||||
type: string
|
||||
|
||||
ScriptEntry:
|
||||
type: object
|
||||
properties:
|
||||
id:
|
||||
type: string
|
||||
name:
|
||||
type: string
|
||||
description:
|
||||
type: string
|
||||
uri:
|
||||
type: string
|
||||
content:
|
||||
type: string
|
||||
version:
|
||||
type: string
|
||||
type:
|
||||
enum:
|
||||
- shell
|
||||
- bundle
|
||||
created:
|
||||
type: integer
|
||||
modified:
|
||||
type: integer
|
||||
author:
|
||||
type: string
|
||||
restricted:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
deferred:
|
||||
type: boolean
|
||||
default: false
|
||||
timeout:
|
||||
type: integer
|
||||
default: 30
|
||||
defaultUploadURI:
|
||||
type: string
|
||||
|
||||
ScriptEntryList:
|
||||
type: object
|
||||
properties:
|
||||
scripts:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/ScriptEntry'
|
||||
|
||||
FactoryRequest:
|
||||
type: object
|
||||
properties:
|
||||
@@ -2474,6 +2569,148 @@ paths:
|
||||
404:
|
||||
$ref: '#/components/responses/NotFound'
|
||||
|
||||
/scripts:
|
||||
get:
|
||||
tags:
|
||||
- Scripting
|
||||
summary: Returns a list scripts.
|
||||
description: Get a list of scripts.
|
||||
operationId: getScripts
|
||||
parameters:
|
||||
- in: query
|
||||
description: Pagination start (starts at 0. If not specified, 0 is assumed)
|
||||
name: offset
|
||||
schema:
|
||||
type: integer
|
||||
required: false
|
||||
- in: query
|
||||
description: Maximum number of entries to return (if absent, no limit is assumed)
|
||||
name: limit
|
||||
schema:
|
||||
type: integer
|
||||
required: false
|
||||
- in: query
|
||||
description: Filter the results
|
||||
name: filter
|
||||
schema:
|
||||
type: string
|
||||
required: false
|
||||
responses:
|
||||
200:
|
||||
description: List all scripts
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/ScriptEntryList'
|
||||
403:
|
||||
$ref: '#/components/responses/Unauthorized'
|
||||
404:
|
||||
$ref: '#/components/responses/NotFound'
|
||||
|
||||
/script/{uuid}:
|
||||
get:
|
||||
tags:
|
||||
- Scripting
|
||||
summary: Returns a script entry.
|
||||
description: Get a specific script entry.
|
||||
operationId: getScript
|
||||
parameters:
|
||||
- in: path
|
||||
description: The UUID of the script
|
||||
name: uuid
|
||||
schema:
|
||||
type: string
|
||||
format: uuid
|
||||
required: true
|
||||
responses:
|
||||
200:
|
||||
description: A script entry
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/ScriptEntry'
|
||||
403:
|
||||
$ref: '#/components/responses/Unauthorized'
|
||||
404:
|
||||
$ref: '#/components/responses/NotFound'
|
||||
|
||||
post:
|
||||
tags:
|
||||
- Scripting
|
||||
summary: Create a new script.
|
||||
operationId: createScript
|
||||
parameters:
|
||||
- in: path
|
||||
description: The UUID of the script. Must be set to 0 for creation
|
||||
name: uuid
|
||||
schema:
|
||||
type: string
|
||||
format: uuid
|
||||
required: true
|
||||
requestBody:
|
||||
description: Complet script entry
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/ScriptEntry'
|
||||
responses:
|
||||
200:
|
||||
$ref: '#/components/schemas/ScriptEntry'
|
||||
403:
|
||||
$ref: '#/components/responses/Unauthorized'
|
||||
404:
|
||||
$ref: '#/components/responses/NotFound'
|
||||
|
||||
put:
|
||||
tags:
|
||||
- Scripting
|
||||
summary: Modify a script.
|
||||
operationId: modifyScript
|
||||
parameters:
|
||||
- in: path
|
||||
description: The UUID of the script.
|
||||
name: uuid
|
||||
schema:
|
||||
type: string
|
||||
format: uuid
|
||||
required: true
|
||||
requestBody:
|
||||
description: Complete script entry. You may only modify the name, description, version, uri, and content
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/ScriptEntry'
|
||||
responses:
|
||||
200:
|
||||
$ref: '#/components/schemas/ScriptEntry'
|
||||
403:
|
||||
$ref: '#/components/responses/Unauthorized'
|
||||
404:
|
||||
$ref: '#/components/responses/NotFound'
|
||||
|
||||
delete:
|
||||
tags:
|
||||
- Scripting
|
||||
summary: Delete a script.
|
||||
operationId: deleteScript
|
||||
parameters:
|
||||
- in: path
|
||||
name: uuid
|
||||
schema:
|
||||
type: string
|
||||
format: uuid
|
||||
required: true
|
||||
responses:
|
||||
204:
|
||||
$ref: '#/components/responses/Success'
|
||||
403:
|
||||
$ref: '#/components/responses/Unauthorized'
|
||||
404:
|
||||
$ref: '#/components/responses/NotFound'
|
||||
|
||||
|
||||
|
||||
|
||||
/blacklist:
|
||||
get:
|
||||
tags:
|
||||
|
||||
@@ -75,6 +75,7 @@ openwifi.autoprovisioning = true
|
||||
openwifi.devicetypes.0 = AP:linksys_ea8300,edgecore_eap101,linksys_e8450-ubi
|
||||
openwifi.devicetypes.1 = SWITCH:edgecore_ecs4100-12ph
|
||||
openwifi.devicetypes.2 = IOT:esp32
|
||||
openwifi.certificates.allowmismatch = ${CERTIFICATES_ALLOWMISMATCH}
|
||||
oui.download.uri = https://standards-oui.ieee.org/oui/oui.txt
|
||||
simulatorid = ${SIMULATORID}
|
||||
iptocountry.default = US
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
"weight" : 10,
|
||||
"radsec" : true,
|
||||
"radsecPort" : 2083,
|
||||
"allowSelfSigned" : false,
|
||||
"radsecSecret" : "radsec",
|
||||
"radsecKey" : "LS0tLS1CRUdJTiBFQyBQUklWQVRFIEtFWS0tLS0tCk1IY0NBUUVFSUR6RnpXeTZlYXg0QVoxTySG9VUURRZ0FFS3BnWVBHMktPTVd2S0w1Z3NMRXpUc09rREg1M3NHaEQyS3RsRXBDTXVnNDNIZlFnTFVpUgpTR1R2S1l0bDFmbmJaU1lnY0RJdncxdjNYRy9hVDhOY2JBPT0KLS0tLS1FTkQgRUMgUFJJVkFURSBLRVktLS0tLQo=",
|
||||
"radsecCert" : "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUNRVENDQWVpZ0F3SUJBZ0lVY3BKS3pVM0Ba0dBMVVFQmhNQ1ZWTXhFekFSQmdOVkJBb1RDa0oxZEhSdmJuZHZiMlF4SFRBYkJnTlZCQU1URkVKMQpkSFJ2Ym5kdmIyUWdVbUZrYzJWaklFTkJNQjRYRFRJeU1EY3dNekExTWpVeE5Gb1hEVEkzTURVeE9UQTFNalV4Ck5Gb3dkVEVMTUFrR0ExVUVCaE1DVlZNeEV6QVJCZ05WQkFvVENrSjFkSFJ2Ym5kdmIyUXhOakEwQmdOVkJBTVQKTFdGeWFXeHBZUzVqWWpFd2FtTnVjemgxYlhCbk9HWnBjRFowTUM1dmNtbHZiaTVoY21WaE1USXdMbU52YlRFWgpNQmNHQ2dtU0pvbVQ4aXhrQVFFVENVZHZiMmRzWlRwVlV6QlpNQk1HQnlxR1NNNDlBZ0VHQ0NxR1NNNDlBd0VICkEwSUFCQ3FZR0R4dGlqakZyeWkrWUxDeE0wN0RwQXgrZDdCb1E5aXJaUktRakxvT054MzBJQzFJa1Voazd5bUwKWmRYNTIyVW1JSEF5TDhOYjkxeHYyay9EWEd5amdZa3dnWVl3RGdZRFZSMFBBUUgvQkFRREFnZUFNQk1HQTFVZApKUVFNTUFvR0NDc0dBUVVGQndNQ01Bd0dBMVVkRXdFQi93UUNNQUF3T0FZRFZSMFJCREV3TDRJdFlYSnBiR2xoCkxtTmlNVEJxWTI1ek9IVnRjR2M0Wm1sd05uUXdMbTl5YVc5dUxtRnlaV0V4TWpBdVkyOXRNQmNHQTFVZElBUVEKTUE0d0RBWUtLd1lCQkFIdUtnRUJCVEFLQmdncWhrak9QUVFEQWdOSEFEQkVBaUFwTmM1dUNBSkp6KzVyakdqdwpCWGtOdHE3UU83bWU5dUg5bkNsTDZnSVE5Z0lnUHM2VkVKVW5CcEZ0RktXbFF4eWJ1YlBxYnpJNjBPSERHQ0ExCmhXUk1PS1U9Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K",
|
||||
|
||||
@@ -28,6 +28,8 @@
|
||||
|
||||
#include "fmt/format.h"
|
||||
|
||||
#include "framework/ow_constants.h"
|
||||
|
||||
|
||||
#include "RADIUS_proxy_server.h"
|
||||
|
||||
@@ -290,7 +292,7 @@ namespace OpenWifi {
|
||||
bool Sent;
|
||||
|
||||
StorageService()->AddCommand(SerialNumber_, Cmd, Storage::CommandExecutionType::COMMAND_EXECUTED);
|
||||
CommandManager()->PostCommand(CommandManager()->Next_RPC_ID(),SerialNumber_, Cmd.Command, Params, Cmd.UUID, Sent);
|
||||
CommandManager()->PostCommand(CommandManager()->Next_RPC_ID(), APCommands::to_apcommand(Cmd.Command.c_str()),SerialNumber_, Cmd.Command, Params, Cmd.UUID, Sent);
|
||||
|
||||
GWWebSocketNotifications::SingleDeviceConfigurationChange_t Notification;
|
||||
Notification.content.serialNumber = D.SerialNumber;
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
#include "Poco/Net/WebSocket.h"
|
||||
|
||||
#include "RESTObjects/RESTAPI_GWobjects.h"
|
||||
#include "AP_restrictions.h"
|
||||
|
||||
namespace OpenWifi {
|
||||
|
||||
@@ -78,7 +77,7 @@ namespace OpenWifi {
|
||||
State = State_;
|
||||
}
|
||||
|
||||
inline void GetRestrictions(AP_Restrictions & R) const {
|
||||
inline void GetRestrictions(GWObjects::DeviceRestrictions & R) const {
|
||||
std::shared_lock G(ConnectionMutex_);
|
||||
R = Restrictions_;
|
||||
}
|
||||
@@ -115,7 +114,7 @@ namespace OpenWifi {
|
||||
|
||||
friend class AP_WS_Server;
|
||||
|
||||
inline AP_Restrictions Restrictions() const {
|
||||
inline GWObjects::DeviceRestrictions Restrictions() const {
|
||||
std::shared_lock G(ConnectionMutex_);
|
||||
return Restrictions_;
|
||||
}
|
||||
@@ -150,7 +149,7 @@ namespace OpenWifi {
|
||||
std::atomic_flag Dead_=false;
|
||||
std::atomic_bool DeviceValidated_=false;
|
||||
std::atomic_bool Valid_=false;
|
||||
AP_Restrictions Restrictions_;
|
||||
OpenWifi::GWObjects::DeviceRestrictions Restrictions_;
|
||||
|
||||
static inline std::atomic_uint64_t ConcurrentStartingDevices_=0;
|
||||
|
||||
|
||||
@@ -50,12 +50,10 @@ namespace OpenWifi {
|
||||
}
|
||||
|
||||
bool RestrictedDevice = false;
|
||||
if(ParamsObj->has("restricted") && ParamsObj->get("restricted").isBoolean()) {
|
||||
if(Capabilities->has("restrictions")){
|
||||
RestrictedDevice = true;
|
||||
if(Capabilities->has("restrictions")) {
|
||||
auto RestrictionObject = Capabilities->getObject("restrictions");
|
||||
Restrictions_.initialize(Logger_, SerialNumber_, RestrictionObject);
|
||||
}
|
||||
Poco::JSON::Object::Ptr RestrictionObject = Capabilities->getObject("restrictions");
|
||||
Restrictions_.from_json(RestrictionObject);
|
||||
}
|
||||
|
||||
State_.locale = FindCountryFromIP()->Get(IP);
|
||||
@@ -97,9 +95,15 @@ namespace OpenWifi {
|
||||
++Updated;
|
||||
}
|
||||
|
||||
if(Restrictions_ != DeviceInfo.restrictionDetails) {
|
||||
DeviceInfo.restrictionDetails = Restrictions_;
|
||||
++Updated;
|
||||
}
|
||||
|
||||
if(Updated) {
|
||||
StorageService()->UpdateDevice(DeviceInfo);
|
||||
}
|
||||
|
||||
uint64_t UpgradedUUID=0;
|
||||
LookForUpgrade(UUID,UpgradedUUID);
|
||||
State_.UUID = UpgradedUUID;
|
||||
@@ -111,7 +115,7 @@ namespace OpenWifi {
|
||||
State_.connectionCompletionTime = ConnectionCompletionTime_.count();
|
||||
|
||||
if(State_.VerifiedCertificate == GWObjects::VALID_CERTIFICATE) {
|
||||
if (( Utils::SerialNumberMatch(CN_, SerialNumber_, AP_WS_Server()->MismatchDepth())) ||
|
||||
if (( Utils::SerialNumberMatch(CN_, SerialNumber_, (int)AP_WS_Server()->MismatchDepth())) ||
|
||||
AP_WS_Server()->IsSimSerialNumber(CN_)) {
|
||||
State_.VerifiedCertificate = GWObjects::VERIFIED;
|
||||
poco_information(Logger_, fmt::format("CONNECT({}): Fully validated and authenticated device. Session={} ConnectionCompletion Time={}",
|
||||
@@ -127,9 +131,8 @@ namespace OpenWifi {
|
||||
State_.connectionCompletionTime));
|
||||
} else {
|
||||
poco_information(
|
||||
Logger_, fmt::format("CONNECT({}): Serial number mismatch disallowed. Device rejected. CN={} Serial={} Session={} ConnectionCompletion Time={}",
|
||||
CId_, CN_, SerialNumber_, State_.sessionId,
|
||||
State_.connectionCompletionTime));
|
||||
Logger_, fmt::format("CONNECT({}): Serial number mismatch disallowed. Device rejected. CN={} Serial={} Session={}",
|
||||
CId_, CN_, SerialNumber_, State_.sessionId));
|
||||
return EndConnection();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include "framework/ow_constants.h"
|
||||
#include "framework/MicroServiceFuncs.h"
|
||||
#include "fmt/format.h"
|
||||
#include "framework/ow_constants.h"
|
||||
|
||||
namespace OpenWifi {
|
||||
void AP_WS_Connection::Process_recovery(Poco::JSON::Object::Ptr ParamsObj) {
|
||||
@@ -51,7 +52,7 @@ namespace OpenWifi {
|
||||
Poco::JSON::Stringifier::stringify(Params, O);
|
||||
Cmd.Details = O.str();
|
||||
bool Sent;
|
||||
CommandManager()->PostCommand(CommandManager()->Next_RPC_ID(),SerialNumber_, Cmd.Command, Params, Cmd.UUID, Sent);
|
||||
CommandManager()->PostCommand(CommandManager()->Next_RPC_ID(), APCommands::Commands::reboot, SerialNumber_, Cmd.Command, Params, Cmd.UUID, Sent);
|
||||
StorageService()->AddCommand(SerialNumber_, Cmd, Storage::CommandExecutionType::COMMAND_EXECUTED);
|
||||
poco_information(Logger_, fmt::format("RECOVERY({}): Recovery mode received, need for a reboot.", CId_));
|
||||
} else {
|
||||
|
||||
@@ -296,7 +296,7 @@ namespace OpenWifi {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool AP_WS_Server::Connected(uint64_t SerialNumber, AP_Restrictions & Restrictions) const {
|
||||
bool AP_WS_Server::Connected(uint64_t SerialNumber, GWObjects::DeviceRestrictions & Restrictions) const {
|
||||
std::shared_ptr<AP_WS_Connection> DevicePtr;
|
||||
{
|
||||
std::lock_guard Lock(WSServerMutex_);
|
||||
|
||||
@@ -134,7 +134,7 @@ namespace OpenWifi {
|
||||
}
|
||||
bool GetHealthcheck(uint64_t SerialNumber, GWObjects::HealthCheck & CheckData) const ;
|
||||
|
||||
bool Connected(uint64_t SerialNumber, AP_Restrictions & Restrictions) const ;
|
||||
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 {
|
||||
|
||||
@@ -1,77 +0,0 @@
|
||||
//
|
||||
// Created by stephane bourque on 2022-11-14.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <set>
|
||||
|
||||
#include "Poco/JSON/Object.h"
|
||||
#include "Poco/Logger.h"
|
||||
#include "fmt/format.h"
|
||||
|
||||
/*
|
||||
{
|
||||
“country”: [
|
||||
“US”, “CA”
|
||||
],
|
||||
“dfs”: true,
|
||||
“ssh”: true,
|
||||
“rtty”: true,
|
||||
“tty”: true,
|
||||
“developer”: true,
|
||||
“sysupgrade”: true,
|
||||
“commands”: true
|
||||
}
|
||||
*/
|
||||
|
||||
namespace OpenWifi {
|
||||
class AP_Restrictions {
|
||||
public:
|
||||
inline bool initialize(Poco::Logger & Logger, const std::string & serialNumber, const Poco::JSON::Object::Ptr &O) {
|
||||
try {
|
||||
dfs_ = O->optValue("dfs",false);
|
||||
ssh_ = O->optValue("ssh",false);
|
||||
rtty_ = O->optValue("rtty",false);
|
||||
tty_ = O->optValue("tty",false);
|
||||
developer_ = O->optValue("developer",false);
|
||||
sysupgrade_ = O->optValue("sysupgrade",false);
|
||||
commands_ = O->optValue("commands",false);
|
||||
if(O->has("country") && O->isArray("country")) {
|
||||
auto Countries = O->getArray("country");
|
||||
for(const auto &country:*Countries) {
|
||||
countries_.insert(Poco::toLower(country.toString()));
|
||||
}
|
||||
}
|
||||
return true;
|
||||
} catch (...) {
|
||||
poco_error(Logger,fmt::format("Cannot parse restrictions for device {}", serialNumber));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
[[nodiscard]] inline auto dfs_not_allowed() const { return dfs_; }
|
||||
[[nodiscard]] inline auto ssh_not_allowed() const { return ssh_; }
|
||||
[[nodiscard]] inline auto rtty_not_allowed() const { return rtty_; }
|
||||
[[nodiscard]] inline auto tty_not_allowed() const { return tty_; }
|
||||
[[nodiscard]] inline auto developer_not_allowed() const { return developer_; }
|
||||
[[nodiscard]] inline auto sysupgrade_not_allowed() const { return sysupgrade_; }
|
||||
[[nodiscard]] inline auto commands_not_allowed() const { return commands_; }
|
||||
[[nodiscard]] inline bool valid_country(const std::string &c) const {
|
||||
if(countries_.empty())
|
||||
return true;
|
||||
return countries_.find(Poco::toLower(c))!=countries_.end();
|
||||
}
|
||||
|
||||
private:
|
||||
std::set<std::string> countries_;
|
||||
bool dfs_ = false;
|
||||
bool ssh_ = false;
|
||||
bool rtty_ = false;
|
||||
bool tty_ = false;
|
||||
bool developer_ = false;
|
||||
bool sysupgrade_ = false;
|
||||
bool commands_ = false;
|
||||
};
|
||||
}
|
||||
@@ -67,11 +67,11 @@ R"lit(
|
||||
"ipv4": {
|
||||
"addressing": "static",
|
||||
"dhcp": {
|
||||
"lease-count": 10000,
|
||||
"lease-count": 100,
|
||||
"lease-first": 10,
|
||||
"lease-time": "6h"
|
||||
},
|
||||
"subnet": "192.168.1.1/16"
|
||||
"subnet": "192.168.1.1/24"
|
||||
},
|
||||
"name": "LAN",
|
||||
"role": "downstream",
|
||||
|
||||
@@ -34,13 +34,13 @@ namespace OpenWifi {
|
||||
Poco::JSON::Object::Ptr Payload = Resp->Payload_;
|
||||
std::string SerialNumberStr = Utils::IntToSerialNumber(Resp->SerialNumber_);
|
||||
|
||||
std::ostringstream SS;
|
||||
Payload->stringify(SS);
|
||||
bool NoReply = false;
|
||||
|
||||
if (!Payload->has(uCentralProtocol::ID)) {
|
||||
poco_error(Logger(), fmt::format("({}): Invalid RPC response.", SerialNumberStr));
|
||||
} else {
|
||||
uint64_t ID = Payload->get(uCentralProtocol::ID);
|
||||
std::shared_ptr<promise_type_t> TmpRpcEntry;
|
||||
poco_debug(Logger(),fmt::format("({}): Processing {} response.", SerialNumberStr, ID));
|
||||
if (ID > 1) {
|
||||
std::lock_guard Lock(LocalMutex_);
|
||||
@@ -53,16 +53,65 @@ namespace OpenWifi {
|
||||
std::chrono::duration<double, std::milli> rpc_execution_time =
|
||||
std::chrono::high_resolution_clock::now() -
|
||||
RPC->second.submitted;
|
||||
StorageService()->CommandCompleted(RPC->second.UUID, Payload,
|
||||
rpc_execution_time, true);
|
||||
if (RPC->second.rpc_entry) {
|
||||
RPC->second.rpc_entry->set_value(Payload);
|
||||
}
|
||||
|
||||
poco_debug(Logger(),
|
||||
fmt::format("({}): Received RPC answer {}. Command={}",
|
||||
SerialNumberStr, ID, RPC->second.Command));
|
||||
OutStandingRequests_.erase(ID);
|
||||
SerialNumberStr, ID, APCommands::to_string(RPC->second.Command)));
|
||||
if(RPC->second.Command==APCommands::Commands::script) {
|
||||
if(RPC->second.State==2) {
|
||||
// look at the payload to see if we should continue or not...
|
||||
if (RPC->second.rpc_entry) {
|
||||
TmpRpcEntry = RPC->second.rpc_entry;
|
||||
}
|
||||
|
||||
// Payload->stringify(std::cout);
|
||||
|
||||
if (Payload->has("result")) {
|
||||
auto Result = Payload->getObject("result");
|
||||
if (Result->has("status")) {
|
||||
auto Status = Result->getObject("status");
|
||||
// Status->stringify(std::cout);
|
||||
std::uint64_t Error = Status->get("error");
|
||||
if(Error==0) {
|
||||
StorageService()->CommandCompleted(RPC->second.UUID, Payload,
|
||||
rpc_execution_time, true);
|
||||
RPC->second.State = 1 ;
|
||||
} else {
|
||||
StorageService()->CommandCompleted(RPC->second.UUID, Payload,
|
||||
rpc_execution_time, true);
|
||||
std::string ErrorTxt = Status->get("result");
|
||||
StorageService()->CancelWaitFile(RPC->second.UUID, ErrorTxt);
|
||||
RPC->second.State = 0 ;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// std::cout << "Bad payload on command result" << std::endl;
|
||||
RPC->second.State=0;
|
||||
}
|
||||
} else {
|
||||
// std::cout << "Completing script 2 phase commit." << std::endl;
|
||||
StorageService()->CommandCompleted(RPC->second.UUID, Payload,
|
||||
rpc_execution_time, true);
|
||||
NoReply = true;
|
||||
RPC->second.State=0;
|
||||
}
|
||||
} else {
|
||||
if(RPC->second.Command!=APCommands::Commands::telemetry) {
|
||||
StorageService()->CommandCompleted(
|
||||
RPC->second.UUID, Payload, rpc_execution_time, true);
|
||||
}
|
||||
if (RPC->second.rpc_entry) {
|
||||
TmpRpcEntry = RPC->second.rpc_entry;
|
||||
}
|
||||
RPC->second.State = 0 ;
|
||||
}
|
||||
|
||||
if(RPC->second.State==0) {
|
||||
OutStandingRequests_.erase(ID);
|
||||
}
|
||||
}
|
||||
if(!NoReply && TmpRpcEntry != nullptr)
|
||||
TmpRpcEntry->set_value(Payload);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -120,7 +169,7 @@ namespace OpenWifi {
|
||||
if(delta > 10min) {
|
||||
MyLogger.debug(fmt::format("{}: Command={} for {} Timed out.",
|
||||
request->second.UUID,
|
||||
request->second.Command,
|
||||
APCommands::to_string(request->second.Command),
|
||||
Utils::IntToSerialNumber(request->second.SerialNumber)));
|
||||
request = OutStandingRequests_.erase(request);
|
||||
} else {
|
||||
@@ -189,14 +238,15 @@ namespace OpenWifi {
|
||||
continue;
|
||||
}
|
||||
|
||||
std::string ExecutingCommand, ExecutingUUID;
|
||||
std::string ExecutingUUID;
|
||||
APCommands::Commands ExecutingCommand=APCommands::Commands::unknown;
|
||||
if (CommandRunningForDevice(Utils::SerialNumberToInt(Cmd.SerialNumber),
|
||||
ExecutingUUID, ExecutingCommand)) {
|
||||
poco_trace(
|
||||
MyLogger,
|
||||
fmt::format(
|
||||
"{}: Serial={} Command={} Device is already busy with command {} (Command={})."
|
||||
, Cmd.UUID, Cmd.SerialNumber, Cmd.Command,ExecutingUUID, ExecutingCommand));
|
||||
, Cmd.UUID, Cmd.SerialNumber, Cmd.Command, ExecutingUUID, APCommands::to_string(ExecutingCommand)));
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -205,7 +255,7 @@ namespace OpenWifi {
|
||||
poco_information(MyLogger, fmt::format("{}: Serial={} Command={} Preparing execution.",
|
||||
Cmd.UUID, Cmd.SerialNumber, Cmd.Command));
|
||||
auto Params = P.parse(Cmd.Details).extract<Poco::JSON::Object::Ptr>();
|
||||
auto Result = PostCommandDisk(Next_RPC_ID(), Cmd.SerialNumber, Cmd.Command,
|
||||
auto Result = PostCommandDisk(Next_RPC_ID(), APCommands::to_apcommand(Cmd.Command.c_str()), Cmd.SerialNumber, Cmd.Command,
|
||||
*Params, Cmd.UUID, Sent);
|
||||
if (Sent) {
|
||||
StorageService()->SetCommandExecuted(Cmd.UUID);
|
||||
@@ -240,9 +290,10 @@ namespace OpenWifi {
|
||||
}
|
||||
|
||||
std::shared_ptr<CommandManager::promise_type_t> CommandManager::PostCommand(
|
||||
uint64_t RPCID,
|
||||
uint64_t RPC_ID,
|
||||
APCommands::Commands Command,
|
||||
const std::string &SerialNumber,
|
||||
const std::string &Command,
|
||||
const std::string &CommandStr,
|
||||
const Poco::JSON::Object &Params,
|
||||
const std::string &UUID,
|
||||
bool oneway_rpc,
|
||||
@@ -255,31 +306,33 @@ namespace OpenWifi {
|
||||
std::stringstream ToSend;
|
||||
|
||||
CommandInfo Idx;
|
||||
Idx.Id = oneway_rpc ? 1 : RPCID;
|
||||
Idx.Id = oneway_rpc ? 1 : RPC_ID;
|
||||
Idx.SerialNumber = SerialNumberInt;
|
||||
Idx.Command = Command;
|
||||
if(Command == APCommands::Commands::script)
|
||||
Idx.State=2;
|
||||
Idx.UUID = UUID;
|
||||
|
||||
Poco::JSON::Object CompleteRPC;
|
||||
CompleteRPC.set(uCentralProtocol::JSONRPC, uCentralProtocol::JSONRPC_VERSION);
|
||||
CompleteRPC.set(uCentralProtocol::ID, RPCID);
|
||||
CompleteRPC.set(uCentralProtocol::METHOD, Command);
|
||||
CompleteRPC.set(uCentralProtocol::ID, RPC_ID);
|
||||
CompleteRPC.set(uCentralProtocol::METHOD, CommandStr);
|
||||
CompleteRPC.set(uCentralProtocol::PARAMS, Params);
|
||||
Poco::JSON::Stringifier::stringify(CompleteRPC, ToSend);
|
||||
Idx.rpc_entry = disk_only ? nullptr : std::make_shared<CommandManager::promise_type_t>();
|
||||
|
||||
poco_debug(Logger(), fmt::format("{}: Sending command. ID: {}", UUID, RPCID));
|
||||
poco_debug(Logger(), fmt::format("{}: Sending command {} to {}. ID: {}", UUID, CommandStr, SerialNumber, RPC_ID));
|
||||
if(AP_WS_Server()->SendFrame(SerialNumber, ToSend.str())) {
|
||||
if(!oneway_rpc) {
|
||||
std::lock_guard M(Mutex_);
|
||||
OutStandingRequests_[RPCID] = Idx;
|
||||
OutStandingRequests_[RPC_ID] = Idx;
|
||||
}
|
||||
poco_debug(Logger(), fmt::format("{}: Sent command. ID: {}", UUID, RPCID));
|
||||
poco_debug(Logger(), fmt::format("{}: Sent command. ID: {}", UUID, RPC_ID));
|
||||
Sent=true;
|
||||
return Idx.rpc_entry;
|
||||
}
|
||||
|
||||
poco_warning(Logger(), fmt::format("{}: Failed to send command. ID: {}", UUID, RPCID));
|
||||
poco_warning(Logger(), fmt::format("{}: Failed to send command. ID: {}", UUID, RPC_ID));
|
||||
return nullptr;
|
||||
}
|
||||
} // namespace
|
||||
@@ -49,10 +49,11 @@ namespace OpenWifi {
|
||||
using promise_type_t = std::promise<objtype_t>;
|
||||
|
||||
struct CommandInfo {
|
||||
std::uint64_t Id=0;
|
||||
std::uint64_t SerialNumber=0;
|
||||
std::string Command;
|
||||
std::string UUID;
|
||||
std::uint64_t Id=0;
|
||||
std::uint64_t SerialNumber=0;
|
||||
APCommands::Commands Command;
|
||||
std::string UUID;
|
||||
std::uint64_t State=1;
|
||||
std::chrono::time_point<std::chrono::high_resolution_clock> submitted = std::chrono::high_resolution_clock::now();
|
||||
std::shared_ptr<promise_type_t> rpc_entry;
|
||||
};
|
||||
@@ -76,12 +77,15 @@ namespace OpenWifi {
|
||||
}
|
||||
|
||||
std::shared_ptr<promise_type_t> PostCommandOneWayDisk(uint64_t RPC_ID,
|
||||
APCommands::Commands Command,
|
||||
const std::string &SerialNumber,
|
||||
const std::string &Method,
|
||||
const Poco::JSON::Object &Params,
|
||||
const std::string &UUID,
|
||||
bool & Sent) {
|
||||
return PostCommand(RPC_ID, SerialNumber,
|
||||
return PostCommand(RPC_ID,
|
||||
Command,
|
||||
SerialNumber,
|
||||
Method,
|
||||
Params,
|
||||
UUID,
|
||||
@@ -90,12 +94,14 @@ namespace OpenWifi {
|
||||
|
||||
std::shared_ptr<promise_type_t> PostCommandDisk(
|
||||
uint64_t RPC_ID,
|
||||
APCommands::Commands Command,
|
||||
const std::string &SerialNumber,
|
||||
const std::string &Method,
|
||||
const Poco::JSON::Object &Params,
|
||||
const std::string &UUID,
|
||||
bool & Sent) {
|
||||
return PostCommand(RPC_ID,
|
||||
Command,
|
||||
SerialNumber,
|
||||
Method,
|
||||
Params,
|
||||
@@ -105,12 +111,15 @@ namespace OpenWifi {
|
||||
|
||||
std::shared_ptr<promise_type_t> PostCommand(
|
||||
uint64_t RPC_ID,
|
||||
APCommands::Commands Command,
|
||||
const std::string &SerialNumber,
|
||||
const std::string &Method,
|
||||
const Poco::JSON::Object &Params,
|
||||
const std::string &UUID,
|
||||
bool & Sent) {
|
||||
return PostCommand(RPC_ID, SerialNumber,
|
||||
return PostCommand(RPC_ID,
|
||||
Command,
|
||||
SerialNumber,
|
||||
Method,
|
||||
Params,
|
||||
UUID,
|
||||
@@ -120,12 +129,14 @@ namespace OpenWifi {
|
||||
|
||||
std::shared_ptr<promise_type_t> PostCommandOneWay(
|
||||
uint64_t RPC_ID,
|
||||
APCommands::Commands Command,
|
||||
const std::string &SerialNumber,
|
||||
const std::string &Method,
|
||||
const Poco::JSON::Object &Params,
|
||||
const std::string &UUID,
|
||||
bool & Sent) {
|
||||
return PostCommand(RPC_ID,
|
||||
Command,
|
||||
SerialNumber,
|
||||
Method,
|
||||
Params,
|
||||
@@ -153,7 +164,7 @@ namespace OpenWifi {
|
||||
OutStandingRequests_.erase(Id);
|
||||
}
|
||||
|
||||
inline bool CommandRunningForDevice(std::uint64_t SerialNumber, std::string & uuid, std::string &command) {
|
||||
inline bool CommandRunningForDevice(std::uint64_t SerialNumber, std::string & uuid, APCommands::Commands &command) {
|
||||
std::lock_guard Lock(LocalMutex_);
|
||||
|
||||
for(const auto &[Request,Command]:OutStandingRequests_) {
|
||||
@@ -190,6 +201,7 @@ namespace OpenWifi {
|
||||
|
||||
std::shared_ptr<promise_type_t> PostCommand(
|
||||
uint64_t RPCID,
|
||||
APCommands::Commands Command,
|
||||
const std::string &SerialNumber,
|
||||
const std::string &Method,
|
||||
const Poco::JSON::Object &Params,
|
||||
|
||||
@@ -28,6 +28,8 @@
|
||||
#include "rttys/RTTYS_server.h"
|
||||
#include "framework/UI_WebSocketClientServer.h"
|
||||
#include "UI_GW_WebSocketNotifications.h"
|
||||
#include "ScriptManager.h"
|
||||
#include "SignatureMgr.h"
|
||||
|
||||
namespace OpenWifi {
|
||||
class Daemon *Daemon::instance() {
|
||||
@@ -50,6 +52,8 @@ namespace OpenWifi {
|
||||
RTTYS_server(),
|
||||
RADIUS_proxy_server(),
|
||||
VenueBroadcaster(),
|
||||
ScriptManager(),
|
||||
SignatureManager(),
|
||||
AP_WS_Server()
|
||||
});
|
||||
return &instance;
|
||||
|
||||
@@ -7,14 +7,45 @@
|
||||
#include "framework/utils.h"
|
||||
|
||||
namespace OpenWifi {
|
||||
void DeviceDashboard::Create() {
|
||||
uint64_t Now = Utils::Now();
|
||||
|
||||
if(LastRun_==0 || (Now-LastRun_)>120) {
|
||||
DB_.reset();
|
||||
StorageService()->AnalyzeCommands(DB_.commands);
|
||||
StorageService()->AnalyzeDevices(DB_);
|
||||
LastRun_ = Now;
|
||||
bool DeviceDashboard::Get(GWObjects::Dashboard &D, Poco::Logger & Logger) {
|
||||
uint64_t Now = Utils::Now();
|
||||
if(!ValidDashboard_ || LastRun_==0 || (Now-LastRun_)>120) {
|
||||
Generate(D, Logger);
|
||||
} else {
|
||||
std::lock_guard G(DataMutex_);
|
||||
D = DB_;
|
||||
}
|
||||
return ValidDashboard_;
|
||||
};
|
||||
|
||||
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);
|
||||
}
|
||||
std::lock_guard G(DataMutex_);
|
||||
D = DB_;
|
||||
} else {
|
||||
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);
|
||||
StorageService()->AnalyzeDevices(NewData);
|
||||
LastRun_ = Utils::Now();
|
||||
NewData.snapshot = LastRun_;
|
||||
D = NewData;
|
||||
std::lock_guard G(DataMutex_);
|
||||
DB_ = NewData;
|
||||
ValidDashboard_=true;
|
||||
} catch(...) {
|
||||
|
||||
}
|
||||
GeneratingDashboard_ = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,19 +4,24 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <mutex>
|
||||
|
||||
#include "RESTObjects//RESTAPI_GWobjects.h"
|
||||
#include "framework/OpenWifiTypes.h"
|
||||
#include "Poco/Logger.h"
|
||||
|
||||
namespace OpenWifi {
|
||||
class DeviceDashboard {
|
||||
public:
|
||||
DeviceDashboard() { DB_.reset(); }
|
||||
void Create();
|
||||
[[nodiscard]] const GWObjects::Dashboard & Report() const { return DB_;}
|
||||
bool Get(GWObjects::Dashboard &D, Poco::Logger & Logger);
|
||||
private:
|
||||
GWObjects::Dashboard DB_;
|
||||
uint64_t LastRun_=0;
|
||||
inline void Reset() { DB_.reset(); }
|
||||
std::mutex DataMutex_;
|
||||
volatile std::atomic_bool GeneratingDashboard_=false;
|
||||
volatile bool ValidDashboard_=false;
|
||||
GWObjects::Dashboard DB_;
|
||||
uint64_t LastRun_=0;
|
||||
|
||||
void Generate(GWObjects::Dashboard &D, Poco::Logger & Logger);
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@ namespace OpenWifi {
|
||||
|
||||
struct UploadId {
|
||||
std::string UUID;
|
||||
std::uint64_t Expires;
|
||||
std::uint64_t Expires;
|
||||
std::string Type;
|
||||
};
|
||||
|
||||
|
||||
@@ -291,6 +291,8 @@ static const struct tok radius_attribute_names[] = {
|
||||
constexpr unsigned char CoA_ACK = 44;
|
||||
constexpr unsigned char CoA_NAK = 45;
|
||||
|
||||
constexpr unsigned char ATTR_MessageAuthenticator = 80;
|
||||
|
||||
inline bool IsAuthentication(unsigned char t) {
|
||||
return (t == RADIUS::Access_Request ||
|
||||
t == RADIUS::Access_Accept ||
|
||||
@@ -330,6 +332,11 @@ static const struct tok radius_attribute_names[] = {
|
||||
return "Unknown";
|
||||
}
|
||||
|
||||
inline void MakeRadiusAuthenticator(unsigned char *authenticator) {
|
||||
for(int i=0;i<16;i++)
|
||||
authenticator[i]=std::rand() & 0xff;
|
||||
}
|
||||
|
||||
//
|
||||
// From: https://github.com/Telecominfraproject/wlan-dictionary/blob/main/dictionary.tip
|
||||
//
|
||||
@@ -666,6 +673,44 @@ static const struct tok radius_attribute_names[] = {
|
||||
bool Valid_=false;
|
||||
};
|
||||
|
||||
class RadiusOutputPacket {
|
||||
public:
|
||||
explicit RadiusOutputPacket(const std::string &Secret)
|
||||
: Secret_(Secret) {
|
||||
}
|
||||
|
||||
inline void MakeStatusMessage() {
|
||||
P_.code = RADCMD_STATUS_SER;
|
||||
P_.identifier = std::rand() & 0x00ff;
|
||||
MakeRadiusAuthenticator(P_.authenticator);
|
||||
unsigned char MessageAuthenticator[16]{0};
|
||||
AddAttribute(ATTR_MessageAuthenticator,sizeof(MessageAuthenticator),MessageAuthenticator);
|
||||
P_.rawlen = 1 + 1 + 2 + 16 + 1 + 1 + 16;
|
||||
|
||||
Poco::HMACEngine<Poco::MD5Engine> H(Secret_);
|
||||
H.update((const unsigned char *)&P_, P_.rawlen);
|
||||
auto digest = H.digest();
|
||||
int p = 0;
|
||||
for (const auto &i : digest)
|
||||
P_.attributes[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;
|
||||
memcpy(&P_.attributes[AttributesLen_],data,len);
|
||||
AttributesLen_+=len;
|
||||
}
|
||||
|
||||
[[nodiscard]] inline const unsigned char * Data() const { return (const unsigned char *) &P_;}
|
||||
[[nodiscard]] inline std::uint16_t Len() const { return P_.rawlen; }
|
||||
|
||||
private:
|
||||
RawRadiusPacket P_;
|
||||
uint16_t AttributesLen_=0;
|
||||
std::string Secret_;
|
||||
};
|
||||
|
||||
inline std::ostream &operator<<(std::ostream &os, RadiusPacket const &P) {
|
||||
os << P.Attrs_ ;
|
||||
return os;
|
||||
|
||||
@@ -22,124 +22,132 @@ namespace OpenWifi {
|
||||
ConfigFilename_ = MicroServiceDataDirectory()+"/radius_pool_config.json";
|
||||
Poco::File Config(ConfigFilename_);
|
||||
|
||||
enabled_ = MicroServiceConfigGetBool("radius.proxy.enable",false);
|
||||
if(!enabled_ && !Config.exists()) {
|
||||
Enabled_ = MicroServiceConfigGetBool("radius.proxy.enable",false);
|
||||
if(!Enabled_ && !Config.exists()) {
|
||||
StopRADSECServers();
|
||||
return 0;
|
||||
}
|
||||
|
||||
poco_notice(Logger(),"Starting...");
|
||||
|
||||
enabled_ = true;
|
||||
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);
|
||||
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);
|
||||
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);
|
||||
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);
|
||||
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);
|
||||
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);
|
||||
CoASocketV6_ = std::make_unique<Poco::Net::DatagramSocket>(CoASockAddrV6,true,true);
|
||||
|
||||
RadiusReactor_.addEventHandler(*AuthenticationSocketV4_,Poco::NObserver<RADIUS_proxy_server, Poco::Net::ReadableNotification>(
|
||||
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>(
|
||||
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>(
|
||||
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>(
|
||||
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>(
|
||||
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>(
|
||||
RadiusReactor_->addEventHandler(*CoASocketV6_,Poco::NObserver<RADIUS_proxy_server, Poco::Net::ReadableNotification>(
|
||||
*this, &RADIUS_proxy_server::OnCoASocketReadable));
|
||||
|
||||
ParseConfig();
|
||||
|
||||
// start RADSEC servers...
|
||||
StopRADSECServers();
|
||||
StartRADSECServers();
|
||||
RadiusReactorThread_.start(RadiusReactor_);
|
||||
|
||||
RadiusReactorThread_.start(*RadiusReactor_);
|
||||
Utils::SetThreadName(RadiusReactorThread_,"rad:reactor");
|
||||
|
||||
running_ = true;
|
||||
Running_ = true;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void RADIUS_proxy_server::Stop() {
|
||||
poco_information(Logger(),"Stopping...");
|
||||
if(enabled_ && running_) {
|
||||
RadiusReactor_.removeEventHandler(
|
||||
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(
|
||||
RadiusReactor_->removeEventHandler(
|
||||
*AuthenticationSocketV6_,
|
||||
Poco::NObserver<RADIUS_proxy_server, Poco::Net::ReadableNotification>(
|
||||
*this, &RADIUS_proxy_server::OnAuthenticationSocketReadable));
|
||||
|
||||
RadiusReactor_.removeEventHandler(
|
||||
RadiusReactor_->removeEventHandler(
|
||||
*AccountingSocketV4_,
|
||||
Poco::NObserver<RADIUS_proxy_server, Poco::Net::ReadableNotification>(
|
||||
*this, &RADIUS_proxy_server::OnAccountingSocketReadable));
|
||||
RadiusReactor_.removeEventHandler(
|
||||
RadiusReactor_->removeEventHandler(
|
||||
*AccountingSocketV6_,
|
||||
Poco::NObserver<RADIUS_proxy_server, Poco::Net::ReadableNotification>(
|
||||
*this, &RADIUS_proxy_server::OnAccountingSocketReadable));
|
||||
|
||||
RadiusReactor_.removeEventHandler(
|
||||
RadiusReactor_->removeEventHandler(
|
||||
*CoASocketV4_,
|
||||
Poco::NObserver<RADIUS_proxy_server, Poco::Net::ReadableNotification>(
|
||||
*this, &RADIUS_proxy_server::OnCoASocketReadable));
|
||||
RadiusReactor_.removeEventHandler(
|
||||
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();
|
||||
RadiusReactor_->stop();
|
||||
RadiusReactorThread_.join();
|
||||
enabled_=false;
|
||||
running_=false;
|
||||
Running_=false;
|
||||
poco_information(Logger(),"Stopped...");
|
||||
}
|
||||
poco_information(Logger(),"Stopped...");
|
||||
}
|
||||
|
||||
void RADIUS_proxy_server::StartRADSECServers() {
|
||||
std::lock_guard G(Mutex_);
|
||||
for(const auto &pool:PoolList_.pools) {
|
||||
for(const auto &entry:pool.authConfig.servers) {
|
||||
if(entry.radsec) {
|
||||
StartRADSECServer(entry);
|
||||
RADSECservers_[ Poco::Net::SocketAddress(entry.ip,0) ] = std::make_unique<RADSEC_server>(*RadiusReactor_,entry);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RADIUS_proxy_server::StopRADSECServers() {
|
||||
std::lock_guard G(Mutex_);
|
||||
RADSECservers_.clear();
|
||||
}
|
||||
|
||||
void RADIUS_proxy_server::StartRADSECServer(const GWObjects::RadiusProxyServerEntry &E) {
|
||||
RADSECservers_[ Poco::Net::SocketAddress(E.ip,0) ] = std::make_unique<RADSEC_server>(RadiusReactor_,E);
|
||||
}
|
||||
|
||||
void RADIUS_proxy_server::OnAccountingSocketReadable(const Poco::AutoPtr<Poco::Net::ReadableNotification>& pNf) {
|
||||
Poco::Net::SocketAddress Sender;
|
||||
RADIUS::RadiusPacket P;
|
||||
@@ -208,7 +216,7 @@ namespace OpenWifi {
|
||||
|
||||
void RADIUS_proxy_server::SendAccountingData(const std::string &serialNumber, const char *buffer, std::size_t size) {
|
||||
|
||||
if(Pools_.empty() || !enabled_)
|
||||
if(!Continue())
|
||||
return;
|
||||
|
||||
try {
|
||||
@@ -266,7 +274,7 @@ namespace OpenWifi {
|
||||
|
||||
void RADIUS_proxy_server::SendAuthenticationData(const std::string &serialNumber, const char *buffer, std::size_t size) {
|
||||
|
||||
if(Pools_.empty() || !enabled_)
|
||||
if(!Continue())
|
||||
return;
|
||||
|
||||
try {
|
||||
@@ -319,7 +327,7 @@ namespace OpenWifi {
|
||||
|
||||
void RADIUS_proxy_server::SendCoAData(const std::string &serialNumber, const char *buffer, std::size_t size) {
|
||||
|
||||
if(Pools_.empty() || !enabled_)
|
||||
if(!Continue())
|
||||
return;
|
||||
|
||||
try {
|
||||
@@ -389,7 +397,7 @@ namespace OpenWifi {
|
||||
};
|
||||
|
||||
if(setAsDefault && D.useRADSEC)
|
||||
defaultIsRADSEC_ = true;
|
||||
DefaultIsRADSEC_ = true;
|
||||
|
||||
if(S.family()==Poco::Net::IPAddress::IPv4) {
|
||||
TotalV4 += server.weight;
|
||||
@@ -483,26 +491,26 @@ namespace OpenWifi {
|
||||
}
|
||||
}
|
||||
|
||||
if(defaultIsRADSEC_) {
|
||||
if(DefaultIsRADSEC_) {
|
||||
UseRADSEC = true;
|
||||
return (IsV4 ? Pools_[defaultPoolIndex_].AuthV4[0].Addr : Pools_[defaultPoolIndex_].AuthV6[0].Addr );
|
||||
return (IsV4 ? Pools_[DefaultPoolIndex_].AuthV4[0].Addr : Pools_[DefaultPoolIndex_].AuthV6[0].Addr );
|
||||
}
|
||||
|
||||
switch(rtype) {
|
||||
case radius_type::auth: {
|
||||
return ChooseAddress(IsV4 ? Pools_[defaultPoolIndex_].AuthV4
|
||||
: Pools_[defaultPoolIndex_].AuthV6,
|
||||
return ChooseAddress(IsV4 ? Pools_[DefaultPoolIndex_].AuthV4
|
||||
: Pools_[DefaultPoolIndex_].AuthV6,
|
||||
RequestedAddress);
|
||||
}
|
||||
case radius_type::acct:
|
||||
default: {
|
||||
return ChooseAddress(IsV4 ? Pools_[defaultPoolIndex_].AcctV4
|
||||
: Pools_[defaultPoolIndex_].AcctV6,
|
||||
return ChooseAddress(IsV4 ? Pools_[DefaultPoolIndex_].AcctV4
|
||||
: Pools_[DefaultPoolIndex_].AcctV6,
|
||||
RequestedAddress);
|
||||
}
|
||||
case radius_type::coa: {
|
||||
return ChooseAddress(IsV4 ? Pools_[defaultPoolIndex_].CoaV4
|
||||
: Pools_[defaultPoolIndex_].CoaV6,
|
||||
return ChooseAddress(IsV4 ? Pools_[DefaultPoolIndex_].CoaV4
|
||||
: Pools_[DefaultPoolIndex_].CoaV6,
|
||||
RequestedAddress);
|
||||
}
|
||||
}
|
||||
@@ -621,7 +629,6 @@ namespace OpenWifi {
|
||||
|
||||
void RADIUS_proxy_server::SetConfig(const GWObjects::RadiusProxyPoolList &C) {
|
||||
std::lock_guard G(Mutex_);
|
||||
PoolList_ = C;
|
||||
|
||||
Poco::JSON::Object Disk;
|
||||
C.to_json(Disk);
|
||||
@@ -630,17 +637,17 @@ namespace OpenWifi {
|
||||
Disk.stringify(ofs);
|
||||
ofs.close();
|
||||
|
||||
if(!running_) {
|
||||
Start();
|
||||
}
|
||||
|
||||
ParseConfig();
|
||||
Stop();
|
||||
ResetConfig();
|
||||
PoolList_ = C;
|
||||
Start();
|
||||
}
|
||||
|
||||
void RADIUS_proxy_server::ResetConfig() {
|
||||
PoolList_.pools.clear();
|
||||
Pools_.clear();
|
||||
defaultPoolIndex_=0;
|
||||
DefaultPoolIndex_=0;
|
||||
DefaultIsRADSEC_=false;
|
||||
}
|
||||
|
||||
void RADIUS_proxy_server::DeleteConfig() {
|
||||
@@ -653,8 +660,8 @@ namespace OpenWifi {
|
||||
} catch (...) {
|
||||
|
||||
}
|
||||
ResetConfig();
|
||||
Stop();
|
||||
ResetConfig();
|
||||
}
|
||||
|
||||
void RADIUS_proxy_server::GetConfig(GWObjects::RadiusProxyPoolList &C) {
|
||||
|
||||
@@ -29,7 +29,7 @@ namespace OpenWifi {
|
||||
|
||||
int Start() final;
|
||||
void Stop() final;
|
||||
inline bool Enabled() const { return enabled_; }
|
||||
inline bool Enabled() const { return Enabled_; }
|
||||
|
||||
void OnAccountingSocketReadable(const Poco::AutoPtr<Poco::Net::ReadableNotification>& pNf);
|
||||
void OnAuthenticationSocketReadable(const Poco::AutoPtr<Poco::Net::ReadableNotification>& pNf);
|
||||
@@ -44,7 +44,6 @@ namespace OpenWifi {
|
||||
void GetConfig(GWObjects::RadiusProxyPoolList &C);
|
||||
|
||||
void StartRADSECServers();
|
||||
void StartRADSECServer(const GWObjects::RadiusProxyServerEntry &E);
|
||||
void StopRADSECServers();
|
||||
|
||||
struct Destination {
|
||||
@@ -62,6 +61,10 @@ namespace OpenWifi {
|
||||
std::vector<std::string> realms;
|
||||
};
|
||||
|
||||
inline bool Continue() const {
|
||||
return Running_ && Enabled_ && !Pools_.empty();
|
||||
}
|
||||
|
||||
private:
|
||||
std::unique_ptr<Poco::Net::DatagramSocket> AccountingSocketV4_;
|
||||
std::unique_ptr<Poco::Net::DatagramSocket> AccountingSocketV6_;
|
||||
@@ -69,8 +72,8 @@ namespace OpenWifi {
|
||||
std::unique_ptr<Poco::Net::DatagramSocket> AuthenticationSocketV6_;
|
||||
std::unique_ptr<Poco::Net::DatagramSocket> CoASocketV4_;
|
||||
std::unique_ptr<Poco::Net::DatagramSocket> CoASocketV6_;
|
||||
Poco::Net::SocketReactor RadiusReactor_;
|
||||
Poco::Thread RadiusReactorThread_;
|
||||
std::unique_ptr<Poco::Net::SocketReactor> RadiusReactor_;
|
||||
Poco::Thread RadiusReactorThread_;
|
||||
|
||||
GWObjects::RadiusProxyPoolList PoolList_;
|
||||
std::string ConfigFilename_;
|
||||
@@ -87,10 +90,10 @@ namespace OpenWifi {
|
||||
};
|
||||
|
||||
std::vector<RadiusPool> Pools_;
|
||||
uint defaultPoolIndex_=0;
|
||||
bool enabled_=false;
|
||||
bool defaultIsRADSEC_=false;
|
||||
std::atomic_bool running_=false;
|
||||
uint DefaultPoolIndex_=0;
|
||||
bool Enabled_=false;
|
||||
bool DefaultIsRADSEC_=false;
|
||||
std::atomic_bool Running_=false;
|
||||
|
||||
RADIUS_proxy_server() noexcept:
|
||||
SubSystemServer("RADIUS-PROXY", "RADIUS-PROXY", "radius.proxy")
|
||||
|
||||
@@ -33,15 +33,17 @@ namespace OpenWifi {
|
||||
Logger_(Poco::Logger::get(fmt::format("RADSEC: {}@{}:{}",
|
||||
Server_.name ,
|
||||
Server_.ip,
|
||||
Server_.port)))
|
||||
{
|
||||
ReconnectThread_.start(*this);
|
||||
Server_.port))) {
|
||||
Start();
|
||||
}
|
||||
|
||||
~RADSEC_server() {
|
||||
if(ReconnectThread_.isRunning()) {
|
||||
Stop();
|
||||
}
|
||||
Stop();
|
||||
}
|
||||
|
||||
inline int Start() {
|
||||
ReconnectThread_.start(*this);
|
||||
return 0;
|
||||
}
|
||||
|
||||
inline void Stop() {
|
||||
@@ -52,12 +54,22 @@ namespace OpenWifi {
|
||||
}
|
||||
|
||||
inline void run() final {
|
||||
Poco::Thread::trySleep(3000);
|
||||
std::uint64_t LastStatus=0 ;
|
||||
auto RadSecKeepAlive = MicroServiceConfigGetInt("radsec.keepalive",120);
|
||||
while(TryAgain_) {
|
||||
if(!Connected_) {
|
||||
std::unique_lock G(Mutex_);
|
||||
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(3000);
|
||||
Poco::Thread::trySleep(!Connected_ ? 3000 : 10000);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -65,22 +77,23 @@ namespace OpenWifi {
|
||||
try {
|
||||
if (Connected_) {
|
||||
RADIUS::RadiusPacket P(buffer, length);
|
||||
// std::cout << serial_number << " Sending " << P.PacketType() << " " << length << " bytes" << std::endl;
|
||||
int sent_bytes;
|
||||
if (P.VerifyMessageAuthenticator(Server_.radsecSecret)) {
|
||||
poco_debug(Logger_,fmt::format("{}: {} Sending {} bytes", serial_number,
|
||||
P.PacketType(), length));
|
||||
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));
|
||||
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;
|
||||
}
|
||||
@@ -90,7 +103,7 @@ namespace OpenWifi {
|
||||
|
||||
try {
|
||||
auto NumberOfReceivedBytes = Socket_->receiveBytes(Buffer,sizeof(Buffer));
|
||||
if(NumberOfReceivedBytes>40) {
|
||||
if(NumberOfReceivedBytes>=20) {
|
||||
RADIUS::RadiusPacket P(Buffer,NumberOfReceivedBytes);
|
||||
if (P.IsAuthentication()) {
|
||||
auto SerialNumber = P.ExtractSerialNumberFromProxyState();
|
||||
@@ -101,9 +114,7 @@ namespace OpenWifi {
|
||||
AP_WS_Server()->SendRadiusAuthenticationData(SerialNumber, Buffer,
|
||||
NumberOfReceivedBytes);
|
||||
} else {
|
||||
poco_debug(Logger_,
|
||||
fmt::format("Invalid AUTH packet received in proxy dropped. No serial number Source={}",
|
||||
Socket_->address().toString()));
|
||||
poco_debug(Logger_, "AUTH packet dropped.");
|
||||
}
|
||||
} else if (P.IsAccounting()) {
|
||||
auto SerialNumber = P.ExtractSerialNumberFromProxyState();
|
||||
@@ -114,53 +125,72 @@ namespace OpenWifi {
|
||||
AP_WS_Server()->SendRadiusAccountingData(SerialNumber, Buffer,
|
||||
NumberOfReceivedBytes);
|
||||
} else {
|
||||
poco_debug(Logger_,
|
||||
fmt::format("Invalid ACCT packet received in proxy dropped. No serial number Source={}",
|
||||
Socket_->address().toString()));
|
||||
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) {
|
||||
std::cout << "onError" << std::endl;
|
||||
poco_warning(Logger_,"Socker error. Terminating connection.");
|
||||
Disconnect();
|
||||
}
|
||||
|
||||
inline void onShutdown([[maybe_unused]] const Poco::AutoPtr<Poco::Net::ShutdownNotification>& pNf) {
|
||||
std::cout << "onShutdown" << std::endl;
|
||||
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<Poco::TemporaryFile> CaCertFiles_;
|
||||
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(Poco::TemporaryFile(MicroServiceDataDirectory()));
|
||||
DecodeFile(CaCertFiles_[CaCertFiles_.size()-1].path(), cert);
|
||||
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());
|
||||
Poco::Crypto::X509Certificate cert(ca->path());
|
||||
SecureContext->addCertificateAuthority(cert);
|
||||
}
|
||||
|
||||
@@ -172,7 +202,10 @@ namespace OpenWifi {
|
||||
poco_information(Logger_, "Attempting to connect");
|
||||
Socket_->connect(Destination, Poco::Timespan(100, 0));
|
||||
Socket_->completeHandshake();
|
||||
Socket_->verifyPeerCertificate();
|
||||
|
||||
if(!Server_.allowSelfSigned) {
|
||||
Socket_->verifyPeerCertificate();
|
||||
}
|
||||
|
||||
if(Socket_->havePeerCertificate()) {
|
||||
Peer_Cert_ = std::make_unique<Poco::Crypto::X509Certificate>(Socket_->peerCertificate());
|
||||
@@ -194,9 +227,6 @@ namespace OpenWifi {
|
||||
*Socket_,
|
||||
Poco::NObserver<RADSEC_server, Poco::Net::ShutdownNotification>(
|
||||
*this, &RADSEC_server::onShutdown));
|
||||
Socket_->setBlocking(false);
|
||||
Socket_->setNoDelay(true);
|
||||
Socket_->setKeepAlive(true);
|
||||
|
||||
Connected_ = true;
|
||||
poco_information(Logger_,fmt::format("Connected. CN={}",CommonName()));
|
||||
@@ -216,7 +246,7 @@ namespace OpenWifi {
|
||||
|
||||
inline void Disconnect() {
|
||||
if(Connected_) {
|
||||
std::unique_lock G(Mutex_);
|
||||
std::lock_guard G(LocalMutex_);
|
||||
|
||||
Reactor_.removeEventHandler(
|
||||
*Socket_, Poco::NObserver<RADSEC_server, Poco::Net::ReadableNotification>(
|
||||
@@ -227,6 +257,7 @@ namespace OpenWifi {
|
||||
Reactor_.removeEventHandler(
|
||||
*Socket_, Poco::NObserver<RADSEC_server, Poco::Net::ShutdownNotification>(
|
||||
*this, &RADSEC_server::onShutdown));
|
||||
Socket_->close();
|
||||
Connected_ = false;
|
||||
}
|
||||
poco_information(Logger_,"Disconnecting.");
|
||||
@@ -259,7 +290,7 @@ namespace OpenWifi {
|
||||
}
|
||||
|
||||
private:
|
||||
std::recursive_mutex Mutex_;
|
||||
std::recursive_mutex LocalMutex_;
|
||||
Poco::Net::SocketReactor &Reactor_;
|
||||
GWObjects::RadiusProxyServerEntry Server_;
|
||||
Poco::Logger &Logger_;
|
||||
|
||||
@@ -34,6 +34,7 @@ namespace OpenWifi::RESTAPI_RPC {
|
||||
}
|
||||
|
||||
void WaitForCommand(uint64_t RPCID,
|
||||
APCommands::Commands Command,
|
||||
bool RetryLater,
|
||||
GWObjects::CommandDetails &Cmd,
|
||||
Poco::JSON::Object & Params,
|
||||
@@ -64,7 +65,7 @@ namespace OpenWifi::RESTAPI_RPC {
|
||||
bool Sent;
|
||||
std::chrono::time_point<std::chrono::high_resolution_clock> rpc_submitted = std::chrono::high_resolution_clock::now();
|
||||
std::shared_ptr<CommandManager::promise_type_t> rpc_endpoint =
|
||||
CommandManager()->PostCommand(RPCID, Cmd.SerialNumber, Cmd.Command, Params, Cmd.UUID, Sent);
|
||||
CommandManager()->PostCommand(RPCID, Command, Cmd.SerialNumber, Cmd.Command, Params, Cmd.UUID, Sent);
|
||||
|
||||
if(RetryLater && (!Sent || rpc_endpoint== nullptr)) {
|
||||
Logger.information(fmt::format("{},{}: Pending completion. Device is not connected.", Cmd.UUID, RPCID));
|
||||
|
||||
@@ -18,10 +18,13 @@
|
||||
#include "StorageService.h"
|
||||
#include "framework/RESTAPI_Handler.h"
|
||||
|
||||
#include "framework/ow_constants.h"
|
||||
|
||||
namespace OpenWifi::RESTAPI_RPC {
|
||||
|
||||
void WaitForCommand(
|
||||
uint64_t RPCID,
|
||||
APCommands::Commands Command,
|
||||
bool RetryLater,
|
||||
GWObjects::CommandDetails &Cmd,
|
||||
Poco::JSON::Object & Params,
|
||||
|
||||
@@ -20,6 +20,8 @@ namespace OpenWifi {
|
||||
return BadRequest(RESTAPI::Errors::MissingSerialNumber);
|
||||
}
|
||||
|
||||
poco_debug(Logger(),fmt::format("BLACKLIST-DELETE: {}", SerialNumber));
|
||||
|
||||
GWObjects::BlackListedDevice D;
|
||||
if(!StorageService()->GetBlackListDevice(SerialNumber, D)) {
|
||||
return NotFound();
|
||||
@@ -38,14 +40,12 @@ namespace OpenWifi {
|
||||
return BadRequest(RESTAPI::Errors::MissingSerialNumber);
|
||||
}
|
||||
|
||||
poco_debug(Logger(),fmt::format("BLACKLIST-GET: {}", SerialNumber));
|
||||
GWObjects::BlackListedDevice D;
|
||||
if(!StorageService()->GetBlackListDevice(SerialNumber, D)) {
|
||||
return NotFound();
|
||||
}
|
||||
|
||||
Poco::JSON::Object Answer;
|
||||
D.to_json(Answer);
|
||||
return ReturnObject(Answer);
|
||||
return Object(D);
|
||||
}
|
||||
|
||||
void RESTAPI_blacklist::DoPost() {
|
||||
@@ -60,6 +60,8 @@ namespace OpenWifi {
|
||||
return BadRequest(RESTAPI::Errors::MissingSerialNumber);
|
||||
}
|
||||
|
||||
poco_debug(Logger(),fmt::format("BLACKLIST-POST: {}", D.serialNumber));
|
||||
|
||||
Poco::toLowerInPlace(D.serialNumber);
|
||||
if(StorageService()->IsBlackListed(D.serialNumber)) {
|
||||
return BadRequest(RESTAPI::Errors::SerialNumberExists);
|
||||
@@ -70,12 +72,8 @@ namespace OpenWifi {
|
||||
|
||||
if(StorageService()->AddBlackListDevice(D)) {
|
||||
GWObjects::BlackListedDevice CreatedDevice;
|
||||
|
||||
StorageService()->GetBlackListDevice(D.serialNumber,CreatedDevice);
|
||||
Poco::JSON::Object Answer;
|
||||
|
||||
CreatedDevice.to_json(Answer);
|
||||
return ReturnObject(Answer);
|
||||
return Object(CreatedDevice);
|
||||
}
|
||||
return BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
|
||||
}
|
||||
@@ -92,6 +90,8 @@ namespace OpenWifi {
|
||||
return BadRequest(RESTAPI::Errors::InvalidJSONDocument);
|
||||
}
|
||||
|
||||
poco_debug(Logger(),fmt::format("BLACKLIST-PUT: {}", SerialNumber));
|
||||
|
||||
GWObjects::BlackListedDevice NewDevice;
|
||||
if(!NewDevice.from_json(Obj)) {
|
||||
return BadRequest(RESTAPI::Errors::InvalidJSONDocument);
|
||||
@@ -104,10 +104,7 @@ namespace OpenWifi {
|
||||
GWObjects::BlackListedDevice CreatedDevice;
|
||||
|
||||
StorageService()->GetBlackListDevice(SerialNumber,CreatedDevice);
|
||||
Poco::JSON::Object Answer;
|
||||
|
||||
CreatedDevice.to_json(Answer);
|
||||
return ReturnObject(Answer);
|
||||
return Object(CreatedDevice);
|
||||
}
|
||||
return BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
|
||||
}
|
||||
|
||||
@@ -10,22 +10,16 @@
|
||||
namespace OpenWifi {
|
||||
void RESTAPI_blacklist_list::DoGet() {
|
||||
|
||||
std::vector<GWObjects::BlackListedDevice> Devices;
|
||||
poco_debug(Logger(),fmt::format("BLACKLIST-GET: Device serial number list"));
|
||||
|
||||
Poco::JSON::Array Arr;
|
||||
Poco::JSON::Object Answer;
|
||||
std::vector<GWObjects::BlackListedDevice> Devices;
|
||||
|
||||
if(QB_.CountOnly) {
|
||||
auto Count = StorageService()->GetBlackListDeviceCount();
|
||||
return ReturnCountOnly(Count);
|
||||
} else if(StorageService()->GetBlackListDevices(QB_.Offset, QB_.Limit, Devices)) {
|
||||
for(const auto &i:Devices) {
|
||||
Poco::JSON::Object O;
|
||||
i.to_json(O);
|
||||
Arr.add(O);
|
||||
}
|
||||
return Object("devices",Devices);
|
||||
}
|
||||
Answer.set("devices", Arr);
|
||||
return ReturnObject(Answer);
|
||||
NotFound();
|
||||
}
|
||||
}
|
||||
@@ -20,9 +20,7 @@ namespace OpenWifi {
|
||||
|
||||
GWObjects::CommandDetails Command;
|
||||
if (StorageService()->GetCommand(CommandUUID, Command)) {
|
||||
Poco::JSON::Object RetObj;
|
||||
Command.to_json(RetObj);
|
||||
return ReturnObject(RetObj);
|
||||
return Object(Command);
|
||||
}
|
||||
return NotFound();
|
||||
}
|
||||
|
||||
@@ -24,15 +24,7 @@ namespace OpenWifi {
|
||||
StorageService()->GetCommands(SerialNumber, QB_.StartDate, QB_.EndDate, QB_.Offset, QB_.Limit,
|
||||
Commands);
|
||||
}
|
||||
Poco::JSON::Array ArrayObj;
|
||||
for (const auto &i : Commands) {
|
||||
Poco::JSON::Object Obj;
|
||||
i.to_json(Obj);
|
||||
ArrayObj.add(Obj);
|
||||
}
|
||||
Poco::JSON::Object RetObj;
|
||||
RetObj.set(RESTAPI::Protocol::COMMANDS, ArrayObj);
|
||||
ReturnObject(RetObj);
|
||||
return Object(RESTAPI::Protocol::COMMANDS, Commands);
|
||||
}
|
||||
|
||||
void RESTAPI_commands::DoDelete() {
|
||||
|
||||
@@ -22,9 +22,7 @@ namespace OpenWifi {
|
||||
std::string Name = ORM::Escape(GetBinding(RESTAPI::Protocol::NAME, ""));
|
||||
GWObjects::DefaultConfiguration DefConfig;
|
||||
if (StorageService()->GetDefaultConfiguration(Name, DefConfig)) {
|
||||
Poco::JSON::Object Obj;
|
||||
DefConfig.to_json(Obj);
|
||||
return ReturnObject(Obj);
|
||||
return Object(DefConfig);
|
||||
}
|
||||
NotFound();
|
||||
}
|
||||
@@ -106,12 +104,9 @@ namespace OpenWifi {
|
||||
GWObjects::DefaultConfiguration ModifiedConfig;
|
||||
|
||||
StorageService()->GetDefaultConfiguration(Name,ModifiedConfig);
|
||||
Poco::JSON::Object Answer;
|
||||
ModifiedConfig.to_json(Answer);
|
||||
return ReturnObject(Answer);
|
||||
return Object(ModifiedConfig);
|
||||
}
|
||||
|
||||
BadRequest(RESTAPI::Errors::RecordNotUpdated);
|
||||
|
||||
}
|
||||
}
|
||||
@@ -23,16 +23,6 @@ namespace OpenWifi {
|
||||
|
||||
std::vector<GWObjects::DefaultConfiguration> DefConfigs;
|
||||
StorageService()->GetDefaultConfigurations(QB_.Offset, QB_.Limit, DefConfigs);
|
||||
|
||||
Poco::JSON::Array Objects;
|
||||
for (const auto &i : DefConfigs) {
|
||||
Poco::JSON::Object Obj;
|
||||
i.to_json(Obj);
|
||||
Objects.add(Obj);
|
||||
}
|
||||
|
||||
Poco::JSON::Object RetObj;
|
||||
RetObj.set(RESTAPI::Protocol::CONFIGURATIONS, Objects);
|
||||
ReturnObject(RetObj);
|
||||
return Object(RESTAPI::Protocol::CONFIGURATIONS, DefConfigs);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,9 +8,11 @@
|
||||
|
||||
namespace OpenWifi {
|
||||
void RESTAPI_deviceDashboardHandler::DoGet() {
|
||||
Daemon()->GetDashboard().Create();
|
||||
Poco::JSON::Object Answer;
|
||||
Daemon()->GetDashboard().Report().to_json(Answer);
|
||||
ReturnObject(Answer);
|
||||
poco_information(Logger(),fmt::format("GET-DASHBOARD: {}", Requester()));
|
||||
GWObjects::Dashboard Data;
|
||||
if(Daemon()->GetDashboard().Get(Data, Logger())) {
|
||||
return Object(Data);
|
||||
}
|
||||
return BadRequest(RESTAPI::Errors::InternalError);
|
||||
}
|
||||
}
|
||||
@@ -21,6 +21,8 @@
|
||||
#include "TelemetryStream.h"
|
||||
#include "CommandManager.h"
|
||||
|
||||
#include "SignatureMgr.h"
|
||||
|
||||
#include "framework/ConfigurationValidator.h"
|
||||
#include "framework/KafkaTopics.h"
|
||||
#include "framework/ow_constants.h"
|
||||
@@ -50,33 +52,40 @@ namespace OpenWifi {
|
||||
return NotFound();
|
||||
}
|
||||
|
||||
auto Command = APCommands::to_apcommand(Command_.c_str());
|
||||
if(Command==APCommands::Commands::unknown) {
|
||||
return BadRequest(RESTAPI::Errors::InvalidCommand);
|
||||
}
|
||||
|
||||
SerialNumberInt_ = Utils::SerialNumberToInt(SerialNumber_);
|
||||
Poco::Thread::current()->setName(fmt::format("{}:{}:{}", Command_, TransactionId_, SerialNumber_));
|
||||
|
||||
if (Command_ == RESTAPI::Protocol::CAPABILITIES){
|
||||
return GetCapabilities();
|
||||
} else if (Command_ == RESTAPI::Protocol::LOGS) {
|
||||
return GetLogs();
|
||||
} else if (Command_ == RESTAPI::Protocol::HEALTHCHECKS) {
|
||||
return GetChecks();
|
||||
} else if (Command_ == RESTAPI::Protocol::STATISTICS) {
|
||||
return GetStatistics();
|
||||
} else if (Command_ == RESTAPI::Protocol::STATUS) {
|
||||
return GetStatus();
|
||||
} else if (Command_ == RESTAPI::Protocol::RTTY) {
|
||||
AP_Restrictions Restrictions;
|
||||
if(!AP_WS_Server()->Connected(SerialNumberInt_, Restrictions)) {
|
||||
CallCanceled(Command_.c_str(), RESTAPI::Errors::DeviceNotConnected);
|
||||
return BadRequest(RESTAPI::Errors::DeviceNotConnected);
|
||||
}
|
||||
auto UUID = MicroServiceCreateUUID();
|
||||
auto RPC = CommandManager()->Next_RPC_ID();
|
||||
poco_debug(Logger_,fmt::format("Command rtty TID={} can proceed. Identified as {} and RPCID as {}. thr_id={}",
|
||||
TransactionId_, UUID, RPC,
|
||||
Poco::Thread::current()->id()));
|
||||
return Rtty(UUID,RPC,60000ms, Restrictions);
|
||||
} else {
|
||||
return BadRequest(RESTAPI::Errors::InvalidCommand);
|
||||
switch(Command) {
|
||||
case APCommands::Commands::capabilities:
|
||||
return GetCapabilities();
|
||||
case APCommands::Commands::logs:
|
||||
return GetLogs();
|
||||
case APCommands::Commands::healthchecks:
|
||||
return GetChecks();
|
||||
case APCommands::Commands::statistics:
|
||||
return GetStatistics();
|
||||
case APCommands::Commands::status:
|
||||
return GetStatus();
|
||||
case APCommands::Commands::rtty: {
|
||||
GWObjects::DeviceRestrictions Restrictions;
|
||||
if(!AP_WS_Server()->Connected(SerialNumberInt_, Restrictions)) {
|
||||
CallCanceled(Command_.c_str(), RESTAPI::Errors::DeviceNotConnected);
|
||||
return BadRequest(RESTAPI::Errors::DeviceNotConnected);
|
||||
}
|
||||
auto UUID = MicroServiceCreateUUID();
|
||||
auto RPC = CommandManager()->Next_RPC_ID();
|
||||
poco_debug(Logger_,fmt::format("Command rtty TID={} can proceed. Identified as {} and RPCID as {}. thr_id={}",
|
||||
TransactionId_, UUID, RPC,
|
||||
Poco::Thread::current()->id()));
|
||||
return Rtty(UUID,RPC,60000ms, Restrictions);
|
||||
};
|
||||
default:
|
||||
return BadRequest(RESTAPI::Errors::InvalidCommand);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -94,44 +103,50 @@ namespace OpenWifi {
|
||||
return NotFound();
|
||||
}
|
||||
|
||||
auto Command = APCommands::to_apcommand(Command_.c_str());
|
||||
if(Command==APCommands::Commands::unknown) {
|
||||
return BadRequest(RESTAPI::Errors::InvalidCommand);
|
||||
}
|
||||
|
||||
SerialNumberInt_ = Utils::SerialNumberToInt(SerialNumber_);
|
||||
Poco::Thread::current()->setName(fmt::format("{}:{}:{}",Command_, TransactionId_,SerialNumber_));
|
||||
|
||||
if (Command_ == RESTAPI::Protocol::CAPABILITIES) {
|
||||
switch(Command) {
|
||||
case APCommands::Commands::capabilities:
|
||||
return DeleteCapabilities();
|
||||
} else if (Command_ == RESTAPI::Protocol::LOGS){
|
||||
case APCommands::Commands::logs:
|
||||
return DeleteLogs();
|
||||
} else if (Command_ == RESTAPI::Protocol::HEALTHCHECKS){
|
||||
case APCommands::Commands::healthchecks:
|
||||
return DeleteChecks();
|
||||
} else if (Command_ == RESTAPI::Protocol::STATISTICS) {
|
||||
case APCommands::Commands::statistics:
|
||||
return DeleteStatistics();
|
||||
} else {
|
||||
default:
|
||||
return BadRequest(RESTAPI::Errors::InvalidCommand);
|
||||
}
|
||||
}
|
||||
|
||||
struct PostDeviceCommand {
|
||||
const char * Command;
|
||||
bool AllowParallel=false;
|
||||
bool RequireConnection = true;
|
||||
void (RESTAPI_device_commandHandler::*funPtr)(const std::string &, std::uint64_t, std::chrono::milliseconds, const AP_Restrictions &R );
|
||||
APCommands::Commands Command=APCommands::Commands::unknown;
|
||||
bool AllowParallel=false;
|
||||
bool RequireConnection = true;
|
||||
void (RESTAPI_device_commandHandler::*funPtr)(const std::string &, std::uint64_t, std::chrono::milliseconds, const GWObjects::DeviceRestrictions &R );
|
||||
std::chrono::milliseconds Timeout=120ms;
|
||||
};
|
||||
|
||||
const std::vector<PostDeviceCommand> PostCommands =
|
||||
static const std::vector<PostDeviceCommand> PostCommands =
|
||||
{
|
||||
{ RESTAPI::Protocol::CONFIGURE, false, false, &RESTAPI_device_commandHandler::Configure, 120000ms },
|
||||
{ RESTAPI::Protocol::UPGRADE, false, false, &RESTAPI_device_commandHandler::Upgrade, 30000ms },
|
||||
{ RESTAPI::Protocol::REBOOT, false, true, &RESTAPI_device_commandHandler::Reboot, 30000ms },
|
||||
{ RESTAPI::Protocol::FACTORY, false, false, &RESTAPI_device_commandHandler::Factory, 30000ms },
|
||||
{ RESTAPI::Protocol::LEDS, false, true, &RESTAPI_device_commandHandler::LEDs, 120000ms },
|
||||
{ RESTAPI::Protocol::TRACE, false, true, &RESTAPI_device_commandHandler::Trace, 300000ms },
|
||||
{ RESTAPI::Protocol::REQUEST, false, true, &RESTAPI_device_commandHandler::MakeRequest, 120000ms },
|
||||
{ RESTAPI::Protocol::WIFISCAN, false, true, &RESTAPI_device_commandHandler::WifiScan, 120000ms },
|
||||
{ RESTAPI::Protocol::EVENTQUEUE, false, true, &RESTAPI_device_commandHandler::EventQueue, 30000ms },
|
||||
{ RESTAPI::Protocol::TELEMETRY, false, true, &RESTAPI_device_commandHandler::Telemetry, 30000ms },
|
||||
{ RESTAPI::Protocol::PING, false, true, &RESTAPI_device_commandHandler::Ping, 60000ms },
|
||||
{ RESTAPI::Protocol::SCRIPT, false, true, &RESTAPI_device_commandHandler::Script, 300000ms }
|
||||
{ APCommands::Commands::configure, false, false, &RESTAPI_device_commandHandler::Configure, 120000ms },
|
||||
{ APCommands::Commands::upgrade, false, false, &RESTAPI_device_commandHandler::Upgrade, 30000ms },
|
||||
{ APCommands::Commands::reboot, false, true, &RESTAPI_device_commandHandler::Reboot, 30000ms },
|
||||
{ APCommands::Commands::factory, false, false, &RESTAPI_device_commandHandler::Factory, 30000ms },
|
||||
{ APCommands::Commands::leds, false, true, &RESTAPI_device_commandHandler::LEDs, 120000ms },
|
||||
{ APCommands::Commands::trace, false, true, &RESTAPI_device_commandHandler::Trace, 300000ms },
|
||||
{ APCommands::Commands::request, false, true, &RESTAPI_device_commandHandler::MakeRequest, 120000ms },
|
||||
{ APCommands::Commands::wifiscan, false, true, &RESTAPI_device_commandHandler::WifiScan, 120000ms },
|
||||
{ APCommands::Commands::eventqueue, false, true, &RESTAPI_device_commandHandler::EventQueue, 30000ms },
|
||||
{ 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 }
|
||||
};
|
||||
|
||||
void RESTAPI_device_commandHandler::DoPost() {
|
||||
@@ -141,32 +156,39 @@ namespace OpenWifi {
|
||||
if(!Utils::NormalizeMac(SerialNumber_)) {
|
||||
return BadRequest(RESTAPI::Errors::MissingSerialNumber);
|
||||
}
|
||||
|
||||
auto Command = APCommands::to_apcommand(Command_.c_str());
|
||||
if(Command==APCommands::Commands::unknown) {
|
||||
return BadRequest(RESTAPI::Errors::InvalidCommand);
|
||||
}
|
||||
|
||||
SerialNumberInt_ = Utils::SerialNumberToInt(SerialNumber_);
|
||||
GWObjects::Device TheDevice;
|
||||
if(!StorageService()->GetDevice(SerialNumber_,TheDevice)) {
|
||||
return NotFound();
|
||||
}
|
||||
|
||||
for(const auto &Command:PostCommands) {
|
||||
if(Command_==Command.Command) {
|
||||
Poco::Thread::current()->setName(fmt::format("{}:{}:{}",Command.Command, TransactionId_,SerialNumber_));
|
||||
AP_Restrictions Restrictions;
|
||||
if(Command.RequireConnection && !AP_WS_Server()->Connected(SerialNumberInt_, Restrictions)) {
|
||||
CallCanceled(Command.Command, RESTAPI::Errors::DeviceNotConnected);
|
||||
for(const auto &PostCommand:PostCommands) {
|
||||
if(Command==PostCommand.Command) {
|
||||
Poco::Thread::current()->setName(fmt::format("{}:{}:{}",Command_, TransactionId_,SerialNumber_));
|
||||
GWObjects::DeviceRestrictions Restrictions;
|
||||
if(PostCommand.RequireConnection && !AP_WS_Server()->Connected(SerialNumberInt_, Restrictions)) {
|
||||
CallCanceled(Command_.c_str(), RESTAPI::Errors::DeviceNotConnected);
|
||||
return BadRequest(RESTAPI::Errors::DeviceNotConnected);
|
||||
}
|
||||
std::string Command_UUID, CommandName;
|
||||
if(!Command.AllowParallel && CommandManager()->CommandRunningForDevice(SerialNumberInt_,Command_UUID,CommandName)) {
|
||||
auto Extra = fmt::format("UUID={} Command={}", Command_UUID, CommandName);
|
||||
CallCanceled(Command.Command, RESTAPI::Errors::DeviceIsAlreadyBusy, Extra);
|
||||
std::string Command_UUID;
|
||||
APCommands::Commands CommandName;
|
||||
if(!PostCommand.AllowParallel && CommandManager()->CommandRunningForDevice(SerialNumberInt_,Command_UUID,CommandName)) {
|
||||
auto Extra = fmt::format("UUID={} Command={}", Command_UUID, APCommands::to_string(CommandName));
|
||||
CallCanceled(Command_.c_str(), RESTAPI::Errors::DeviceIsAlreadyBusy, Extra);
|
||||
return BadRequest(RESTAPI::Errors::DeviceIsAlreadyBusy, Extra);
|
||||
}
|
||||
auto UUID = MicroServiceCreateUUID();
|
||||
auto RPC = CommandManager()->Next_RPC_ID();
|
||||
poco_debug(Logger_,fmt::format("Command {} TID={} can proceed. Identified as {} and RPCID as {}. thr_id={}",
|
||||
Command.Command, TransactionId_, UUID, RPC,
|
||||
Command_, TransactionId_, UUID, RPC,
|
||||
Poco::Thread::current()->id()));
|
||||
return (*this.*Command.funPtr)(UUID,RPC,Command.Timeout, Restrictions);
|
||||
return (*this.*PostCommand.funPtr)(UUID,RPC,PostCommand.Timeout, Restrictions);
|
||||
}
|
||||
}
|
||||
return BadRequest(RESTAPI::Errors::InvalidCommand);
|
||||
@@ -207,6 +229,9 @@ namespace OpenWifi {
|
||||
if (AP_WS_Server()->GetStatistics(SerialNumber_, Stats) && !Stats.empty()) {
|
||||
return ReturnRawJSON(Stats);
|
||||
}
|
||||
if(AP_WS_Server()->Connected(SerialNumberInt_)) {
|
||||
return BadRequest(RESTAPI::Errors::NoDeviceStatisticsYet);
|
||||
}
|
||||
return BadRequest(RESTAPI::Errors::DeviceNotConnected);
|
||||
}
|
||||
|
||||
@@ -226,12 +251,13 @@ namespace OpenWifi {
|
||||
QB_.Offset, QB_.Limit, Stats);
|
||||
}
|
||||
|
||||
Poco::JSON::Array ArrayObj;
|
||||
Poco::JSON::Array::Ptr ArrayObj = Poco::SharedPtr<Poco::JSON::Array>(new Poco::JSON::Array);
|
||||
for (const auto &i : Stats) {
|
||||
Poco::JSON::Object Obj;
|
||||
i.to_json(Obj);
|
||||
ArrayObj.add(Obj);
|
||||
Poco::JSON::Object::Ptr Obj = Poco::SharedPtr<Poco::JSON::Object>(new Poco::JSON::Object);
|
||||
i.to_json(*Obj);
|
||||
ArrayObj->add(Obj);
|
||||
}
|
||||
|
||||
Poco::JSON::Object RetObj;
|
||||
RetObj.set(RESTAPI::Protocol::DATA, ArrayObj);
|
||||
RetObj.set(RESTAPI::Protocol::SERIALNUMBER, SerialNumber_);
|
||||
@@ -349,7 +375,7 @@ namespace OpenWifi {
|
||||
BadRequest(RESTAPI::Errors::NoRecordsDeleted);
|
||||
}
|
||||
|
||||
void RESTAPI_device_commandHandler::Ping(const std::string &CMD_UUID, uint64_t CMD_RPC, std::chrono::milliseconds timeout, [[maybe_unused]] const AP_Restrictions &R) {
|
||||
void RESTAPI_device_commandHandler::Ping(const std::string &CMD_UUID, uint64_t CMD_RPC, std::chrono::milliseconds timeout, [[maybe_unused]] const GWObjects::DeviceRestrictions &R) {
|
||||
poco_information(Logger_,fmt::format("PING({},{}): TID={} user={} serial={}", CMD_UUID, CMD_RPC, TransactionId_, Requester(), SerialNumber_));
|
||||
const auto &Obj = ParsedBody_;
|
||||
if (Obj->has(RESTAPI::Protocol::SERIALNUMBER)) {
|
||||
@@ -373,7 +399,7 @@ namespace OpenWifi {
|
||||
Params.stringify(ParamStream);
|
||||
Cmd.Details = ParamStream.str();
|
||||
|
||||
RESTAPI_RPC::WaitForCommand(CMD_RPC,false,Cmd, Params, *Request, *Response, timeout, nullptr, nullptr, Logger_);
|
||||
RESTAPI_RPC::WaitForCommand(CMD_RPC, APCommands::Commands::ping,false,Cmd, Params, *Request, *Response, timeout, nullptr, nullptr, Logger_);
|
||||
|
||||
GWObjects::CommandDetails Cmd2;
|
||||
if(StorageService()->GetCommand(CMD_UUID,Cmd2)) {
|
||||
@@ -409,12 +435,8 @@ namespace OpenWifi {
|
||||
return t=="shell" || t=="bundle";
|
||||
}
|
||||
|
||||
void RESTAPI_device_commandHandler::Script(const std::string &CMD_UUID, uint64_t CMD_RPC, std::chrono::milliseconds timeout, [[maybe_unused]] const AP_Restrictions &R) {
|
||||
void RESTAPI_device_commandHandler::Script(const std::string &CMD_UUID, uint64_t CMD_RPC, std::chrono::milliseconds timeout, [[maybe_unused]] const GWObjects::DeviceRestrictions &R) {
|
||||
poco_information(Logger_,fmt::format("SCRIPT({},{}): TID={} user={} serial={}", CMD_UUID, CMD_RPC, TransactionId_, Requester(), SerialNumber_));
|
||||
if(!Internal_ && UserInfo_.userinfo.userRole!=SecurityObjects::ROOT) {
|
||||
CallCanceled("SCRIPT", CMD_UUID, CMD_RPC,RESTAPI::Errors::ACCESS_DENIED);
|
||||
return UnAuthorized(RESTAPI::Errors::ACCESS_DENIED);
|
||||
}
|
||||
|
||||
const auto &Obj = ParsedBody_;
|
||||
GWObjects::ScriptRequest SCR;
|
||||
@@ -423,11 +445,25 @@ namespace OpenWifi {
|
||||
return BadRequest(RESTAPI::Errors::InvalidJSONDocument);
|
||||
}
|
||||
|
||||
if (SCR.serialNumber.empty() ||
|
||||
SCR.script.empty() ||
|
||||
!ValidateScriptType(SCR.type)) {
|
||||
CallCanceled("SCRIPT", CMD_UUID, CMD_RPC,RESTAPI::Errors::MissingOrInvalidParameters);
|
||||
return BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
|
||||
bool DiagnosticScript = (SCR.type=="diagnostic");
|
||||
if(!SCR.script.empty() && !SCR.scriptId.empty()) {
|
||||
CallCanceled("SCRIPT", CMD_UUID, CMD_RPC,RESTAPI::Errors::InvalidScriptSelection);
|
||||
return UnAuthorized(RESTAPI::Errors::InvalidScriptSelection);
|
||||
}
|
||||
|
||||
if(!Internal_ && UserInfo_.userinfo.userRole!=SecurityObjects::ROOT && SCR.scriptId.empty()) {
|
||||
CallCanceled("SCRIPT", CMD_UUID, CMD_RPC,RESTAPI::Errors::ACCESS_DENIED);
|
||||
return UnAuthorized(RESTAPI::Errors::ACCESS_DENIED);
|
||||
}
|
||||
|
||||
if (SCR.script.empty() && SCR.scriptId.empty() && !DiagnosticScript) {
|
||||
CallCanceled("SCRIPT", CMD_UUID, CMD_RPC,RESTAPI::Errors::InvalidScriptSelection);
|
||||
return BadRequest(RESTAPI::Errors::InvalidScriptSelection);
|
||||
}
|
||||
|
||||
if(DiagnosticScript && (!SCR.scriptId.empty() || !SCR.script.empty())){
|
||||
CallCanceled("SCRIPT", CMD_UUID, CMD_RPC,RESTAPI::Errors::InvalidScriptSelection);
|
||||
return BadRequest(RESTAPI::Errors::InvalidScriptSelection);
|
||||
}
|
||||
|
||||
if (SerialNumber_ != SCR.serialNumber) {
|
||||
@@ -435,13 +471,48 @@ namespace OpenWifi {
|
||||
return BadRequest(RESTAPI::Errors::SerialNumberMismatch);
|
||||
}
|
||||
|
||||
if(!SCR.uri.empty() && !Utils::ValidateURI(SCR.uri)) {
|
||||
return BadRequest(RESTAPI::Errors::InvalidURI);
|
||||
}
|
||||
|
||||
GWObjects::Device D;
|
||||
if(!StorageService()->GetDevice(SerialNumber_,D)) {
|
||||
return NotFound();
|
||||
}
|
||||
|
||||
if(D.restrictedDevice && SCR.signature.empty()) {
|
||||
return BadRequest(RESTAPI::Errors::DeviceRequiresSignature);
|
||||
if(!SCR.scriptId.empty()) {
|
||||
GWObjects::ScriptEntry Existing;
|
||||
if(!StorageService()->ScriptDB().GetRecord("id",SCR.scriptId,Existing)) {
|
||||
CallCanceled("SCRIPT", CMD_UUID, CMD_RPC,RESTAPI::Errors::MissingOrInvalidParameters);
|
||||
return BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
|
||||
}
|
||||
|
||||
// verify the role...
|
||||
if(Existing.restricted.empty() && UserInfo_.userinfo.userRole!=SecurityObjects::ROOT) {
|
||||
CallCanceled("SCRIPT", CMD_UUID, CMD_RPC,RESTAPI::Errors::ACCESS_DENIED);
|
||||
return UnAuthorized(RESTAPI::Errors::ACCESS_DENIED);
|
||||
}
|
||||
|
||||
if(UserInfo_.userinfo.userRole!=SecurityObjects::ROOT) {
|
||||
if (std::find(Existing.restricted.begin(), Existing.restricted.end(),
|
||||
SecurityObjects::UserTypeToString(UserInfo_.userinfo.userRole)) ==
|
||||
end(Existing.restricted)) {
|
||||
CallCanceled("SCRIPT", CMD_UUID, CMD_RPC, RESTAPI::Errors::ACCESS_DENIED);
|
||||
return UnAuthorized(RESTAPI::Errors::ACCESS_DENIED);
|
||||
}
|
||||
}
|
||||
poco_information(Logger_,fmt::format("SCRIPT({},{}): TID={} Name={}", CMD_UUID, CMD_RPC, TransactionId_, Existing.name));
|
||||
SCR.script = Existing.content;
|
||||
SCR.type = Existing.type;
|
||||
if(!ParsedBody_->has("deferred"))
|
||||
SCR.deferred = Existing.deferred;
|
||||
if(!ParsedBody_->has("timeout"))
|
||||
SCR.timeout = Existing.timeout;
|
||||
} else {
|
||||
if(!DiagnosticScript && !ValidateScriptType(SCR.type)) {
|
||||
CallCanceled("SCRIPT", CMD_UUID, CMD_RPC,RESTAPI::Errors::MissingOrInvalidParameters);
|
||||
return BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
|
||||
}
|
||||
}
|
||||
|
||||
uint64_t ap_timeout = SCR.timeout==0 ? 30 : SCR.timeout;
|
||||
@@ -469,8 +540,21 @@ namespace OpenWifi {
|
||||
if(!SCR.signature.empty()) {
|
||||
Params.set(uCentralProtocol::SIGNATURE, SCR.signature);
|
||||
}
|
||||
|
||||
if(D.restrictedDevice && SCR.signature.empty()) {
|
||||
SCR.signature = SignatureManager()->Sign(R, SCR.script);
|
||||
}
|
||||
|
||||
if(D.restrictedDevice && SCR.signature.empty()) {
|
||||
return BadRequest(RESTAPI::Errors::DeviceRequiresSignature);
|
||||
}
|
||||
|
||||
// convert script to base64 ...
|
||||
auto EncodedScript = Utils::base64encode((const unsigned char *)SCR.script.c_str(),SCR.script.size());
|
||||
Params.set(uCentralProtocol::TYPE, SCR.type);
|
||||
Params.set(uCentralProtocol::SCRIPT, SCR.script);
|
||||
if(!DiagnosticScript) {
|
||||
Params.set(uCentralProtocol::SCRIPT, EncodedScript);
|
||||
}
|
||||
Params.set(uCentralProtocol::WHEN, SCR.when);
|
||||
|
||||
std::stringstream ParamStream;
|
||||
@@ -478,10 +562,10 @@ namespace OpenWifi {
|
||||
Cmd.Details = ParamStream.str();
|
||||
FileUploader()->AddUUID(CMD_UUID, 15min, "script_result");
|
||||
|
||||
return RESTAPI_RPC::WaitForCommand(CMD_RPC,false,Cmd, Params, *Request, *Response, timeout, nullptr, this, Logger_);
|
||||
return RESTAPI_RPC::WaitForCommand(CMD_RPC, APCommands::Commands::script,false,Cmd, Params, *Request, *Response, timeout, nullptr, this, Logger_);
|
||||
}
|
||||
|
||||
void RESTAPI_device_commandHandler::Configure(const std::string &CMD_UUID, uint64_t CMD_RPC, std::chrono::milliseconds timeout, [[maybe_unused]] const AP_Restrictions &R) {
|
||||
void RESTAPI_device_commandHandler::Configure(const std::string &CMD_UUID, uint64_t CMD_RPC, std::chrono::milliseconds timeout, [[maybe_unused]] const GWObjects::DeviceRestrictions &R) {
|
||||
poco_information(Logger_,fmt::format("CONFIGURE({},{}): TID={} user={} serial={}", CMD_UUID, CMD_RPC, TransactionId_, Requester(), SerialNumber_));
|
||||
|
||||
const auto &Obj = ParsedBody_;
|
||||
@@ -526,14 +610,14 @@ namespace OpenWifi {
|
||||
Cmd.Details = ParamStream.str();
|
||||
|
||||
// AP_WS_Server()->SetPendingUUID(SerialNumber_, NewUUID);
|
||||
return RESTAPI_RPC::WaitForCommand(CMD_RPC,true,Cmd, Params, *Request, *Response, timeout, nullptr, this, Logger_);
|
||||
return RESTAPI_RPC::WaitForCommand(CMD_RPC, APCommands::Commands::configure,true,Cmd, Params, *Request, *Response, timeout, nullptr, this, Logger_);
|
||||
}
|
||||
return BadRequest(RESTAPI::Errors::RecordNotUpdated);
|
||||
}
|
||||
BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
|
||||
}
|
||||
|
||||
void RESTAPI_device_commandHandler::Upgrade(const std::string &CMD_UUID, uint64_t CMD_RPC, std::chrono::milliseconds timeout, [[maybe_unused]] const AP_Restrictions &R) {
|
||||
void RESTAPI_device_commandHandler::Upgrade(const std::string &CMD_UUID, uint64_t CMD_RPC, std::chrono::milliseconds timeout, [[maybe_unused]] const GWObjects::DeviceRestrictions &R) {
|
||||
poco_information(Logger_,fmt::format("UPGRADE({},{}): TID={} user={} serial={}", CMD_UUID, CMD_RPC, TransactionId_, Requester(), SerialNumber_));
|
||||
|
||||
const auto &Obj = ParsedBody_;
|
||||
@@ -548,16 +632,11 @@ namespace OpenWifi {
|
||||
}
|
||||
|
||||
GWObjects::Device DeviceInfo;
|
||||
|
||||
if(!StorageService()->GetDevice(SerialNumber_,DeviceInfo)) {
|
||||
return NotFound();
|
||||
}
|
||||
|
||||
std::string FWSignature = GetParameter("FWsignature","");
|
||||
if(FWSignature.empty() && R.sysupgrade_not_allowed()) {
|
||||
return BadRequest(RESTAPI::Errors::DeviceRequiresSignature);
|
||||
}
|
||||
|
||||
auto URI = GetS(RESTAPI::Protocol::URI, Obj);
|
||||
auto When = GetWhen(Obj);
|
||||
|
||||
@@ -576,21 +655,32 @@ namespace OpenWifi {
|
||||
Params.set(uCentralProtocol::SERIAL, SerialNumber_);
|
||||
Params.set(uCentralProtocol::URI, URI);
|
||||
Params.set(uCentralProtocol::KEEP_REDIRECTOR, KeepRedirector ? 1 : 0);
|
||||
if(!FWSignature.empty()) {
|
||||
Params.set(uCentralProtocol::FWSIGNATURE, FWSignature);
|
||||
|
||||
if(DeviceInfo.restrictionDetails.upgrade && FWSignature.empty()) {
|
||||
Poco::URI uri(URI);
|
||||
FWSignature = SignatureManager()->Sign(DeviceInfo.restrictionDetails,uri);
|
||||
}
|
||||
|
||||
if(FWSignature.empty() && DeviceInfo.restrictionDetails.upgrade) {
|
||||
return BadRequest(RESTAPI::Errors::DeviceRequiresSignature);
|
||||
}
|
||||
|
||||
if(!FWSignature.empty()) {
|
||||
Params.set(uCentralProtocol::SIGNATURE, FWSignature);
|
||||
}
|
||||
|
||||
Params.set(uCentralProtocol::WHEN, When);
|
||||
|
||||
std::stringstream ParamStream;
|
||||
Params.stringify(ParamStream);
|
||||
Cmd.Details = ParamStream.str();
|
||||
|
||||
return RESTAPI_RPC::WaitForCommand(CMD_RPC,true,Cmd,Params, *Request, *Response, timeout, nullptr, this, Logger_);
|
||||
return RESTAPI_RPC::WaitForCommand(CMD_RPC, APCommands::Commands::upgrade,true,Cmd,Params, *Request, *Response, timeout, nullptr, this, Logger_);
|
||||
}
|
||||
BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
|
||||
}
|
||||
|
||||
void RESTAPI_device_commandHandler::Reboot(const std::string &CMD_UUID, uint64_t CMD_RPC, std::chrono::milliseconds timeout, [[maybe_unused]] const AP_Restrictions &R) {
|
||||
void RESTAPI_device_commandHandler::Reboot(const std::string &CMD_UUID, uint64_t CMD_RPC, std::chrono::milliseconds timeout, [[maybe_unused]] const GWObjects::DeviceRestrictions &R) {
|
||||
poco_information(Logger_,fmt::format("REBOOT({},{}): TID={} user={} serial={}", CMD_UUID, CMD_RPC, TransactionId_, Requester(), SerialNumber_));
|
||||
|
||||
const auto &Obj = ParsedBody_;
|
||||
@@ -619,12 +709,12 @@ namespace OpenWifi {
|
||||
Params.stringify(ParamStream);
|
||||
Cmd.Details = ParamStream.str();
|
||||
|
||||
return RESTAPI_RPC::WaitForCommand(CMD_RPC,false,Cmd, Params, *Request, *Response, timeout, nullptr, this, Logger_);
|
||||
return RESTAPI_RPC::WaitForCommand(CMD_RPC, APCommands::Commands::reboot, false,Cmd, Params, *Request, *Response, timeout, nullptr, this, Logger_);
|
||||
}
|
||||
BadRequest(RESTAPI::Errors::MissingSerialNumber);
|
||||
}
|
||||
|
||||
void RESTAPI_device_commandHandler::Factory(const std::string &CMD_UUID, uint64_t CMD_RPC, std::chrono::milliseconds timeout, [[maybe_unused]] const AP_Restrictions &R) {
|
||||
void RESTAPI_device_commandHandler::Factory(const std::string &CMD_UUID, uint64_t CMD_RPC, std::chrono::milliseconds timeout, [[maybe_unused]] const GWObjects::DeviceRestrictions &R) {
|
||||
poco_information(Logger_,fmt::format("FACTORY-RESET({},{}): TID={} user={} serial={}", CMD_UUID, CMD_RPC, TransactionId_, Requester(), SerialNumber_));
|
||||
|
||||
const auto &Obj = ParsedBody_;
|
||||
@@ -659,12 +749,12 @@ namespace OpenWifi {
|
||||
Params.stringify(ParamStream);
|
||||
Cmd.Details = ParamStream.str();
|
||||
|
||||
return RESTAPI_RPC::WaitForCommand(CMD_RPC,true,Cmd, Params, *Request, *Response, timeout, nullptr, this, Logger_);
|
||||
return RESTAPI_RPC::WaitForCommand(CMD_RPC, APCommands::Commands::factory,true,Cmd, Params, *Request, *Response, timeout, nullptr, this, Logger_);
|
||||
}
|
||||
BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
|
||||
}
|
||||
|
||||
void RESTAPI_device_commandHandler::LEDs(const std::string &CMD_UUID, uint64_t CMD_RPC, std::chrono::milliseconds timeout, [[maybe_unused]] const AP_Restrictions &R) {
|
||||
void RESTAPI_device_commandHandler::LEDs(const std::string &CMD_UUID, uint64_t CMD_RPC, std::chrono::milliseconds timeout, [[maybe_unused]] const GWObjects::DeviceRestrictions &R) {
|
||||
poco_information(Logger_,fmt::format("LEDS({},{}): TID={} user={} serial={}", CMD_UUID, CMD_RPC, TransactionId_, Requester(), SerialNumber_));
|
||||
|
||||
const auto &Obj = ParsedBody_;
|
||||
@@ -707,12 +797,12 @@ namespace OpenWifi {
|
||||
Params.stringify(ParamStream);
|
||||
Cmd.Details = ParamStream.str();
|
||||
|
||||
return RESTAPI_RPC::WaitForCommand(CMD_RPC,false,Cmd, Params, *Request, *Response, timeout, nullptr, this, Logger_);
|
||||
return RESTAPI_RPC::WaitForCommand(CMD_RPC, APCommands::Commands::leds,false,Cmd, Params, *Request, *Response, timeout, nullptr, this, Logger_);
|
||||
}
|
||||
BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
|
||||
}
|
||||
|
||||
void RESTAPI_device_commandHandler::Trace(const std::string &CMD_UUID, uint64_t CMD_RPC, std::chrono::milliseconds timeout, [[maybe_unused]] const AP_Restrictions &R) {
|
||||
void RESTAPI_device_commandHandler::Trace(const std::string &CMD_UUID, uint64_t CMD_RPC, std::chrono::milliseconds timeout, [[maybe_unused]] const GWObjects::DeviceRestrictions &R) {
|
||||
poco_information(Logger_,fmt::format("TRACE({},{}): TID={} user={} serial={}", CMD_UUID, CMD_RPC, TransactionId_, Requester(), SerialNumber_));
|
||||
|
||||
const auto &Obj = ParsedBody_;
|
||||
@@ -760,12 +850,12 @@ namespace OpenWifi {
|
||||
Cmd.Details = ParamStream.str();
|
||||
|
||||
FileUploader()->AddUUID(CMD_UUID, 10min, "trace");
|
||||
return RESTAPI_RPC::WaitForCommand(CMD_RPC,false,Cmd, Params, *Request, *Response, timeout, nullptr, this, Logger_);
|
||||
return RESTAPI_RPC::WaitForCommand(CMD_RPC, APCommands::Commands::trace,false,Cmd, Params, *Request, *Response, timeout, nullptr, this, Logger_);
|
||||
}
|
||||
BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
|
||||
}
|
||||
|
||||
void RESTAPI_device_commandHandler::WifiScan(const std::string &CMD_UUID, uint64_t CMD_RPC, std::chrono::milliseconds timeout, [[maybe_unused]] const AP_Restrictions &R) {
|
||||
void RESTAPI_device_commandHandler::WifiScan(const std::string &CMD_UUID, uint64_t CMD_RPC, std::chrono::milliseconds timeout, [[maybe_unused]] const GWObjects::DeviceRestrictions &R) {
|
||||
poco_information(Logger_,fmt::format("WIFISCAN({},{}): TID={} user={} serial={}", CMD_UUID, CMD_RPC, TransactionId_, Requester(), SerialNumber_));
|
||||
const auto &Obj = ParsedBody_;
|
||||
|
||||
@@ -795,7 +885,7 @@ namespace OpenWifi {
|
||||
|
||||
Params.set(uCentralProtocol::SERIAL, SerialNumber_);
|
||||
|
||||
if(R.dfs_not_allowed() && OverrideDFS) {
|
||||
if(R.dfs && OverrideDFS) {
|
||||
return BadRequest(RESTAPI::Errors::DeviceIsRestricted);
|
||||
}
|
||||
|
||||
@@ -809,13 +899,13 @@ namespace OpenWifi {
|
||||
std::stringstream ParamStream;
|
||||
Params.stringify(ParamStream);
|
||||
Cmd.Details = ParamStream.str();
|
||||
RESTAPI_RPC::WaitForCommand(CMD_RPC,false,Cmd, Params, *Request, *Response, timeout, nullptr, this, Logger_);
|
||||
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_, Cmd.Results);
|
||||
}
|
||||
}
|
||||
|
||||
void RESTAPI_device_commandHandler::EventQueue(const std::string &CMD_UUID, uint64_t CMD_RPC, std::chrono::milliseconds timeout, [[maybe_unused]] const AP_Restrictions &R) {
|
||||
void RESTAPI_device_commandHandler::EventQueue(const std::string &CMD_UUID, uint64_t CMD_RPC, std::chrono::milliseconds timeout, [[maybe_unused]] const GWObjects::DeviceRestrictions &R) {
|
||||
poco_information(Logger_,fmt::format("EVENT-QUEUE({},{}): TID={} user={} serial={}", CMD_UUID, CMD_RPC, TransactionId_, Requester(), SerialNumber_));
|
||||
|
||||
const auto &Obj = ParsedBody_;
|
||||
@@ -844,7 +934,7 @@ namespace OpenWifi {
|
||||
Params.stringify(ParamStream);
|
||||
Cmd.Details = ParamStream.str();
|
||||
|
||||
RESTAPI_RPC::WaitForCommand(CMD_RPC,false,Cmd, Params, *Request, *Response, timeout, nullptr, this, Logger_);
|
||||
RESTAPI_RPC::WaitForCommand(CMD_RPC, APCommands::Commands::eventqueue,false,Cmd, Params, *Request, *Response, timeout, nullptr, this, Logger_);
|
||||
if(Cmd.ErrorCode==0) {
|
||||
KafkaManager()->PostMessage(KafkaTopics::DEVICE_EVENT_QUEUE, SerialNumber_,
|
||||
Cmd.Results);
|
||||
@@ -854,7 +944,7 @@ namespace OpenWifi {
|
||||
BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
|
||||
}
|
||||
|
||||
void RESTAPI_device_commandHandler::MakeRequest(const std::string &CMD_UUID, uint64_t CMD_RPC, std::chrono::milliseconds timeout, [[maybe_unused]] const AP_Restrictions &R) {
|
||||
void RESTAPI_device_commandHandler::MakeRequest(const std::string &CMD_UUID, uint64_t CMD_RPC, std::chrono::milliseconds timeout, [[maybe_unused]] const GWObjects::DeviceRestrictions &R) {
|
||||
poco_information(Logger_,fmt::format("FORCE-REQUEST({},{}): TID={} user={} serial={}", CMD_UUID, CMD_RPC, TransactionId_, Requester(), SerialNumber_));
|
||||
|
||||
const auto &Obj = ParsedBody_;
|
||||
@@ -891,15 +981,17 @@ namespace OpenWifi {
|
||||
Params.stringify(ParamStream);
|
||||
Cmd.Details = ParamStream.str();
|
||||
|
||||
return RESTAPI_RPC::WaitForCommand(CMD_RPC,false,Cmd, Params, *Request, *Response, timeout, nullptr, this, Logger_ );
|
||||
return RESTAPI_RPC::WaitForCommand(CMD_RPC, APCommands::Commands::request,false,Cmd, Params, *Request, *Response, timeout, nullptr, this, Logger_ );
|
||||
}
|
||||
BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
|
||||
}
|
||||
|
||||
void RESTAPI_device_commandHandler::Rtty(const std::string &CMD_UUID, uint64_t CMD_RPC, std::chrono::milliseconds timeout, [[maybe_unused]] const AP_Restrictions &R) {
|
||||
#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 &R) {
|
||||
poco_information(Logger_,fmt::format("RTTY({},{}): TID={} user={} serial={}", CMD_UUID, CMD_RPC, TransactionId_, Requester(), SerialNumber_));
|
||||
|
||||
if(R.rtty_not_allowed()) {
|
||||
if(R.rtty) {
|
||||
return BadRequest(RESTAPI::Errors::DeviceIsRestricted);
|
||||
}
|
||||
|
||||
@@ -907,14 +999,15 @@ namespace OpenWifi {
|
||||
GWObjects::Device Device;
|
||||
|
||||
if (StorageService()->GetDevice(SerialNumber_, Device)) {
|
||||
|
||||
static std::uint64_t rtty_sid = 0;
|
||||
rtty_sid += std::rand();
|
||||
GWObjects::RttySessionDetails Rtty{
|
||||
.SerialNumber = SerialNumber_,
|
||||
.Server = MicroServiceConfigGetString("rtty.server", "localhost"),
|
||||
.Port = MicroServiceConfigGetInt("rtty.port", 5912),
|
||||
.Token = MicroServiceConfigGetString("rtty.token", "nothing"),
|
||||
.TimeOut = MicroServiceConfigGetInt("rtty.timeout", 60),
|
||||
.ConnectionId = Utils::ComputeHash(SerialNumber_,Utils::Now()).substr(0,RTTY_DEVICE_TOKEN_LENGTH),
|
||||
.ConnectionId = Utils::ComputeHash(SerialNumber_,Utils::Now(),rtty_sid).substr(0,RTTY_DEVICE_TOKEN_LENGTH),
|
||||
.Started = Utils::Now(),
|
||||
.CommandUUID = CMD_UUID,
|
||||
.ViewPort = MicroServiceConfigGetInt("rtty.viewport", 5913),
|
||||
@@ -954,7 +1047,7 @@ namespace OpenWifi {
|
||||
Params.stringify(ParamStream);
|
||||
Cmd.Details = ParamStream.str();
|
||||
poco_information(Logger_,fmt::format("RTTY: user={} serial={} rttyid={} token={} cmd={}.", Requester(), SerialNumber_, Rtty.ConnectionId, Rtty.Token, CMD_UUID));
|
||||
return RESTAPI_RPC::WaitForCommand(CMD_RPC,false,Cmd, Params, *Request, *Response, timeout, &ReturnedObject, this, Logger_);
|
||||
return RESTAPI_RPC::WaitForCommand(CMD_RPC, APCommands::Commands::rtty,false,Cmd, Params, *Request, *Response, timeout, &ReturnedObject, this, Logger_);
|
||||
}
|
||||
return NotFound();
|
||||
}
|
||||
@@ -962,9 +1055,7 @@ namespace OpenWifi {
|
||||
return ReturnStatus(Poco::Net::HTTPResponse::HTTP_SERVICE_UNAVAILABLE);
|
||||
}
|
||||
|
||||
// #define DBG { std::cout << __LINE__ << std::endl; }
|
||||
|
||||
void RESTAPI_device_commandHandler::Telemetry(const std::string &CMD_UUID, uint64_t CMD_RPC, [[maybe_unused]] std::chrono::milliseconds timeout, [[maybe_unused]] const AP_Restrictions &R){
|
||||
void RESTAPI_device_commandHandler::Telemetry(const std::string &CMD_UUID, uint64_t CMD_RPC, [[maybe_unused]] std::chrono::milliseconds timeout, [[maybe_unused]] const GWObjects::DeviceRestrictions &R){
|
||||
poco_information(Logger_,fmt::format("TELEMETRY({},{}): TID={} user={} serial={}", CMD_UUID, CMD_RPC, TransactionId_, Requester(), SerialNumber_));
|
||||
|
||||
const auto &Obj = ParsedBody_;
|
||||
@@ -981,7 +1072,6 @@ namespace OpenWifi {
|
||||
|
||||
std::stringstream oooss;
|
||||
Obj->stringify(oooss);
|
||||
// std::cout << "Payload:" << oooss.str() << std::endl;
|
||||
|
||||
std::uint64_t Lifetime = 60 * 60 ; // 1 hour
|
||||
std::uint64_t Interval = 5;
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "framework/RESTAPI_Handler.h"
|
||||
#include "AP_restrictions.h"
|
||||
#include "RESTObjects/RESTAPI_GWobjects.h"
|
||||
|
||||
namespace OpenWifi {
|
||||
class RESTAPI_device_commandHandler : public RESTAPIHandler {
|
||||
@@ -34,19 +34,19 @@ namespace OpenWifi {
|
||||
void GetChecks();
|
||||
void DeleteChecks();
|
||||
|
||||
void Configure(const std::string &UUID, uint64_t RPC, std::chrono::milliseconds timeout, const AP_Restrictions &R);
|
||||
void Upgrade(const std::string &UUID, uint64_t RPC, std::chrono::milliseconds timeout, const AP_Restrictions &R);
|
||||
void Reboot(const std::string &UUID, uint64_t RPC, std::chrono::milliseconds timeout, const AP_Restrictions &R);
|
||||
void Factory(const std::string &UUID, uint64_t RPC, std::chrono::milliseconds timeout, const AP_Restrictions &R);
|
||||
void LEDs(const std::string &UUID, uint64_t RPC, std::chrono::milliseconds timeout, const AP_Restrictions &R);
|
||||
void Trace(const std::string &UUID, uint64_t RPC, std::chrono::milliseconds timeout, const AP_Restrictions &R);
|
||||
void MakeRequest(const std::string &UUID, uint64_t RPC, std::chrono::milliseconds timeout, const AP_Restrictions &R);
|
||||
void WifiScan(const std::string &UUID, uint64_t RPC, std::chrono::milliseconds timeout, const AP_Restrictions &R);
|
||||
void EventQueue(const std::string &UUID, uint64_t RPC, std::chrono::milliseconds timeout, const AP_Restrictions &R);
|
||||
void Rtty(const std::string &UUID, uint64_t RPC, std::chrono::milliseconds timeout, const AP_Restrictions &R);
|
||||
void Telemetry(const std::string &UUID, uint64_t RPC, std::chrono::milliseconds timeout, const AP_Restrictions &R);
|
||||
void Ping(const std::string &UUID, uint64_t RPC, std::chrono::milliseconds timeout, const AP_Restrictions &R);
|
||||
void Script(const std::string &UUID, uint64_t RPC, std::chrono::milliseconds timeout, const AP_Restrictions &R);
|
||||
void Configure(const std::string &UUID, uint64_t RPC, std::chrono::milliseconds timeout, const GWObjects::DeviceRestrictions &R);
|
||||
void Upgrade(const std::string &UUID, uint64_t RPC, std::chrono::milliseconds timeout, const GWObjects::DeviceRestrictions &R);
|
||||
void Reboot(const std::string &UUID, uint64_t RPC, std::chrono::milliseconds timeout, const GWObjects::DeviceRestrictions &R);
|
||||
void Factory(const std::string &UUID, uint64_t RPC, std::chrono::milliseconds timeout, const GWObjects::DeviceRestrictions &R);
|
||||
void LEDs(const std::string &UUID, uint64_t RPC, std::chrono::milliseconds timeout, const GWObjects::DeviceRestrictions &R);
|
||||
void Trace(const std::string &UUID, uint64_t RPC, std::chrono::milliseconds timeout, const GWObjects::DeviceRestrictions &R);
|
||||
void MakeRequest(const std::string &UUID, uint64_t RPC, std::chrono::milliseconds timeout, const GWObjects::DeviceRestrictions &R);
|
||||
void WifiScan(const std::string &UUID, uint64_t RPC, std::chrono::milliseconds timeout, const GWObjects::DeviceRestrictions &R);
|
||||
void EventQueue(const std::string &UUID, uint64_t RPC, std::chrono::milliseconds timeout, const GWObjects::DeviceRestrictions &R);
|
||||
void Rtty(const std::string &UUID, uint64_t RPC, std::chrono::milliseconds timeout, const GWObjects::DeviceRestrictions &R);
|
||||
void Telemetry(const std::string &UUID, uint64_t RPC, std::chrono::milliseconds timeout, const GWObjects::DeviceRestrictions &R);
|
||||
void Ping(const std::string &UUID, uint64_t RPC, std::chrono::milliseconds timeout, const GWObjects::DeviceRestrictions &R);
|
||||
void Script(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}"}; };
|
||||
void DoGet() final;
|
||||
|
||||
@@ -32,9 +32,7 @@ namespace OpenWifi {
|
||||
CompleteDeviceInfo(Device, Answer);
|
||||
return ReturnObject(Answer);
|
||||
} else {
|
||||
Poco::JSON::Object Obj;
|
||||
Device.to_json(Obj);
|
||||
return ReturnObject(Obj);
|
||||
return Object(Device);
|
||||
}
|
||||
}
|
||||
NotFound();
|
||||
@@ -139,9 +137,7 @@ namespace OpenWifi {
|
||||
|
||||
if (StorageService()->CreateDevice(Device)) {
|
||||
SetCurrentConfigurationID(SerialNumber, Device.UUID);
|
||||
Poco::JSON::Object DevObj;
|
||||
Device.to_json(DevObj);
|
||||
return ReturnObject(DevObj);
|
||||
return Object(Device);
|
||||
}
|
||||
InternalError(RESTAPI::Errors::RecordNotCreated);
|
||||
}
|
||||
@@ -191,9 +187,9 @@ namespace OpenWifi {
|
||||
Existing.LastConfigurationChange = Utils::Now();
|
||||
if (StorageService()->UpdateDevice(Existing)) {
|
||||
SetCurrentConfigurationID(SerialNumber, Existing.UUID);
|
||||
Poco::JSON::Object DevObj;
|
||||
NewDevice.to_json(DevObj);
|
||||
return ReturnObject(DevObj);
|
||||
GWObjects::Device UpdatedDevice;
|
||||
StorageService()->GetDevice(SerialNumber, UpdatedDevice);
|
||||
return Object(UpdatedDevice);
|
||||
}
|
||||
InternalError(RESTAPI::Errors::RecordNotUpdated);
|
||||
}
|
||||
|
||||
@@ -25,7 +25,12 @@ namespace OpenWifi {
|
||||
if (!StorageService()->GetAttachedFileContent(UUID, SerialNumber, FileContent, FileType)) {
|
||||
return NotFound();
|
||||
}
|
||||
SendFileContent(FileContent,"pcap",UUID+".pcap");
|
||||
if(FileType=="pcap")
|
||||
SendFileContent(FileContent,"application/vnd.tcpdump.pcap",UUID+".pcap");
|
||||
else if(FileType=="gzip")
|
||||
SendFileContent(FileContent,"application/gzip",UUID+".tar.gz");
|
||||
else
|
||||
SendFileContent(FileContent,"application/txt",UUID+".txt");
|
||||
}
|
||||
|
||||
void RESTAPI_file::DoDelete() {
|
||||
|
||||
@@ -14,9 +14,7 @@ namespace OpenWifi {
|
||||
Poco::Thread::current()->id()));
|
||||
GWObjects::RadiusProxyPoolList C;
|
||||
RADIUS_proxy_server()->GetConfig(C);
|
||||
Poco::JSON::Object Answer;
|
||||
C.to_json(Answer);
|
||||
return ReturnObject(Answer);
|
||||
return Object(C);
|
||||
}
|
||||
|
||||
void RESTAPI_radiusProxyConfig_handler::DoDelete() {
|
||||
@@ -77,7 +75,7 @@ namespace OpenWifi {
|
||||
TransactionId_, Requester(),
|
||||
Poco::Thread::current()->id()));
|
||||
RADIUS_proxy_server()->SetConfig(C);
|
||||
return ReturnObject(*ParsedBody_);
|
||||
return Object(C);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -18,6 +18,8 @@
|
||||
#include "RESTAPI/RESTAPI_telemetryWebSocket.h"
|
||||
#include "RESTAPI/RESTAPI_iptocountry_handler.h"
|
||||
#include "RESTAPI/RESTAPI_radiusProxyConfig_handler.h"
|
||||
#include "RESTAPI/RESTAPI_script_handler.h"
|
||||
#include "RESTAPI/RESTAPI_scripts_handler.h"
|
||||
|
||||
#include "framework/RESTAPI_SystemCommand.h"
|
||||
#include "framework/RESTAPI_WebSocketServer.h"
|
||||
@@ -46,6 +48,8 @@ namespace OpenWifi {
|
||||
RESTAPI_blacklist_list,
|
||||
RESTAPI_iptocountry_handler,
|
||||
RESTAPI_radiusProxyConfig_handler,
|
||||
RESTAPI_scripts_handler,
|
||||
RESTAPI_script_handler,
|
||||
RESTAPI_capabilities_handler, RESTAPI_telemetryWebSocket>(Path,Bindings,L, S, TransactionId);
|
||||
}
|
||||
|
||||
@@ -65,6 +69,8 @@ namespace OpenWifi {
|
||||
RESTAPI_blacklist,
|
||||
RESTAPI_iptocountry_handler,
|
||||
RESTAPI_radiusProxyConfig_handler,
|
||||
RESTAPI_scripts_handler,
|
||||
RESTAPI_script_handler,
|
||||
RESTAPI_blacklist_list>(Path,Bindings,L, S, TransactionId);
|
||||
}
|
||||
}
|
||||
160
src/RESTAPI/RESTAPI_script_handler.cpp
Normal file
160
src/RESTAPI/RESTAPI_script_handler.cpp
Normal file
@@ -0,0 +1,160 @@
|
||||
//
|
||||
// Created by stephane bourque on 2022-11-21.
|
||||
//
|
||||
|
||||
#include "RESTAPI_script_handler.h"
|
||||
|
||||
namespace OpenWifi {
|
||||
|
||||
void RESTAPI_script_handler::DoGet() {
|
||||
std::string UUID = GetBinding("uuid","");
|
||||
|
||||
if(UUID.empty()) {
|
||||
return BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
|
||||
}
|
||||
|
||||
GWObjects::ScriptEntry SE;
|
||||
if(DB_.GetRecord("id",UUID, SE)) {
|
||||
return Object(SE);
|
||||
}
|
||||
return NotFound();
|
||||
}
|
||||
|
||||
void RESTAPI_script_handler::DoDelete() {
|
||||
std::string UUID = GetBinding("uuid","");
|
||||
|
||||
if(UserInfo_.userinfo.userRole!=SecurityObjects::ROOT) {
|
||||
return BadRequest(RESTAPI::Errors::ACCESS_DENIED);
|
||||
}
|
||||
|
||||
if(UUID.empty()) {
|
||||
return BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
|
||||
}
|
||||
|
||||
if(DB_.DeleteRecord("id",UUID)) {
|
||||
return OK();
|
||||
}
|
||||
return NotFound();
|
||||
}
|
||||
|
||||
void RESTAPI_script_handler::DoPost() {
|
||||
std::string UUID = GetBinding("uuid","");
|
||||
|
||||
if(UserInfo_.userinfo.userRole!=SecurityObjects::ROOT) {
|
||||
return BadRequest(RESTAPI::Errors::ACCESS_DENIED);
|
||||
}
|
||||
|
||||
if(UUID.empty()) {
|
||||
return BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
|
||||
}
|
||||
|
||||
GWObjects::ScriptEntry SE;
|
||||
if(!SE.from_json(ParsedBody_)) {
|
||||
return BadRequest(RESTAPI::Errors::InvalidJSONDocument);
|
||||
}
|
||||
|
||||
if( SE.name.empty() ||
|
||||
SE.author.empty() ||
|
||||
(SE.type!="bundle" && SE.type!="shell") ||
|
||||
SE.content.empty() ||
|
||||
SE.version.empty()) {
|
||||
return BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
|
||||
}
|
||||
|
||||
if(!SE.restricted.empty()) {
|
||||
for(const auto &role:SE.restricted) {
|
||||
if(SecurityObjects::UserTypeFromString(role)==SecurityObjects::UNKNOWN) {
|
||||
return BadRequest(RESTAPI::Errors::InvalidUserRole);
|
||||
}
|
||||
}
|
||||
std::sort(SE.restricted.begin(),SE.restricted.end());
|
||||
}
|
||||
|
||||
if(!SE.uri.empty() && !Utils::ValidateURI(SE.uri)) {
|
||||
return BadRequest(RESTAPI::Errors::InvalidURI);
|
||||
}
|
||||
|
||||
if(!SE.defaultUploadURI.empty() && !Utils::ValidateURI(SE.defaultUploadURI)) {
|
||||
return BadRequest(RESTAPI::Errors::InvalidURI);
|
||||
}
|
||||
|
||||
SE.id = MicroServiceCreateUUID();
|
||||
SE.created = SE.modified = Utils::Now();
|
||||
if(DB_.CreateRecord(SE)) {
|
||||
return Object(SE);
|
||||
}
|
||||
return BadRequest(RESTAPI::Errors::RecordNotCreated);
|
||||
}
|
||||
|
||||
void RESTAPI_script_handler::DoPut() {
|
||||
std::string UUID = GetBinding("uuid","");
|
||||
|
||||
if(UserInfo_.userinfo.userRole!=SecurityObjects::ROOT) {
|
||||
return BadRequest(RESTAPI::Errors::ACCESS_DENIED);
|
||||
}
|
||||
|
||||
if(UUID.empty()) {
|
||||
return BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
|
||||
}
|
||||
|
||||
GWObjects::ScriptEntry SE;
|
||||
if(!SE.from_json(ParsedBody_)) {
|
||||
return BadRequest(RESTAPI::Errors::InvalidJSONDocument);
|
||||
}
|
||||
|
||||
if(!SE.restricted.empty()) {
|
||||
for(const auto &role:SE.restricted) {
|
||||
if(SecurityObjects::UserTypeFromString(role)==SecurityObjects::UNKNOWN) {
|
||||
return BadRequest(RESTAPI::Errors::InvalidUserRole);
|
||||
}
|
||||
}
|
||||
std::sort(SE.restricted.begin(),SE.restricted.end());
|
||||
}
|
||||
|
||||
GWObjects::ScriptEntry Existing;
|
||||
if(!DB_.GetRecord("id", UUID, Existing)) {
|
||||
return NotFound();
|
||||
}
|
||||
|
||||
if(ParsedBody_->has("name") && SE.name.empty()) {
|
||||
return BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
|
||||
}
|
||||
|
||||
if(ParsedBody_->has("content") && SE.content.empty()) {
|
||||
return BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
|
||||
}
|
||||
|
||||
if(ParsedBody_->has("version") && SE.version.empty()) {
|
||||
return BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
|
||||
}
|
||||
|
||||
if(!SE.uri.empty() && !Utils::ValidateURI(SE.uri)) {
|
||||
return BadRequest(RESTAPI::Errors::InvalidURI);
|
||||
}
|
||||
|
||||
if(!SE.defaultUploadURI.empty() && !Utils::ValidateURI(SE.defaultUploadURI)) {
|
||||
return BadRequest(RESTAPI::Errors::InvalidURI);
|
||||
}
|
||||
|
||||
if(ParsedBody_->has("restricted")) {
|
||||
Existing.restricted = SE.restricted;
|
||||
}
|
||||
|
||||
AssignIfPresent(ParsedBody_, "name", Existing.name);
|
||||
AssignIfPresent(ParsedBody_, "description", Existing.description);
|
||||
AssignIfPresent(ParsedBody_, "uri", Existing.uri);
|
||||
AssignIfPresent(ParsedBody_, "content", Existing.content);
|
||||
AssignIfPresent(ParsedBody_, "version", Existing.version);
|
||||
AssignIfPresent(ParsedBody_, "deferred", Existing.deferred);
|
||||
AssignIfPresent(ParsedBody_, "timeout", Existing.timeout);
|
||||
AssignIfPresent(ParsedBody_, "defaultUploadURI", Existing.defaultUploadURI);
|
||||
|
||||
Existing.modified = Utils::Now();
|
||||
|
||||
if(DB_.UpdateRecord("id", UUID, Existing)) {
|
||||
return Object(Existing);
|
||||
}
|
||||
return BadRequest(RESTAPI::Errors::RecordNotUpdated);
|
||||
}
|
||||
|
||||
} // namespace OpenWifi
|
||||
31
src/RESTAPI/RESTAPI_script_handler.h
Normal file
31
src/RESTAPI/RESTAPI_script_handler.h
Normal file
@@ -0,0 +1,31 @@
|
||||
//
|
||||
// Created by stephane bourque on 2022-11-21.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "framework/RESTAPI_Handler.h"
|
||||
#include "StorageService.h"
|
||||
|
||||
namespace OpenWifi {
|
||||
class RESTAPI_script_handler : public RESTAPIHandler {
|
||||
public:
|
||||
RESTAPI_script_handler(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_PUT,
|
||||
Poco::Net::HTTPRequest::HTTP_POST,
|
||||
Poco::Net::HTTPRequest::HTTP_DELETE,
|
||||
Poco::Net::HTTPRequest::HTTP_OPTIONS},
|
||||
Server, TransactionId, Internal){};
|
||||
static auto PathName() { return std::list<std::string>{"/api/v1/script/{uuid}"}; };
|
||||
private:
|
||||
ScriptDB & DB_{ StorageService()->ScriptDB() };
|
||||
void DoGet() final;
|
||||
void DoDelete() final;
|
||||
void DoPost() final;
|
||||
void DoPut() final;
|
||||
};
|
||||
}
|
||||
20
src/RESTAPI/RESTAPI_scripts_handler.cpp
Normal file
20
src/RESTAPI/RESTAPI_scripts_handler.cpp
Normal file
@@ -0,0 +1,20 @@
|
||||
//
|
||||
// Created by stephane bourque on 2022-11-21.
|
||||
//
|
||||
|
||||
#include "RESTAPI_scripts_handler.h"
|
||||
#include "RESTObjects/RESTAPI_GWobjects.h"
|
||||
#include "StorageService.h"
|
||||
|
||||
namespace OpenWifi {
|
||||
|
||||
void RESTAPI_scripts_handler::DoGet() {
|
||||
GWObjects::ScriptEntryList L;
|
||||
|
||||
StorageService()->ScriptDB().GetRecords(QB_.Offset,QB_.Limit,L.scripts);
|
||||
Poco::JSON::Object Answer;
|
||||
L.to_json(Answer);
|
||||
return ReturnObject(Answer);
|
||||
}
|
||||
|
||||
} // namespace OpenWifi
|
||||
25
src/RESTAPI/RESTAPI_scripts_handler.h
Normal file
25
src/RESTAPI/RESTAPI_scripts_handler.h
Normal file
@@ -0,0 +1,25 @@
|
||||
//
|
||||
// Created by stephane bourque on 2022-11-21.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "framework/RESTAPI_Handler.h"
|
||||
|
||||
namespace OpenWifi {
|
||||
class RESTAPI_scripts_handler : public RESTAPIHandler {
|
||||
public:
|
||||
RESTAPI_scripts_handler(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/scripts"}; };
|
||||
void DoGet() final;
|
||||
void DoDelete() final{};
|
||||
void DoPost() final{};
|
||||
void DoPut() final{};
|
||||
};
|
||||
}
|
||||
@@ -51,7 +51,9 @@ namespace OpenWifi::GWObjects {
|
||||
field_to_json(Obj,"modified", modified);
|
||||
field_to_json(Obj,"locale", locale);
|
||||
field_to_json(Obj,"restrictedDevice", restrictedDevice);
|
||||
|
||||
field_to_json(Obj,"pendingConfiguration", pendingConfiguration);
|
||||
field_to_json(Obj,"pendingConfigurationCmd", pendingConfigurationCmd);
|
||||
field_to_json(Obj,"restrictionDetails", restrictionDetails);
|
||||
}
|
||||
|
||||
void Device::to_json_with_status(Poco::JSON::Object &Obj) const {
|
||||
@@ -93,6 +95,9 @@ namespace OpenWifi::GWObjects {
|
||||
field_from_json(Obj,"entity", entity);
|
||||
field_from_json(Obj,"locale", locale);
|
||||
field_from_json(Obj,"restrictedDevice", restrictedDevice);
|
||||
field_from_json(Obj,"pendingConfiguration", pendingConfiguration);
|
||||
field_from_json(Obj,"pendingConfigurationCmd", pendingConfigurationCmd);
|
||||
field_from_json(Obj,"restrictionDetails", restrictionDetails);
|
||||
return true;
|
||||
} catch (const Poco::Exception &E) {
|
||||
}
|
||||
@@ -304,6 +309,7 @@ namespace OpenWifi::GWObjects {
|
||||
field_to_json(Obj,"serialNumber",serialNumber);
|
||||
field_to_json(Obj,"timeout",timeout);
|
||||
field_to_json(Obj,"type",type);
|
||||
field_to_json(Obj,"scriptId",scriptId);
|
||||
field_to_json(Obj,"script",script);
|
||||
field_to_json(Obj,"when",when);
|
||||
field_to_json(Obj,"signature", signature);
|
||||
@@ -317,6 +323,7 @@ namespace OpenWifi::GWObjects {
|
||||
field_from_json(Obj,"timeout",timeout);
|
||||
field_from_json(Obj,"type",type);
|
||||
field_from_json(Obj,"script",script);
|
||||
field_from_json(Obj,"scriptId",scriptId);
|
||||
field_from_json(Obj,"when",when);
|
||||
field_from_json(Obj,"signature", signature);
|
||||
field_from_json(Obj,"deferred", deferred);
|
||||
@@ -392,6 +399,7 @@ namespace OpenWifi::GWObjects {
|
||||
field_to_json(Obj,"secret",secret);
|
||||
field_to_json(Obj,"certificate",certificate);
|
||||
field_to_json(Obj,"radsec",radsec);
|
||||
field_to_json(Obj,"allowSelfSigned",allowSelfSigned);
|
||||
field_to_json(Obj,"radsecPort",radsecPort);
|
||||
field_to_json(Obj,"radsecSecret",radsecSecret);
|
||||
field_to_json(Obj,"radsecCacerts",radsecCacerts);
|
||||
@@ -410,6 +418,7 @@ namespace OpenWifi::GWObjects {
|
||||
field_from_json(Obj,"secret",secret);
|
||||
field_from_json(Obj,"certificate",certificate);
|
||||
field_from_json(Obj,"radsec",radsec);
|
||||
field_from_json(Obj,"allowSelfSigned",allowSelfSigned);
|
||||
field_from_json(Obj,"radsecSecret",radsecSecret);
|
||||
field_from_json(Obj,"radsecPort",radsecPort);
|
||||
field_from_json(Obj,"radsecCacerts",radsecCacerts);
|
||||
@@ -422,5 +431,117 @@ namespace OpenWifi::GWObjects {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void ScriptEntry::to_json(Poco::JSON::Object &Obj) const {
|
||||
field_to_json(Obj,"id", id);
|
||||
field_to_json(Obj,"name", name);
|
||||
field_to_json(Obj,"description", description);
|
||||
field_to_json(Obj,"uri", uri);
|
||||
field_to_json(Obj,"content", content);
|
||||
field_to_json(Obj,"version", version);
|
||||
field_to_json(Obj,"type", type);
|
||||
field_to_json(Obj,"created", created);
|
||||
field_to_json(Obj,"modified", modified);
|
||||
field_to_json(Obj,"author", author);
|
||||
field_to_json(Obj,"restricted", restricted);
|
||||
field_to_json(Obj,"deferred", deferred);
|
||||
field_to_json(Obj,"timeout", timeout);
|
||||
field_to_json(Obj,"defaultUploadURI", defaultUploadURI);
|
||||
}
|
||||
|
||||
bool ScriptEntry::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,"description", description);
|
||||
field_from_json(Obj,"uri", uri);
|
||||
field_from_json(Obj,"content", content);
|
||||
field_from_json(Obj,"version", version);
|
||||
field_from_json(Obj,"type", type);
|
||||
field_from_json(Obj,"created", created);
|
||||
field_from_json(Obj,"modified", modified);
|
||||
field_from_json(Obj,"author", author);
|
||||
field_from_json(Obj,"restricted", restricted);
|
||||
field_from_json(Obj,"deferred", deferred);
|
||||
field_from_json(Obj,"timeout", timeout);
|
||||
field_from_json(Obj,"defaultUploadURI", defaultUploadURI);
|
||||
return true;
|
||||
} catch (const Poco::Exception &E) {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void ScriptEntryList::to_json(Poco::JSON::Object &Obj) const {
|
||||
field_to_json(Obj,"scripts",scripts);
|
||||
}
|
||||
|
||||
bool ScriptEntryList::from_json(const Poco::JSON::Object::Ptr &Obj) {
|
||||
try {
|
||||
field_from_json(Obj,"scripts",scripts);
|
||||
return true;
|
||||
} catch (const Poco::Exception &E) {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void DeviceRestrictionsKeyInfo::to_json(Poco::JSON::Object &Obj) const {
|
||||
field_to_json(Obj,"vendor", vendor);
|
||||
field_to_json(Obj,"algo", algo);
|
||||
}
|
||||
|
||||
bool DeviceRestrictionsKeyInfo::from_json(const Poco::JSON::Object::Ptr &Obj) {
|
||||
try {
|
||||
field_from_json(Obj,"vendor", vendor);
|
||||
field_from_json(Obj,"algo", algo);
|
||||
return true;
|
||||
} catch (const Poco::Exception &E) {
|
||||
}
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
void DeviceRestrictions::to_json(Poco::JSON::Object &Obj) const {
|
||||
field_to_json(Obj,"dfs", dfs);
|
||||
field_to_json(Obj,"ssh", ssh);
|
||||
field_to_json(Obj,"rtty", rtty);
|
||||
field_to_json(Obj,"tty", tty);
|
||||
field_to_json(Obj,"developer", developer);
|
||||
field_to_json(Obj,"upgrade", upgrade);
|
||||
field_to_json(Obj,"commands", commands);
|
||||
field_to_json(Obj,"country", country);
|
||||
field_to_json(Obj,"key_info", key_info);
|
||||
}
|
||||
|
||||
bool DeviceRestrictions::from_json(const Poco::JSON::Object::Ptr &Obj) {
|
||||
try {
|
||||
field_from_json(Obj,"dfs", dfs);
|
||||
field_from_json(Obj,"ssh", ssh);
|
||||
field_from_json(Obj,"rtty", rtty);
|
||||
field_from_json(Obj,"tty", tty);
|
||||
field_from_json(Obj,"developer", developer);
|
||||
field_from_json(Obj,"upgrade", upgrade);
|
||||
field_from_json(Obj,"commands", commands);
|
||||
field_from_json(Obj,"country", country);
|
||||
field_from_json(Obj,"key_info", key_info);
|
||||
return true;
|
||||
} catch (const Poco::Exception &E) {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool DeviceRestrictionsKeyInfo::operator!=(const OpenWifi::GWObjects::DeviceRestrictionsKeyInfo &T) const {
|
||||
return (T.algo!=algo) || (T.vendor!=vendor);
|
||||
}
|
||||
|
||||
bool DeviceRestrictions::operator!=(const OpenWifi::GWObjects::DeviceRestrictions &T) const {
|
||||
return ( (T.dfs!=dfs) ||
|
||||
(T.rtty!=rtty) ||
|
||||
(T.upgrade!=upgrade) ||
|
||||
(T.commands != commands) ||
|
||||
(T.developer != developer) ||
|
||||
(T.ssh !=ssh) ||
|
||||
(T.key_info != key_info) ||
|
||||
(T.country != country) );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -47,6 +47,33 @@ namespace OpenWifi::GWObjects {
|
||||
void to_json(Poco::JSON::Object &Obj) const;
|
||||
};
|
||||
|
||||
struct DeviceRestrictionsKeyInfo {
|
||||
std::string vendor;
|
||||
std::string algo;
|
||||
|
||||
bool operator !=(const DeviceRestrictionsKeyInfo &b) const;
|
||||
|
||||
void to_json(Poco::JSON::Object &Obj) const;
|
||||
bool from_json(const Poco::JSON::Object::Ptr &Obj);
|
||||
};
|
||||
|
||||
struct DeviceRestrictions {
|
||||
bool dfs = false;
|
||||
bool ssh = false;
|
||||
bool rtty = false;
|
||||
bool tty = false;
|
||||
bool developer = false;
|
||||
bool upgrade = false;
|
||||
bool commands = false;
|
||||
std::vector<std::string> country;
|
||||
DeviceRestrictionsKeyInfo key_info;
|
||||
|
||||
bool operator !=(const DeviceRestrictions &D) const;
|
||||
|
||||
void to_json(Poco::JSON::Object &Obj) const;
|
||||
bool from_json(const Poco::JSON::Object::Ptr &Obj);
|
||||
};
|
||||
|
||||
struct Device {
|
||||
std::string SerialNumber;
|
||||
std::string DeviceType;
|
||||
@@ -71,6 +98,9 @@ namespace OpenWifi::GWObjects {
|
||||
uint64_t modified=0;
|
||||
std::string locale;
|
||||
bool restrictedDevice=false;
|
||||
std::string pendingConfiguration;
|
||||
std::string pendingConfigurationCmd;
|
||||
DeviceRestrictions restrictionDetails;
|
||||
|
||||
void to_json(Poco::JSON::Object &Obj) const;
|
||||
void to_json_with_status(Poco::JSON::Object &Obj) const;
|
||||
@@ -216,11 +246,39 @@ namespace OpenWifi::GWObjects {
|
||||
void to_json(Poco::JSON::Object &Obj) const;
|
||||
};
|
||||
|
||||
struct ScriptEntry {
|
||||
std::string id;
|
||||
std::string name;
|
||||
std::string description;
|
||||
std::string uri;
|
||||
std::string content;
|
||||
std::string version;
|
||||
std::string type;
|
||||
std::uint64_t created;
|
||||
std::uint64_t modified;
|
||||
std::string author;
|
||||
Types::StringVec restricted;
|
||||
bool deferred=false;
|
||||
std::uint64_t timeout=30;
|
||||
std::string defaultUploadURI;
|
||||
|
||||
void to_json(Poco::JSON::Object &Obj) const;
|
||||
bool from_json(const Poco::JSON::Object::Ptr &Obj);
|
||||
};
|
||||
|
||||
struct ScriptEntryList {
|
||||
std::vector<ScriptEntry> scripts;
|
||||
|
||||
void to_json(Poco::JSON::Object &Obj) const;
|
||||
bool from_json(const Poco::JSON::Object::Ptr &Obj);
|
||||
};
|
||||
|
||||
struct ScriptRequest {
|
||||
std::string serialNumber;
|
||||
uint64_t timeout=30;
|
||||
std::string type;
|
||||
std::string script;
|
||||
std::string scriptId;
|
||||
std::uint64_t when;
|
||||
std::string signature;
|
||||
bool deferred;
|
||||
@@ -238,6 +296,7 @@ namespace OpenWifi::GWObjects {
|
||||
std::string secret;
|
||||
std::string certificate;
|
||||
bool radsec=false;
|
||||
bool allowSelfSigned=false;
|
||||
uint16_t radsecPort=2083;
|
||||
std::string radsecSecret;
|
||||
std::string radsecKey;
|
||||
@@ -279,4 +338,5 @@ namespace OpenWifi::GWObjects {
|
||||
void to_json(Poco::JSON::Object &Obj) const;
|
||||
bool from_json(const Poco::JSON::Object::Ptr &Obj);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
23
src/ScriptManager.cpp
Normal file
23
src/ScriptManager.cpp
Normal file
@@ -0,0 +1,23 @@
|
||||
//
|
||||
// Created by stephane bourque on 2022-11-21.
|
||||
//
|
||||
|
||||
#include "ScriptManager.h"
|
||||
#include "framework/MicroServiceFuncs.h"
|
||||
#include <fstream>
|
||||
#include "Poco/JSON/Parser.h"
|
||||
|
||||
namespace OpenWifi {
|
||||
|
||||
int ScriptManager::Start() {
|
||||
poco_notice(Logger(),"Starting...");
|
||||
ScriptDir_ = MicroServiceConfigPath("script.manager.directory", MicroServiceDataDirectory() + "/included_scripts" );
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ScriptManager::Stop() {
|
||||
poco_notice(Logger(),"Stopping...");
|
||||
poco_notice(Logger(),"Stopped...");
|
||||
}
|
||||
|
||||
} // namespace OpenWifi
|
||||
34
src/ScriptManager.h
Normal file
34
src/ScriptManager.h
Normal file
@@ -0,0 +1,34 @@
|
||||
//
|
||||
// Created by stephane bourque on 2022-11-21.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "framework/SubSystemServer.h"
|
||||
|
||||
namespace OpenWifi {
|
||||
|
||||
class ScriptManager : public SubSystemServer {
|
||||
public:
|
||||
static auto instance() {
|
||||
auto static instance_ = new ScriptManager;
|
||||
return instance_;
|
||||
}
|
||||
|
||||
int Start();
|
||||
void Stop();
|
||||
|
||||
private:
|
||||
std::string ScriptDir_;
|
||||
|
||||
explicit ScriptManager() noexcept:
|
||||
SubSystemServer("ScriptManager", "SCRIPT-MGR", "script.manager")
|
||||
{
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
inline auto ScriptManager() { return ScriptManager::instance(); }
|
||||
|
||||
} // namespace OpenWifi
|
||||
|
||||
7
src/SignatureMgr.cpp
Normal file
7
src/SignatureMgr.cpp
Normal file
@@ -0,0 +1,7 @@
|
||||
//
|
||||
// Created by stephane bourque on 2022-11-22.
|
||||
//
|
||||
|
||||
#include "SignatureMgr.h"
|
||||
|
||||
namespace OpenWifi {} // namespace OpenWifi
|
||||
176
src/SignatureMgr.h
Normal file
176
src/SignatureMgr.h
Normal file
@@ -0,0 +1,176 @@
|
||||
//
|
||||
// Created by stephane bourque on 2022-11-22.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <fstream>
|
||||
#include <shared_mutex>
|
||||
|
||||
#include "framework/SubSystemServer.h"
|
||||
#include "framework/MicroServiceFuncs.h"
|
||||
#include "framework/utils.h"
|
||||
|
||||
#include "RESTObjects/RESTAPI_GWobjects.h"
|
||||
#include "Poco/DigestStream.h"
|
||||
#include "Poco/DigestEngine.h"
|
||||
#include "Poco/Crypto/RSADigestEngine.h"
|
||||
#include "Poco/StreamCopier.h"
|
||||
#include "Poco/File.h"
|
||||
#include "Poco/StringTokenizer.h"
|
||||
#include "Poco/TemporaryFile.h"
|
||||
#include "fmt/format.h"
|
||||
|
||||
namespace OpenWifi {
|
||||
|
||||
class SignatureManager : public SubSystemServer {
|
||||
public:
|
||||
inline static auto instance() {
|
||||
static auto instance_ = new SignatureManager;
|
||||
return instance_;
|
||||
}
|
||||
|
||||
struct SignatureCacheEntry {
|
||||
std::string vendor_uri_hash;
|
||||
std::string signature;
|
||||
};
|
||||
|
||||
inline int Start() final {
|
||||
poco_notice(Logger(),"Starting...");
|
||||
|
||||
std::shared_lock L(KeyMutex_);
|
||||
|
||||
CacheFilename_ = MicroServiceDataDirectory() + "/signature_cache";
|
||||
Poco::File CacheFile(CacheFilename_);
|
||||
|
||||
if(CacheFile.exists()) {
|
||||
std::fstream CacheFileContent(CacheFilename_, std::ios_base::in);
|
||||
std::string line;
|
||||
while(std::getline(CacheFileContent, line)) {
|
||||
auto Tokens = Poco::StringTokenizer(line,":");
|
||||
if(Tokens.count()==2) {
|
||||
SignatureCache_[Tokens[0]] = Tokens[1];
|
||||
}
|
||||
}
|
||||
}
|
||||
poco_information(Logger(),fmt::format("Found {} entries in signature cache.", SignatureCache_.size()));
|
||||
|
||||
// read all the key vendors.
|
||||
// signature.manager.0.key.public
|
||||
// signature.manager.0.key.private
|
||||
// signature.manager.0.vendor
|
||||
int i=0;
|
||||
while(true) {
|
||||
auto Vendor = MicroServiceConfigGetString("signature.manager." + std::to_string(i) + ".vendor","");
|
||||
auto PrivateKey = MicroServiceConfigPath("signature.manager." + std::to_string(i) + ".key.private","");
|
||||
auto PublicKey = MicroServiceConfigPath("signature.manager." + std::to_string(i) + ".key.public","");
|
||||
if(Vendor.empty() || PrivateKey.empty() || PublicKey.empty()) {
|
||||
break;
|
||||
}
|
||||
Poco::File PubKey(PublicKey), PrivKey(PrivateKey);
|
||||
if(PubKey.exists() && PrivKey.exists()) {
|
||||
Keys_[Vendor] = Poco::SharedPtr<Poco::Crypto::RSAKey>(
|
||||
new Poco::Crypto::RSAKey(PublicKey, PrivateKey, ""));
|
||||
}
|
||||
++i;
|
||||
}
|
||||
|
||||
poco_information(Logger(),fmt::format("{} signatures in dictionary.", Keys_.size()));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
inline void Stop() final {
|
||||
poco_notice(Logger(),"Stopping...");
|
||||
poco_notice(Logger(),"Stopped...");
|
||||
}
|
||||
|
||||
inline std::string Sign(const GWObjects::DeviceRestrictions &Restrictions, const std::string &Data) const {
|
||||
std::shared_lock L(KeyMutex_);
|
||||
try {
|
||||
if (Restrictions.key_info.algo == "static") {
|
||||
return "aaaaaaaaaa";
|
||||
}
|
||||
auto Vendor = Keys_.find(Restrictions.key_info.vendor);
|
||||
if (Vendor == Keys_.end()) {
|
||||
poco_error( Logger(), fmt::format("{}: vendor unknown.", Vendor->first));
|
||||
return "";
|
||||
}
|
||||
|
||||
if (Restrictions.key_info.algo == "dgst-sha256") {
|
||||
Poco::Crypto::RSADigestEngine R(*Vendor->second, "SHA256");
|
||||
Poco::DigestOutputStream ostr(R);
|
||||
ostr << Data;
|
||||
ostr.flush();
|
||||
auto Signature = Utils::base64encode(
|
||||
(const unsigned char *)R.signature().data(), R.signature().size());
|
||||
return Signature;
|
||||
}
|
||||
} catch (const Poco::Exception &E) {
|
||||
Logger().log(E);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
inline std::string Sign(const GWObjects::DeviceRestrictions &Restrictions, const Poco::URI &uri) {
|
||||
std::shared_lock L(KeyMutex_);
|
||||
try {
|
||||
if (Restrictions.key_info.algo == "static") {
|
||||
return "aaaaaaaaaa";
|
||||
}
|
||||
|
||||
auto Vendor = Keys_.find(Restrictions.key_info.vendor);
|
||||
if (Vendor == Keys_.end()) {
|
||||
poco_error( Logger(), fmt::format("{}: vendor unknown.", Restrictions.key_info.vendor));
|
||||
return "";
|
||||
}
|
||||
|
||||
if (Restrictions.key_info.algo == "dgst-sha256") {
|
||||
auto FileHash =
|
||||
Utils::ComputeHash(Restrictions.key_info.vendor, Restrictions.key_info.algo, uri.getPathAndQuery());
|
||||
auto CacheEntry = SignatureCache_.find(FileHash);
|
||||
if (CacheEntry != end(SignatureCache_)) {
|
||||
return CacheEntry->second;
|
||||
}
|
||||
|
||||
Poco::TemporaryFile TempDownloadedFile;
|
||||
if (Utils::wgetfile(uri, TempDownloadedFile.path())) {
|
||||
Poco::Crypto::RSADigestEngine R(*Vendor->second, "SHA256");
|
||||
Poco::DigestOutputStream ofs(R);
|
||||
std::fstream ifs(TempDownloadedFile.path(),
|
||||
std::ios_base::in | std::ios_base::binary);
|
||||
Poco::StreamCopier::copyStream(ifs, ofs);
|
||||
ofs.flush();
|
||||
auto Signature = Utils::base64encode((const unsigned char *)R.signature().data(),R.signature().size());
|
||||
SignatureCache_[FileHash] = Signature;
|
||||
SaveCache();
|
||||
return Signature;
|
||||
}
|
||||
}
|
||||
} catch (const Poco::Exception &E) {
|
||||
Logger().log(E);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
void SaveCache() {
|
||||
std::ofstream ofs(CacheFilename_, std::ios_base::trunc | std::ios_base::out);
|
||||
|
||||
for(const auto &[hash,signature]:SignatureCache_) {
|
||||
ofs << hash << ":" << signature << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
mutable std::shared_mutex KeyMutex_;
|
||||
std::map<std::string, Poco::SharedPtr<Poco::Crypto::RSAKey>> Keys_;
|
||||
std::map<std::string,std::string> SignatureCache_;
|
||||
std::string CacheFilename_;
|
||||
explicit SignatureManager() noexcept
|
||||
: SubSystemServer("SignatureManager", "SIGNATURE-MGR", "signature.manager") {}
|
||||
};
|
||||
|
||||
inline auto SignatureManager() { return SignatureManager::instance(); }
|
||||
|
||||
}
|
||||
|
||||
@@ -12,7 +12,14 @@ namespace OpenWifi::StateUtils {
|
||||
return 5;
|
||||
}
|
||||
|
||||
bool ComputeAssociations(const Poco::JSON::Object::Ptr & RawObject,
|
||||
static int BandToInt(const std::string &band) {
|
||||
if(band=="2G") return 2;
|
||||
if(band=="5G") return 5;
|
||||
if(band=="6G") return 6;
|
||||
return 2;
|
||||
}
|
||||
|
||||
bool ComputeAssociations(const Poco::JSON::Object::Ptr RawObject,
|
||||
uint64_t &Radios_2G,
|
||||
uint64_t &Radios_5G, uint64_t &Radios_6G) {
|
||||
Radios_2G = 0 ;
|
||||
@@ -24,47 +31,56 @@ namespace OpenWifi::StateUtils {
|
||||
// map of phy to 2g/5g
|
||||
std::map<std::string,int> RadioPHYs;
|
||||
// parse radios and get the phy out with the band
|
||||
bool UseBandInfo = false;
|
||||
for(auto const &i:*RA) {
|
||||
Poco::JSON::Parser p2;
|
||||
// Poco::JSON::Parser p2;
|
||||
auto RadioObj = i.extract<Poco::JSON::Object::Ptr>();
|
||||
if(RadioObj->has("phy") && RadioObj->has("channel")) {
|
||||
if(RadioObj->has("band")) {
|
||||
// std::cout << "Use band info" << std::endl;
|
||||
UseBandInfo = true ;
|
||||
} else if(RadioObj->has("phy") && RadioObj->has("channel")) {
|
||||
if(RadioObj->isArray("channel")) {
|
||||
auto ChannelArray = RadioObj->getArray("channel");
|
||||
if(ChannelArray->size()) {
|
||||
RadioPHYs[RadioObj->get("phy").toString()] =
|
||||
RadioPHYs[RadioObj->get("phy")] =
|
||||
ChannelToBand( ChannelArray->getElement<uint64_t>(0) );
|
||||
}
|
||||
} else {
|
||||
RadioPHYs[RadioObj->get("phy").toString()] =
|
||||
RadioPHYs[RadioObj->get("phy")] =
|
||||
ChannelToBand(RadioObj->get("channel"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto IA = RawObject->getArray("interfaces");
|
||||
for(auto const &i:*IA) {
|
||||
auto InterfaceObj = i.extract<Poco::JSON::Object::Ptr>();
|
||||
auto InterfaceArray = RawObject->getArray("interfaces");
|
||||
for(auto const &interface:*InterfaceArray) {
|
||||
auto InterfaceObj = interface.extract<Poco::JSON::Object::Ptr>();
|
||||
if(InterfaceObj->isArray("ssids")) {
|
||||
auto SSIDA = InterfaceObj->getArray("ssids");
|
||||
for(const auto &s:*SSIDA) {
|
||||
auto SSIDinfo = s.extract<Poco::JSON::Object::Ptr>();
|
||||
if(SSIDinfo->isArray("associations") && SSIDinfo->has("phy")) {
|
||||
auto PHY = SSIDinfo->get("phy").toString();
|
||||
auto SSIDArray = InterfaceObj->getArray("ssids");
|
||||
for(const auto &ssid:*SSIDArray) {
|
||||
auto SSID_info = ssid.extract<Poco::JSON::Object::Ptr>();
|
||||
if(SSID_info->isArray("associations") && SSID_info->has("phy")) {
|
||||
int Radio = 2;
|
||||
auto Rit = RadioPHYs.find(PHY);
|
||||
if(Rit!=RadioPHYs.end())
|
||||
Radio = Rit->second;
|
||||
auto AssocA = SSIDinfo->getArray("associations");
|
||||
if(Radio==2) {
|
||||
Radios_2G += AssocA->size();
|
||||
if(UseBandInfo) {
|
||||
Radio = BandToInt(SSID_info->get("band"));
|
||||
} else {
|
||||
auto PHY = SSID_info->get("phy");
|
||||
auto Rit = RadioPHYs.find(PHY);
|
||||
if (Rit != RadioPHYs.end())
|
||||
Radio = Rit->second;
|
||||
}
|
||||
else {
|
||||
Radios_5G += AssocA->size();
|
||||
auto AssocA = SSID_info->getArray("associations");
|
||||
switch(Radio) {
|
||||
case 2: Radios_2G += AssocA->size(); break;
|
||||
case 5: Radios_5G += AssocA->size(); break;
|
||||
case 6: Radios_6G += AssocA->size(); break;
|
||||
default: Radios_2G += AssocA->size(); break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// std::cout << Radios_2G << " " << Radios_5G << " " << Radios_6G << std::endl;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
||||
@@ -7,6 +7,6 @@
|
||||
#include "Poco/JSON/Object.h"
|
||||
|
||||
namespace OpenWifi::StateUtils {
|
||||
bool ComputeAssociations(const Poco::JSON::Object::Ptr & RawObject, uint64_t &Radios_2G,
|
||||
bool ComputeAssociations(const Poco::JSON::Object::Ptr RawObject, uint64_t &Radios_2G,
|
||||
uint64_t &Radios_5G, uint64_t &Radio_6G);
|
||||
}
|
||||
@@ -18,36 +18,40 @@ namespace OpenWifi {
|
||||
void Archiver::onTimer([[maybe_unused]] Poco::Timer &timer){
|
||||
Utils::SetThreadName("strg-archiver");
|
||||
auto now = Utils::Now();
|
||||
for(const auto &i:DBs_) {
|
||||
if (!Poco::icompare(i.DBName, "healthchecks")) {
|
||||
for(const auto &[DBName, Keep]:DBs_) {
|
||||
if (!Poco::icompare(DBName, "healthchecks")) {
|
||||
poco_information(Logger(),"Archiving HealthChecks...");
|
||||
StorageService()->RemoveHealthChecksRecordsOlderThan(
|
||||
now - (i.HowManyDays * 24 * 60 * 60));
|
||||
} else if (!Poco::icompare(i.DBName, "statistics")) {
|
||||
now - (Keep * 24 * 60 * 60));
|
||||
} else if (!Poco::icompare(DBName, "statistics")) {
|
||||
poco_information(Logger(),"Archiving Statistics...");
|
||||
StorageService()->RemoveStatisticsRecordsOlderThan(
|
||||
now - (i.HowManyDays * 24 * 60 * 60));
|
||||
} else if (!Poco::icompare(i.DBName, "devicelogs")) {
|
||||
now - (Keep * 24 * 60 * 60));
|
||||
} else if (!Poco::icompare(DBName, "devicelogs")) {
|
||||
poco_information(Logger(),"Archiving Device Logs...");
|
||||
StorageService()->RemoveDeviceLogsRecordsOlderThan(
|
||||
now - (i.HowManyDays * 24 * 60 * 60));
|
||||
} else if (!Poco::icompare(i.DBName, "commandlist")) {
|
||||
now - (Keep * 24 * 60 * 60));
|
||||
} else if (!Poco::icompare(DBName, "commandlist")) {
|
||||
poco_information(Logger(),"Archiving Command History...");
|
||||
StorageService()->RemoveCommandListRecordsOlderThan(
|
||||
now - (i.HowManyDays * 24 * 60 * 60));
|
||||
now - (Keep * 24 * 60 * 60));
|
||||
} else if (!Poco::icompare(DBName, "fileuploads")) {
|
||||
poco_information(Logger(),"Archiving Upload files...");
|
||||
StorageService()->RemoveUploadedFilesRecordsOlderThan(
|
||||
now - (Keep * 24 * 60 * 60));
|
||||
} else {
|
||||
poco_information(Logger(),fmt::format("Cannot archive DB '{}'", i.DBName));
|
||||
poco_information(Logger(),fmt::format("Cannot archive DB '{}'", DBName));
|
||||
}
|
||||
}
|
||||
AppServiceRegistry().Set("lastStorageArchiverRun", (uint64_t) now);
|
||||
}
|
||||
|
||||
static auto CalculateDelta(int H, int M) {
|
||||
static auto CalculateDelta(std::uint64_t H, std::uint64_t M) {
|
||||
Poco::LocalDateTime dt;
|
||||
Poco::LocalDateTime scheduled(dt.year(), dt.month(), dt.day(), H, M, 0);
|
||||
Poco::LocalDateTime scheduled(dt.year(), dt.month(), dt.day(), (int)H, (int)M, 0);
|
||||
|
||||
size_t delta = 0;
|
||||
if ((dt.hour() < H) || (dt.hour()==H && dt.minute()<M)) {
|
||||
std::uint64_t delta = 0;
|
||||
if ((dt.hour() < (int)H) || (dt.hour()==(int)H && dt.minute()<(int)M)) {
|
||||
delta = scheduled.timestamp().epochTime() - dt.timestamp().epochTime();
|
||||
} else {
|
||||
delta = (24*60*60) - (dt.timestamp().epochTime() - scheduled.timestamp().epochTime());
|
||||
@@ -69,13 +73,13 @@ namespace OpenWifi {
|
||||
auto Schedule = MicroServiceConfigGetString("archiver.schedule","03:00");
|
||||
auto S = Poco::StringTokenizer(Schedule,":");
|
||||
|
||||
int RunAtHour_, RunAtMin_;
|
||||
std::uint64_t RunAtHour_, RunAtMin_;
|
||||
if(S.count()!=2) {
|
||||
RunAtHour_ = 3 ;
|
||||
RunAtMin_ = 0;
|
||||
} else {
|
||||
RunAtHour_ = std::atoi(S[0].c_str());
|
||||
RunAtMin_ = std::atoi(S[1].c_str());
|
||||
RunAtHour_ = std::strtoull(S[0].c_str(), nullptr, 10);
|
||||
RunAtMin_ = std::strtoull(S[1].c_str(), nullptr, 10);
|
||||
}
|
||||
|
||||
for(int i=0;i<20;i++) {
|
||||
@@ -86,10 +90,7 @@ namespace OpenWifi {
|
||||
if(Poco::icompare(DBName,DB)==0) {
|
||||
std::string Key = "archiver.db." + std::to_string(i) + ".keep";
|
||||
auto Keep = MicroServiceConfigGetInt(Key,7);
|
||||
Archiver_->AddDb(Archiver::ArchiverDBEntry{
|
||||
.DBName = DB,
|
||||
.HowManyDays = Keep
|
||||
});
|
||||
Archiver_->AddDb(DB, Keep);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,28 +13,26 @@
|
||||
|
||||
namespace OpenWifi {
|
||||
|
||||
static const std::list<std::string> AllInternalDBNames{"healthchecks", "statistics", "devicelogs" , "commandlist" };
|
||||
static const std::list<std::string> AllInternalDBNames{"healthchecks", "statistics", "devicelogs" , "commandlist", "fileuploads"};
|
||||
|
||||
class Archiver {
|
||||
public:
|
||||
struct ArchiverDBEntry {
|
||||
std::string DBName;
|
||||
uint64_t HowManyDays=7;
|
||||
};
|
||||
typedef std::vector<ArchiverDBEntry> ArchiverDBEntryVec;
|
||||
|
||||
explicit Archiver(Poco::Logger &Logger):
|
||||
Logger_(Logger) {
|
||||
for(const auto &db:AllInternalDBNames) {
|
||||
DBs_[db] = 7 ;
|
||||
}
|
||||
}
|
||||
|
||||
void onTimer(Poco::Timer & timer);
|
||||
inline void AddDb(const ArchiverDBEntry &E ) {
|
||||
DBs_.push_back(E);
|
||||
inline void AddDb(const std::string &dbname, std::uint64_t retain) {
|
||||
DBs_[dbname] = retain;
|
||||
}
|
||||
inline Poco::Logger & Logger() { return Logger_; }
|
||||
private:
|
||||
Poco::Logger &Logger_;
|
||||
ArchiverDBEntryVec DBs_;
|
||||
Poco::Logger &Logger_;
|
||||
std::map<std::string,std::uint64_t> DBs_;
|
||||
};
|
||||
|
||||
class StorageArchiver : public SubSystemServer {
|
||||
|
||||
@@ -17,6 +17,10 @@ namespace OpenWifi {
|
||||
Create_Tables();
|
||||
InitializeBlackListCache();
|
||||
|
||||
ScriptDB_ = std::make_unique<OpenWifi::ScriptDB>("Scripts", "scr", dbType_,*Pool_, Logger());
|
||||
ScriptDB_->Create();
|
||||
ScriptDB_->Initialize();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#include "RESTObjects//RESTAPI_GWobjects.h"
|
||||
#include "Poco/Net/IPAddress.h"
|
||||
#include "CentralConfig.h"
|
||||
#include "storage/storage_scripts.h"
|
||||
|
||||
namespace OpenWifi {
|
||||
|
||||
@@ -29,6 +30,8 @@ namespace OpenWifi {
|
||||
COMMAND_EXECUTING
|
||||
};
|
||||
|
||||
inline OpenWifi::ScriptDB & ScriptDB() { return *ScriptDB_; }
|
||||
|
||||
inline std::string to_string(const CommandExecutionType &C) {
|
||||
switch(C) {
|
||||
case CommandExecutionType::COMMAND_PENDING: return "pending";
|
||||
@@ -147,10 +150,8 @@ namespace OpenWifi {
|
||||
bool GetReadyToExecuteCommands( uint64_t Offset, uint64_t HowMany, std::vector<GWObjects::CommandDetails> & Commands );
|
||||
bool CommandExecuted(std::string & UUID);
|
||||
bool CommandCompleted(std::string & UUID, Poco::JSON::Object::Ptr ReturnVars, const std::chrono::duration<double, std::milli> & execution_time, bool FullCommand);
|
||||
// bool AttachFileToCommand(std::string & UUID);
|
||||
bool AttachFileDataToCommand(std::string & UUID, const std::stringstream &s, const std::string &Type);
|
||||
bool CancelWaitFile( std::string & UUID, std::string & ErrorText );
|
||||
// bool GetAttachedFile(std::string & UUID, const std::string & SerialNumber, const std::string & FileName, std::string &Type);
|
||||
bool GetAttachedFileContent(std::string & UUID, const std::string & SerialNumber, std::string & FileContent, std::string &Type);
|
||||
bool RemoveAttachedFile(std::string & UUID);
|
||||
bool SetCommandResult(std::string & UUID, std::string & Result);
|
||||
@@ -177,6 +178,7 @@ namespace OpenWifi {
|
||||
bool RemoveDeviceLogsRecordsOlderThan(uint64_t Date);
|
||||
bool RemoveStatisticsRecordsOlderThan(uint64_t Date);
|
||||
bool RemoveCommandListRecordsOlderThan(uint64_t Date);
|
||||
bool RemoveUploadedFilesRecordsOlderThan(uint64_t Date);
|
||||
|
||||
int Create_Tables();
|
||||
int Create_Statistics();
|
||||
@@ -197,6 +199,8 @@ namespace OpenWifi {
|
||||
|
||||
private:
|
||||
|
||||
std::unique_ptr<OpenWifi::ScriptDB> ScriptDB_;
|
||||
|
||||
};
|
||||
|
||||
inline auto StorageService() { return Storage::instance(); }
|
||||
|
||||
@@ -51,7 +51,13 @@ namespace OpenWifi {
|
||||
poco_information(Logger(),"Starting...");
|
||||
Running_=true;
|
||||
Port_ = (int)MicroServiceConfigGetInt("alb.port",15015);
|
||||
Socket_ = std::make_unique<Poco::Net::ServerSocket>(Port_);
|
||||
Poco::Net::IPAddress Addr(Poco::Net::IPAddress::wildcard(
|
||||
Poco::Net::Socket::supportsIPv6() ? Poco::Net::AddressFamily::IPv6
|
||||
: Poco::Net::AddressFamily::IPv4));
|
||||
Poco::Net::SocketAddress SockAddr(Addr, Port_);
|
||||
Poco::Net::ServerSocket ClientSocket(SockAddr, 64);
|
||||
|
||||
Socket_ = std::make_unique<Poco::Net::ServerSocket>(SockAddr, Port_);
|
||||
auto Params = new Poco::Net::HTTPServerParams;
|
||||
Params->setName("ws:alb");
|
||||
Server_ = std::make_unique<Poco::Net::HTTPServer>(new ALBRequestHandlerFactory(Logger()), *Socket_, Params);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -245,7 +245,7 @@ namespace OpenWifi {
|
||||
Poco::Logger::root().setChannel(Splitter);
|
||||
}
|
||||
}
|
||||
|
||||
Poco::Logger::root().information(fmt::format("Enabled console logs: asynch={} websocket={}",UseAsync,DisableWebSocketLogging));
|
||||
}
|
||||
|
||||
void MicroService::SetColorConsoleLogs(bool UseAsync, bool DisableWebSocketLogging, const std::string & FormatterPattern) {
|
||||
@@ -274,7 +274,7 @@ namespace OpenWifi {
|
||||
Poco::Logger::root().setChannel(Splitter);
|
||||
}
|
||||
}
|
||||
|
||||
Poco::Logger::root().information(fmt::format("Enabled color console logs: asynch={} websocket={}",UseAsync,DisableWebSocketLogging));
|
||||
}
|
||||
|
||||
void MicroService::SetSQLLogs([[maybe_unused]] bool UseAsync,[[maybe_unused]] bool DisableWebSocketLogging,[[maybe_unused]] const std::string & FormatterPattern) {
|
||||
@@ -327,6 +327,7 @@ namespace OpenWifi {
|
||||
Poco::Logger::root().setChannel(Splitter);
|
||||
}
|
||||
}
|
||||
Poco::Logger::root().information(fmt::format("Enabled file logs: asynch={} websocket={}",UseAsync,DisableWebSocketLogging));
|
||||
}
|
||||
|
||||
void DaemonPostInitialization(Poco::Util::Application &self);
|
||||
|
||||
@@ -102,6 +102,48 @@ namespace OpenWifi {
|
||||
E.displayText(),
|
||||
E.message(),
|
||||
E.what()));
|
||||
} catch (const Poco::TimeoutException &E) {
|
||||
poco_error(App_.logger(), fmt::format("Poco::TimeoutException thr_name={} thr_id={} code={} text={} msg={} what={}",
|
||||
t_name, t_id, E.code(),
|
||||
E.displayText(),
|
||||
E.message(),
|
||||
E.what()));
|
||||
} catch (const Poco::NoThreadAvailableException &E) {
|
||||
poco_error(App_.logger(), fmt::format("Poco::NoThreadAvailableException thr_name={} thr_id={} code={} text={} msg={} what={}",
|
||||
t_name, t_id, E.code(),
|
||||
E.displayText(),
|
||||
E.message(),
|
||||
E.what()));
|
||||
} catch (const Poco::OutOfMemoryException &E) {
|
||||
poco_error(App_.logger(), fmt::format("Poco::OutOfMemoryException thr_name={} thr_id={} code={} text={} msg={} what={}",
|
||||
t_name, t_id, E.code(),
|
||||
E.displayText(),
|
||||
E.message(),
|
||||
E.what()));
|
||||
} catch (const Poco::BadCastException &E) {
|
||||
poco_error(App_.logger(), fmt::format("Poco::BadCastException thr_name={} thr_id={} code={} text={} msg={} what={}",
|
||||
t_name, t_id, E.code(),
|
||||
E.displayText(),
|
||||
E.message(),
|
||||
E.what()));
|
||||
} catch (const Poco::DataException &E) {
|
||||
poco_error(App_.logger(), fmt::format("Poco::DataException thr_name={} thr_id={} code={} text={} msg={} what={}",
|
||||
t_name, t_id, E.code(),
|
||||
E.displayText(),
|
||||
E.message(),
|
||||
E.what()));
|
||||
} catch (const Poco::PoolOverflowException &E) {
|
||||
poco_error(App_.logger(), fmt::format("Poco::PoolOverflowException thr_name={} thr_id={} code={} text={} msg={} what={}",
|
||||
t_name, t_id, E.code(),
|
||||
E.displayText(),
|
||||
E.message(),
|
||||
E.what()));
|
||||
} catch (const Poco::SystemException &E) {
|
||||
poco_error(App_.logger(), fmt::format("Poco::SystemException thr_name={} thr_id={} code={} text={} msg={} what={}",
|
||||
t_name, t_id, E.code(),
|
||||
E.displayText(),
|
||||
E.message(),
|
||||
E.what()));
|
||||
} catch (const Poco::RuntimeException &E) {
|
||||
poco_error(App_.logger(), fmt::format("Poco::RuntimeException thr_name={} thr_id={} code={} text={} msg={} what={}",
|
||||
t_name, t_id, E.code(),
|
||||
|
||||
@@ -633,6 +633,18 @@ namespace OpenWifi {
|
||||
ReturnObject(Answer);
|
||||
}
|
||||
|
||||
template<typename T> void Object(const char *Name, const std::vector<T> & Objects) {
|
||||
Poco::JSON::Object Answer;
|
||||
RESTAPI_utils::field_to_json(Answer,Name,Objects);
|
||||
ReturnObject(Answer);
|
||||
}
|
||||
|
||||
template <typename T> void Object(const T &O) {
|
||||
Poco::JSON::Object Answer;
|
||||
O.to_json(Answer);
|
||||
ReturnObject(Answer);
|
||||
}
|
||||
|
||||
Poco::Logger & Logger() { return Logger_; }
|
||||
|
||||
virtual void DoGet() = 0 ;
|
||||
|
||||
@@ -119,7 +119,7 @@ namespace OpenWifi {
|
||||
}
|
||||
|
||||
bool UI_WebSocketClientServer::SendToUser(const std::string &UserName, std::uint64_t id, const std::string &Payload) {
|
||||
std::lock_guard G(Mutex_);
|
||||
std::lock_guard G(LocalMutex_);
|
||||
|
||||
for(const auto &Client:Clients_) {
|
||||
if(Client.second->UserName_ == UserName) {
|
||||
@@ -139,7 +139,7 @@ namespace OpenWifi {
|
||||
}
|
||||
|
||||
void UI_WebSocketClientServer::SendToAll(std::uint64_t id, const std::string &Payload) {
|
||||
std::lock_guard G(Mutex_);
|
||||
std::lock_guard G(LocalMutex_);
|
||||
|
||||
for(const auto &Client:Clients_) {
|
||||
try {
|
||||
@@ -189,7 +189,6 @@ namespace OpenWifi {
|
||||
void UI_WebSocketClientServer::OnSocketReadable([[maybe_unused]] const Poco::AutoPtr<Poco::Net::ReadableNotification> &pNf) {
|
||||
|
||||
UI_WebSocketClientServer::ClientList::iterator Client;
|
||||
|
||||
std::lock_guard G(LocalMutex_);
|
||||
|
||||
try {
|
||||
@@ -295,6 +294,7 @@ namespace OpenWifi {
|
||||
|
||||
void UI_WebSocketClientServer::OnSocketShutdown([[maybe_unused]] const Poco::AutoPtr<Poco::Net::ShutdownNotification> &pNf) {
|
||||
try {
|
||||
std::lock_guard G(LocalMutex_);
|
||||
auto Client = Clients_.find(pNf->socket().impl()->sockfd());
|
||||
if (Client == end(Clients_))
|
||||
return;
|
||||
|
||||
@@ -229,7 +229,11 @@ namespace OpenWifi::RESTAPI::Errors {
|
||||
static const struct msg ApiKeyDoesNotExist{1150,"API Key does not exist."};
|
||||
|
||||
static const struct msg DeviceIsRestricted{1151,"Device is protected by regulation. This function is not allowed."};
|
||||
}
|
||||
static const struct msg InvalidURI{1152,"Invalid URI."};
|
||||
static const struct msg InvalidScriptSelection{1153,"Only script or scriptId must be specified. Not both."};
|
||||
|
||||
static const struct msg NoDeviceStatisticsYet{1154,"Device statistics not available yet."};
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -524,6 +528,63 @@ namespace OpenWifi::uCentralProtocol::Events {
|
||||
};
|
||||
}
|
||||
|
||||
namespace OpenWifi::APCommands {
|
||||
enum class Commands:uint8_t {
|
||||
capabilities,
|
||||
logs,
|
||||
healthchecks,
|
||||
statistics,
|
||||
status,
|
||||
rtty,
|
||||
configure,
|
||||
upgrade,
|
||||
reboot,
|
||||
factory,
|
||||
leds,
|
||||
trace,
|
||||
request,
|
||||
wifiscan,
|
||||
eventqueue,
|
||||
telemetry,
|
||||
ping,
|
||||
script,
|
||||
unknown
|
||||
};
|
||||
|
||||
inline static const std::vector<const char *> uCentralAPCommands {
|
||||
RESTAPI::Protocol::CAPABILITIES,
|
||||
RESTAPI::Protocol::LOGS,
|
||||
RESTAPI::Protocol::HEALTHCHECKS,
|
||||
RESTAPI::Protocol::STATISTICS,
|
||||
RESTAPI::Protocol::STATUS,
|
||||
RESTAPI::Protocol::RTTY,
|
||||
RESTAPI::Protocol::CONFIGURE,
|
||||
RESTAPI::Protocol::UPGRADE,
|
||||
RESTAPI::Protocol::REBOOT,
|
||||
RESTAPI::Protocol::FACTORY,
|
||||
RESTAPI::Protocol::LEDS,
|
||||
RESTAPI::Protocol::TRACE,
|
||||
RESTAPI::Protocol::REQUEST,
|
||||
RESTAPI::Protocol::WIFISCAN,
|
||||
RESTAPI::Protocol::EVENTQUEUE,
|
||||
RESTAPI::Protocol::TELEMETRY,
|
||||
RESTAPI::Protocol::PING,
|
||||
RESTAPI::Protocol::SCRIPT};
|
||||
|
||||
inline const char * to_string(Commands Cmd) {
|
||||
return uCentralAPCommands[(uint8_t)Cmd];
|
||||
}
|
||||
|
||||
inline Commands to_apcommand(const char *cmd) {
|
||||
for(auto i=(uint8_t)Commands::capabilities;i!=(uint8_t)Commands::unknown;++i) {
|
||||
if(strcmp(uCentralAPCommands[i],cmd)==0)
|
||||
return (Commands)i;
|
||||
}
|
||||
return Commands::unknown;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace OpenWifi::Provisioning::DeviceClass {
|
||||
|
||||
static const char * ANY = "any";
|
||||
|
||||
@@ -487,6 +487,25 @@ void ReplaceVariables( std::string & Content , const Types::StringPairVec & P) {
|
||||
return false;
|
||||
}
|
||||
|
||||
[[nodiscard]] bool wgetfile(const Poco::URI &uri, const std::string &FileName) {
|
||||
try {
|
||||
Poco::Net::HTTPSClientSession session(uri.getHost(), uri.getPort());
|
||||
|
||||
// send request
|
||||
Poco::Net::HTTPRequest req(Poco::Net::HTTPRequest::HTTP_GET, uri.getPath(), Poco::Net::HTTPMessage::HTTP_1_1);
|
||||
session.sendRequest(req);
|
||||
|
||||
Poco::Net::HTTPResponse res;
|
||||
std::istream &is = session.receiveResponse(res);
|
||||
std::fstream os(FileName,std::ios_base::trunc | std::ios_base::binary | std::ios_base::out);
|
||||
Poco::StreamCopier::copyStream(is,os);
|
||||
return true;
|
||||
} catch (...) {
|
||||
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ExtractBase64CompressedData(const std::string &CompressedData,
|
||||
std::string &UnCompressedData, uint64_t compress_sz ) {
|
||||
std::istringstream ifs(CompressedData);
|
||||
@@ -531,4 +550,14 @@ bool ExtractBase64CompressedData(const std::string &CompressedData,
|
||||
return "*******";
|
||||
}
|
||||
|
||||
[[nodiscard]] bool ValidateURI(const std::string &uri) {
|
||||
try {
|
||||
Poco::URI u(uri);
|
||||
return true;
|
||||
} catch (...) {
|
||||
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#include <random>
|
||||
#include <regex>
|
||||
#include <thread>
|
||||
#include <shared_mutex>
|
||||
|
||||
#include "Poco/Thread.h"
|
||||
#include "Poco/StringTokenizer.h"
|
||||
@@ -115,8 +116,10 @@ namespace OpenWifi::Utils {
|
||||
[[nodiscard]] std::string BinaryFileToHexString(const Poco::File &F);
|
||||
[[nodiscard]] std::string SecondsToNiceText(uint64_t Seconds);
|
||||
[[nodiscard]] bool wgets(const std::string &URL, std::string &Response);
|
||||
[[nodiscard]] bool IsAlphaNumeric(const std::string &s);
|
||||
[[nodiscard]] bool wgetfile(const Poco::URI &uri, const std::string &FileName);
|
||||
[[nodiscard]] bool IsAlphaNumeric(const std::string &s);
|
||||
[[nodiscard]] std::string SanitizeToken(const std::string &Token);
|
||||
[[nodiscard]] bool ValidateURI(const std::string &uri);
|
||||
|
||||
template< typename T >
|
||||
std::string int_to_hex( T i )
|
||||
@@ -126,6 +129,23 @@ namespace OpenWifi::Utils {
|
||||
<< std::hex << i;
|
||||
return stream.str();
|
||||
}
|
||||
|
||||
inline bool SpinLock_Read(std::shared_mutex &M, volatile bool &Flag, uint64_t wait_ms=100) {
|
||||
while(!M.try_lock_shared() && Flag) {
|
||||
Poco::Thread::yield();
|
||||
Poco::Thread::trySleep((long)wait_ms);
|
||||
}
|
||||
return Flag;
|
||||
}
|
||||
|
||||
inline bool SpinLock_Write(std::shared_mutex &M, volatile bool &Flag, uint64_t wait_ms=100) {
|
||||
while(!M.try_lock() && Flag) {
|
||||
Poco::Thread::yield();
|
||||
Poco::Thread::trySleep(wait_ms);
|
||||
}
|
||||
return Flag;
|
||||
}
|
||||
|
||||
bool ExtractBase64CompressedData(const std::string &CompressedData,
|
||||
std::string &UnCompressedData, uint64_t compress_sz );
|
||||
}
|
||||
|
||||
@@ -1,175 +0,0 @@
|
||||
//
|
||||
// Created by stephane bourque on 2021-11-23.
|
||||
//
|
||||
|
||||
#include "RTTYS_ClientConnection.h"
|
||||
#include "rttys/RTTYS_device.h"
|
||||
#include "rttys/RTTYS_server.h"
|
||||
|
||||
#include "fmt/format.h"
|
||||
|
||||
#include "nlohmann/json.hpp"
|
||||
|
||||
namespace OpenWifi {
|
||||
|
||||
RTTYS_ClientConnection::RTTYS_ClientConnection(
|
||||
Poco::Net::HTTPServerRequest &request,
|
||||
Poco::Net::HTTPServerResponse &response,
|
||||
Poco::Net::SocketReactor &reactor,
|
||||
const std::string &Id)
|
||||
:
|
||||
Reactor_(reactor),
|
||||
Id_(Id),
|
||||
Logger_(Poco::Logger::get(fmt::format("RTTY-client({})",Id_)))
|
||||
{
|
||||
Valid_ = true;
|
||||
WS_ = std::make_unique<Poco::Net::WebSocket>(request,response);
|
||||
WS_->setBlocking(false);
|
||||
WS_->setNoDelay(true);
|
||||
WS_->setKeepAlive(true);
|
||||
Registered_ = true;
|
||||
Reactor_.addEventHandler(
|
||||
*WS_, Poco::NObserver<RTTYS_ClientConnection, Poco::Net::ReadableNotification>(
|
||||
*this, &RTTYS_ClientConnection::onSocketReadable));
|
||||
Reactor_.addEventHandler(
|
||||
*WS_, Poco::NObserver<RTTYS_ClientConnection, Poco::Net::ShutdownNotification>(
|
||||
*this, &RTTYS_ClientConnection::onSocketShutdown));
|
||||
Logger_.information("Starting connection");
|
||||
}
|
||||
|
||||
RTTYS_ClientConnection::~RTTYS_ClientConnection() {
|
||||
poco_information(Logger_,
|
||||
fmt::format("Client {} session ending", Id_)
|
||||
);
|
||||
DeRegister();
|
||||
}
|
||||
|
||||
void RTTYS_ClientConnection::DeRegister() {
|
||||
Valid_ = false;
|
||||
if(Registered_) {
|
||||
Registered_ = false;
|
||||
Reactor_.removeEventHandler(
|
||||
*WS_, Poco::NObserver<RTTYS_ClientConnection, Poco::Net::ReadableNotification>(
|
||||
*this, &RTTYS_ClientConnection::onSocketReadable));
|
||||
Reactor_.removeEventHandler(
|
||||
*WS_, Poco::NObserver<RTTYS_ClientConnection, Poco::Net::ShutdownNotification>(
|
||||
*this, &RTTYS_ClientConnection::onSocketShutdown));
|
||||
}
|
||||
}
|
||||
|
||||
void RTTYS_ClientConnection::EndConnection() {
|
||||
DeRegister();
|
||||
RTTYS_server()->NotifyClientDisconnect(Id_, this);
|
||||
}
|
||||
|
||||
void RTTYS_ClientConnection::onSocketReadable([[maybe_unused]] const Poco::AutoPtr<Poco::Net::ReadableNotification> &pNf) {
|
||||
bool MustDisconnect = false;
|
||||
|
||||
{
|
||||
if(!Valid_ || !Registered_)
|
||||
return;
|
||||
std::lock_guard G(Mutex_);
|
||||
try {
|
||||
int flags;
|
||||
Poco::Buffer<char> IncomingFrame(0);
|
||||
auto n = WS_->receiveFrame(IncomingFrame, flags);
|
||||
auto Op = flags & Poco::Net::WebSocket::FRAME_OP_BITMASK;
|
||||
switch (Op) {
|
||||
case Poco::Net::WebSocket::FRAME_OP_PING: {
|
||||
WS_->sendFrame("", 0,
|
||||
(int)Poco::Net::WebSocket::FRAME_OP_PONG |
|
||||
(int)Poco::Net::WebSocket::FRAME_FLAG_FIN);
|
||||
} break;
|
||||
case Poco::Net::WebSocket::FRAME_OP_PONG: {
|
||||
} break;
|
||||
case Poco::Net::WebSocket::FRAME_OP_TEXT: {
|
||||
if (n == 0) {
|
||||
Logger_.information("Socket readable shutdown.");
|
||||
MustDisconnect = true;
|
||||
} else {
|
||||
std::string s((char *)IncomingFrame.begin(), IncomingFrame.size());
|
||||
try {
|
||||
auto Doc = nlohmann::json::parse(s);
|
||||
if (Doc.contains("type")) {
|
||||
auto Type = Doc["type"];
|
||||
if (Type == "winsize") {
|
||||
auto cols = Doc["cols"];
|
||||
auto rows = Doc["rows"];
|
||||
if (!RTTYS_server()->WindowSize(Id_, cols, rows)) {
|
||||
Logger_.information("Winsize shutdown.");
|
||||
MustDisconnect = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (...) {
|
||||
// just ignore parse errors
|
||||
Logger_.information("Frame text exception shutdown.");
|
||||
MustDisconnect = true;
|
||||
}
|
||||
}
|
||||
} break;
|
||||
case Poco::Net::WebSocket::FRAME_OP_BINARY: {
|
||||
if (n == 0) {
|
||||
Logger_.information("Frame binary size shutdown.");
|
||||
MustDisconnect = true;
|
||||
} else {
|
||||
poco_trace(Logger_, fmt::format("Sending {} key strokes to device.", n));
|
||||
if (!RTTYS_server()->SendKeyStrokes(
|
||||
Id_, (const unsigned char *)IncomingFrame.begin(),
|
||||
IncomingFrame.size())) {
|
||||
Logger_.information("Sendkeystrokes shutdown.");
|
||||
MustDisconnect = true;
|
||||
}
|
||||
}
|
||||
} break;
|
||||
case Poco::Net::WebSocket::FRAME_OP_CLOSE: {
|
||||
Logger_.information("Frame frame close shutdown.");
|
||||
MustDisconnect = true;
|
||||
} break;
|
||||
|
||||
default: {
|
||||
}
|
||||
}
|
||||
} catch (...) {
|
||||
Logger_.information("Frame readable shutdown.");
|
||||
MustDisconnect = true;
|
||||
}
|
||||
}
|
||||
|
||||
if(MustDisconnect) {
|
||||
EndConnection();
|
||||
}
|
||||
}
|
||||
|
||||
void RTTYS_ClientConnection::SendData( const u_char *Buf, size_t len ) {
|
||||
if(!Valid_ || !Registered_)
|
||||
return;
|
||||
try {
|
||||
WS_->sendFrame(Buf, len,
|
||||
Poco::Net::WebSocket::FRAME_FLAG_FIN |
|
||||
Poco::Net::WebSocket::FRAME_OP_BINARY);
|
||||
return;
|
||||
} catch (...) {
|
||||
Logger_.information("SendData shutdown.");
|
||||
}
|
||||
EndConnection();
|
||||
}
|
||||
|
||||
void RTTYS_ClientConnection::SendData( const std::string &s) {
|
||||
if(!Valid_ || !Registered_)
|
||||
return;
|
||||
try {
|
||||
WS_->sendFrame(s.c_str(), s.length());
|
||||
return;
|
||||
} catch (...) {
|
||||
Logger_.information("SendData shutdown.");
|
||||
}
|
||||
EndConnection();
|
||||
}
|
||||
|
||||
void RTTYS_ClientConnection::onSocketShutdown([[maybe_unused]] const Poco::AutoPtr<Poco::Net::ShutdownNotification> &pNf) {
|
||||
Logger_.information("Socket shutdown.");
|
||||
EndConnection();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,49 +0,0 @@
|
||||
//
|
||||
// Created by stephane bourque on 2021-11-23.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Poco/Net/WebSocket.h"
|
||||
#include "Poco/Net/SocketReactor.h"
|
||||
#include "Poco/NObserver.h"
|
||||
#include "Poco/Net/SocketNotification.h"
|
||||
#include "Poco/FIFOBuffer.h"
|
||||
#include "Poco/Logger.h"
|
||||
|
||||
#include <mutex>
|
||||
#include <shared_mutex>
|
||||
|
||||
namespace OpenWifi {
|
||||
|
||||
class RTTYS_ClientConnection {
|
||||
public:
|
||||
RTTYS_ClientConnection(Poco::Net::HTTPServerRequest &request,
|
||||
Poco::Net::HTTPServerResponse &response,
|
||||
Poco::Net::SocketReactor & reactor,
|
||||
const std::string &Id);
|
||||
~RTTYS_ClientConnection();
|
||||
void onSocketReadable(const Poco::AutoPtr<Poco::Net::ReadableNotification> &pNf);
|
||||
void onSocketShutdown(const Poco::AutoPtr<Poco::Net::ShutdownNotification> &pNf);
|
||||
|
||||
void SendData( const u_char *Buf, size_t len );
|
||||
void SendData( const std::string & S );
|
||||
void DeRegister();
|
||||
|
||||
[[nodiscard]] inline std::string ID() { return Id_; }
|
||||
[[nodiscard]] inline bool Valid() { return Valid_; }
|
||||
|
||||
private:
|
||||
Poco::Net::SocketReactor &Reactor_;
|
||||
std::string Id_;
|
||||
std::unique_ptr<Poco::Net::WebSocket> WS_;
|
||||
Poco::Logger &Logger_;
|
||||
std::string Sid_;
|
||||
std::recursive_mutex Mutex_;
|
||||
volatile bool Valid_=false;
|
||||
volatile bool Registered_=false;
|
||||
|
||||
void EndConnection();
|
||||
|
||||
};
|
||||
}
|
||||
@@ -7,9 +7,8 @@
|
||||
#include "Poco/Net/HTTPServerRequest.h"
|
||||
#include "Poco/Net/HTTPServerResponse.h"
|
||||
|
||||
#include "RTTYS_ClientConnection.h"
|
||||
#include "RTTYS_WebServer.h"
|
||||
#include "RTTYS_server.h"
|
||||
#include "RTTYS_WebServer.h"
|
||||
|
||||
#include "fmt/format.h"
|
||||
#include "nlohmann/json.hpp"
|
||||
@@ -37,7 +36,7 @@ namespace OpenWifi {
|
||||
}
|
||||
|
||||
try {
|
||||
RTTYS_server()->CreateNewClient(request,response,T[2]);
|
||||
RTTYS_server()->CreateWSClient(request,response,T[2]);
|
||||
} catch (...) {
|
||||
poco_warning(Logger_,"Exception during WS creation");
|
||||
}
|
||||
@@ -113,7 +112,7 @@ namespace OpenWifi {
|
||||
Utils::SetThreadName("rt:webserver");
|
||||
[[maybe_unused]] uint64_t id = rtty_ws_id++;
|
||||
|
||||
poco_debug(Logger(),fmt::format("{}: Starting request.",id));
|
||||
poco_trace(Logger(),fmt::format("{}: Starting request.",id));
|
||||
Poco::URI uri(request.getURI());
|
||||
auto Path = uri.getPath();
|
||||
|
||||
@@ -135,7 +134,7 @@ namespace OpenWifi {
|
||||
if (ParsedPath.count() > 1) {
|
||||
if (ParsedPath[1] == "connect") {
|
||||
response.redirect(Poco::replace(Path,"/connect/","/rtty/"));
|
||||
poco_debug(Logger(),fmt::format("{}: Redirect: {}",id,Path));
|
||||
poco_trace(Logger(),fmt::format("{}: Redirect: {}",id,Path));
|
||||
return;
|
||||
} else if (ParsedPath[1] == "authorized") {
|
||||
SetCommonHeaders(request,response, false);
|
||||
@@ -144,7 +143,7 @@ namespace OpenWifi {
|
||||
response.setContentType("application/json");
|
||||
std::ostream &answer = response.send();
|
||||
answer << to_string(doc);
|
||||
poco_debug(Logger(),fmt::format("{}: Finishing authorization request.",id));
|
||||
poco_trace(Logger(),fmt::format("{}: Finishing authorization request.",id));
|
||||
return;
|
||||
} else if (ParsedPath[1] == "fontsize") {
|
||||
SetCommonHeaders(request,response, false);
|
||||
@@ -153,7 +152,7 @@ namespace OpenWifi {
|
||||
response.setContentType("application/json");
|
||||
std::ostream &answer = response.send();
|
||||
answer << to_string(doc);
|
||||
poco_debug(Logger(),fmt::format("{}: Finishing font size request.",id));
|
||||
poco_trace(Logger(),fmt::format("{}: Finishing font size request.",id));
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -161,12 +160,12 @@ namespace OpenWifi {
|
||||
}
|
||||
|
||||
if(Path.find("../")!=std::string::npos) {
|
||||
poco_debug(Logger(),fmt::format("{}: Finishing request.",id));
|
||||
poco_trace(Logger(),fmt::format("{}: Finishing request.",id));
|
||||
return;
|
||||
}
|
||||
|
||||
if(Path.find("~/")!=std::string::npos) {
|
||||
poco_debug(Logger(),fmt::format("{}: Finishing request.",id));
|
||||
poco_trace(Logger(),fmt::format("{}: Finishing request.",id));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -176,7 +175,7 @@ namespace OpenWifi {
|
||||
// std::cout << id << ": Path " << Path << " does not exist" << std::endl;
|
||||
Path = RTTYS_server()->UIAssets() + "/index.html";
|
||||
response.sendFile(Path,"text/html");
|
||||
poco_debug(Logger(),fmt::format("{}: Finishing request.",id));
|
||||
poco_trace(Logger(),fmt::format("{}: Finishing request.",id));
|
||||
return;
|
||||
}
|
||||
Poco::Path P(Path);
|
||||
@@ -193,7 +192,7 @@ namespace OpenWifi {
|
||||
} else if (Ext == "css") {
|
||||
Type = "text/css; charset=utf-8";
|
||||
if(IsFileGZipped(Path)) {
|
||||
poco_debug(Logger(),fmt::format("{}: Downloading UI Assets.",id));
|
||||
poco_trace(Logger(),fmt::format("{}: Downloading UI Assets.",id));
|
||||
response.set("Content-Encoding", "gzip");
|
||||
}
|
||||
} else if (Ext == "ico")
|
||||
@@ -207,7 +206,7 @@ namespace OpenWifi {
|
||||
|
||||
response.setContentLength(F.getSize());
|
||||
response.sendFile(Path, Type);
|
||||
poco_debug(Logger(),fmt::format("{}: Finishing request.",id));
|
||||
poco_trace(Logger(),fmt::format("{}: Finishing request.",id));
|
||||
}
|
||||
|
||||
RTTYS_Client_RequestHandlerFactory::RTTYS_Client_RequestHandlerFactory(Poco::Logger & L)
|
||||
|
||||
@@ -1,524 +0,0 @@
|
||||
//
|
||||
// Created by stephane bourque on 2021-11-23.
|
||||
//
|
||||
|
||||
#include "RTTYS_device.h"
|
||||
#include "rttys/RTTYS_server.h"
|
||||
#include "Poco/Net/SecureStreamSocketImpl.h"
|
||||
#include "Poco/Net/StreamSocket.h"
|
||||
|
||||
#include "nlohmann/json.hpp"
|
||||
#include "fmt/format.h"
|
||||
|
||||
void dump(const u_char *b, uint s) {
|
||||
static const char hex[] = "0123456789abcdef";
|
||||
|
||||
int l=0;
|
||||
std::cout << std::endl;
|
||||
while(s) {
|
||||
std::string SS;
|
||||
SS += (hex[(*b & 0xf0) >> 4]);
|
||||
SS += (hex[(*b & 0x0f)]);
|
||||
std::cout << SS << " ";
|
||||
l++;
|
||||
if((l % 16) == 0)
|
||||
std::cout << std::endl;
|
||||
b++;
|
||||
--s;
|
||||
}
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
|
||||
#define SOCKET_DEBUG(X,Y,Z) { std::cout << __func__ << ":" << __LINE__ << std::endl; (Z)=socket_.sendBytes(X,Y); dump(X,Y); }
|
||||
|
||||
namespace OpenWifi {
|
||||
|
||||
RTTYS_Device_ConnectionHandler::RTTYS_Device_ConnectionHandler(Poco::Net::StreamSocket& socket, Poco::Net::SocketReactor & reactor):
|
||||
socket_(socket),
|
||||
reactor_(reactor),
|
||||
Logger_(Poco::Logger::get(fmt::format("RTTY-device({})",socket_.peerAddress().toString())))
|
||||
{
|
||||
// std::thread T([=]() { CompleteConnection(); });
|
||||
// T.detach();
|
||||
inBuf_ = std::make_unique<Poco::FIFOBuffer>(RTTY_DEVICE_BUFSIZE);
|
||||
CompleteConnection();
|
||||
}
|
||||
|
||||
void RTTYS_Device_ConnectionHandler::CompleteConnection() {
|
||||
try {
|
||||
valid_=true;
|
||||
device_address_ = socket_.peerAddress();
|
||||
|
||||
auto SS = dynamic_cast<Poco::Net::SecureStreamSocketImpl *>(socket_.impl());
|
||||
while (true) {
|
||||
auto V = SS->completeHandshake();
|
||||
if (V == 1)
|
||||
break;
|
||||
}
|
||||
|
||||
if ((SS->secure())) {
|
||||
poco_information(Logger(), "Secure connection.");
|
||||
}
|
||||
|
||||
socket_.setBlocking(false);
|
||||
socket_.setKeepAlive(true);
|
||||
socket_.setNoDelay(true);
|
||||
socket_.setReceiveTimeout(Poco::Timespan(60*60,0));
|
||||
|
||||
registered_=true;
|
||||
reactor_.addEventHandler(
|
||||
socket_,
|
||||
Poco::NObserver<RTTYS_Device_ConnectionHandler, Poco::Net::ReadableNotification>(
|
||||
*this, &RTTYS_Device_ConnectionHandler::onSocketReadable));
|
||||
reactor_.addEventHandler(
|
||||
socket_,
|
||||
Poco::NObserver<RTTYS_Device_ConnectionHandler, Poco::Net::ShutdownNotification>(
|
||||
*this, &RTTYS_Device_ConnectionHandler::onSocketShutdown));
|
||||
} catch (...) {
|
||||
poco_warning(Logger(), "Device caused exception while completing connection.");
|
||||
std::unique_lock G(M_);
|
||||
EndConnection();
|
||||
}
|
||||
}
|
||||
|
||||
RTTYS_Device_ConnectionHandler::~RTTYS_Device_ConnectionHandler() {
|
||||
poco_information(Logger_,
|
||||
fmt::format("Device {} session ending", id_)
|
||||
);
|
||||
DeRegister();
|
||||
}
|
||||
|
||||
void RTTYS_Device_ConnectionHandler::DeRegister() {
|
||||
if(registered_) {
|
||||
registered_ = false;
|
||||
reactor_.removeEventHandler(
|
||||
socket_,
|
||||
Poco::NObserver<RTTYS_Device_ConnectionHandler, Poco::Net::ReadableNotification>(
|
||||
*this, &RTTYS_Device_ConnectionHandler::onSocketReadable));
|
||||
reactor_.removeEventHandler(
|
||||
socket_,
|
||||
Poco::NObserver<RTTYS_Device_ConnectionHandler, Poco::Net::ShutdownNotification>(
|
||||
*this, &RTTYS_Device_ConnectionHandler::onSocketShutdown));
|
||||
}
|
||||
}
|
||||
|
||||
void RTTYS_Device_ConnectionHandler::EndConnection() {
|
||||
if(valid_) {
|
||||
valid_ = false;
|
||||
DeRegister();
|
||||
if(deviceIsRegistered_) {
|
||||
deviceIsRegistered_ = false;
|
||||
RTTYS_server()->NotifyDeviceDisconnect(id_, this);
|
||||
} else {
|
||||
delete this;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[[maybe_unused]] static void dump(unsigned char *p,uint l) {
|
||||
for(uint i=0;i<l;i++) {
|
||||
std::cout << std::hex << (uint) p[i] << " ";
|
||||
if(i % 16 == 0)
|
||||
std::cout << std::endl;
|
||||
}
|
||||
std::cout << std::dec << std::endl ;
|
||||
}
|
||||
|
||||
void RTTYS_Device_ConnectionHandler::onSocketReadable([[maybe_unused]] const Poco::AutoPtr<Poco::Net::ReadableNotification> &pNf) {
|
||||
bool good = true;
|
||||
|
||||
if(!valid_ || !registered_)
|
||||
return;
|
||||
|
||||
std::unique_lock G(M_);
|
||||
try {
|
||||
auto received_bytes = socket_.receiveBytes(*inBuf_);
|
||||
if (received_bytes == 0) {
|
||||
poco_information(Logger(), fmt::format("{}: Device Closing connection - 0 bytes received.",id_));
|
||||
return EndConnection();
|
||||
}
|
||||
|
||||
while (inBuf_->isReadable() && good) {
|
||||
uint32_t msg_len = 0;
|
||||
if (waiting_for_bytes_ != 0) {
|
||||
|
||||
} else {
|
||||
if (inBuf_->used() >= RTTY_HDR_SIZE) {
|
||||
auto *head = (unsigned char *)inBuf_->begin();
|
||||
last_command_ = head[0];
|
||||
msg_len = head[1] * 256 + head[2];
|
||||
inBuf_->drain(RTTY_HDR_SIZE);
|
||||
} else {
|
||||
good = false;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
switch (last_command_) {
|
||||
case msgTypeRegister: {
|
||||
good = do_msgTypeRegister(msg_len);
|
||||
} break;
|
||||
case msgTypeLogin: {
|
||||
good = do_msgTypeLogin(msg_len);
|
||||
} break;
|
||||
case msgTypeLogout: {
|
||||
good = do_msgTypeLogout(msg_len);
|
||||
} break;
|
||||
case msgTypeTermData: {
|
||||
good = do_msgTypeTermData(msg_len);
|
||||
} break;
|
||||
case msgTypeWinsize: {
|
||||
good = do_msgTypeWinsize(msg_len);
|
||||
} break;
|
||||
case msgTypeCmd: {
|
||||
good = do_msgTypeCmd(msg_len);
|
||||
} break;
|
||||
case msgTypeHeartbeat: {
|
||||
good = do_msgTypeHeartbeat(msg_len);
|
||||
} break;
|
||||
case msgTypeFile: {
|
||||
good = do_msgTypeFile(msg_len);
|
||||
} break;
|
||||
case msgTypeHttp: {
|
||||
good = do_msgTypeHttp(msg_len);
|
||||
} break;
|
||||
case msgTypeAck: {
|
||||
good = do_msgTypeAck(msg_len);
|
||||
} break;
|
||||
case msgTypeMax: {
|
||||
good = do_msgTypeMax(msg_len);
|
||||
} break;
|
||||
default: {
|
||||
poco_warning(Logger(),
|
||||
fmt::format("{}: Unknown command {} from device. GW closing connection.", id_,
|
||||
(int)last_command_));
|
||||
good = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (const Poco::Exception &E) {
|
||||
good = false;
|
||||
poco_warning(Logger(),fmt::format("{}: Exception: {} GW closing connection.", id_, E.what()));
|
||||
} catch (const std::exception &E) {
|
||||
poco_warning(Logger(),fmt::format("{}: std::exception: {}. GW closing connection.", id_, E.what()));
|
||||
good = false;
|
||||
}
|
||||
|
||||
if(!good) {
|
||||
return EndConnection();
|
||||
}
|
||||
}
|
||||
|
||||
void RTTYS_Device_ConnectionHandler::onSocketShutdown([[maybe_unused]] const Poco::AutoPtr<Poco::Net::ShutdownNotification>& pNf) {
|
||||
poco_information(Logger(),fmt::format("{}: Connection being closed - socket shutdown.",id_));
|
||||
EndConnection();
|
||||
}
|
||||
|
||||
bool RTTYS_Device_ConnectionHandler::SendToClient(const u_char *Buf, int Len) {
|
||||
u_char bb[64000]{0};
|
||||
if(old_rtty_) {
|
||||
bb[0] = session_id_[0];
|
||||
memcpy(&bb[1],Buf,Len);
|
||||
} else {
|
||||
bb[0] = 0;
|
||||
memcpy(&bb[1],Buf,Len);
|
||||
}
|
||||
return RTTYS_server()->SendToClient(id_, Buf, Len );
|
||||
}
|
||||
|
||||
bool RTTYS_Device_ConnectionHandler::SendToClient(const std::string &S) {
|
||||
if(!valid_ || !registered_)
|
||||
return false;
|
||||
return RTTYS_server()->SendToClient(id_,S);
|
||||
}
|
||||
|
||||
bool RTTYS_Device_ConnectionHandler::KeyStrokes(const u_char *buf, size_t len) {
|
||||
if(!valid_ || !registered_)
|
||||
return false;
|
||||
|
||||
if(len<=(sizeof(small_buf_)-RTTY_HDR_SIZE-session_length_)) {
|
||||
small_buf_[0] = msgTypeTermData;
|
||||
small_buf_[1] = ((len-1+session_length_) & 0xff00) >> 8;
|
||||
small_buf_[2] = ((len-1+session_length_) & 0x00ff);
|
||||
memcpy(&small_buf_[RTTY_HDR_SIZE],session_id_,session_length_);
|
||||
memcpy(&small_buf_[RTTY_HDR_SIZE+session_length_], &buf[1], len-1);
|
||||
try {
|
||||
auto Sent = socket_.sendBytes(small_buf_, RTTY_HDR_SIZE + session_length_ + len - 1);
|
||||
return (Sent==(int)(RTTY_HDR_SIZE + session_length_ + len - 1));
|
||||
} catch (...) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
auto Msg = std::make_unique<unsigned char []>(len + RTTY_HDR_SIZE + session_length_);
|
||||
Msg.get()[0] = msgTypeTermData;
|
||||
Msg.get()[1] = ((len-1+session_length_) & 0xff00) >> 8;
|
||||
Msg.get()[2] = ((len-1+session_length_) & 0x00ff);
|
||||
memcpy((Msg.get()+RTTY_HDR_SIZE),session_id_,session_length_);
|
||||
memcpy((Msg.get()+RTTY_HDR_SIZE+session_length_), &buf[1], len-1);
|
||||
try {
|
||||
auto Sent = socket_.sendBytes(Msg.get(), RTTY_HDR_SIZE + session_length_ + len - 1);
|
||||
return (Sent==(int)( RTTY_HDR_SIZE + session_length_ + len - 1));
|
||||
} catch (...) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool RTTYS_Device_ConnectionHandler::WindowSize(int cols, int rows) {
|
||||
if(!valid_ || !registered_)
|
||||
return false;
|
||||
|
||||
u_char outBuf[8+RTTY_SESSION_ID_LENGTH]{0};
|
||||
outBuf[0] = msgTypeWinsize;
|
||||
outBuf[1] = 0 ;
|
||||
outBuf[2] = 4 + session_length_ ;
|
||||
memcpy(&outBuf[RTTY_HDR_SIZE],session_id_,session_length_);
|
||||
outBuf[RTTY_HDR_SIZE+0+session_length_] = cols >> 8 ;
|
||||
outBuf[RTTY_HDR_SIZE+1+session_length_] = cols & 0x00ff;
|
||||
outBuf[RTTY_HDR_SIZE+2+session_length_] = rows >> 8;
|
||||
outBuf[RTTY_HDR_SIZE+3+session_length_] = rows & 0x00ff;
|
||||
try {
|
||||
auto Sent = socket_.sendBytes(outBuf, RTTY_HDR_SIZE + 4 + session_length_ );
|
||||
return (Sent==(int)(RTTY_HDR_SIZE + 4 + session_length_));
|
||||
} catch (...) {
|
||||
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool RTTYS_Device_ConnectionHandler::Login() {
|
||||
if(!valid_ || !registered_)
|
||||
return false;
|
||||
|
||||
u_char outBuf[RTTY_HDR_SIZE+RTTY_SESSION_ID_LENGTH]{0};
|
||||
outBuf[0] = msgTypeLogin;
|
||||
outBuf[1] = 0;
|
||||
if(old_rtty_) {
|
||||
outBuf[2] = 0;
|
||||
} else {
|
||||
outBuf[2] = RTTY_SESSION_ID_LENGTH;
|
||||
std::strncpy(session_id_,Utils::ComputeHash(id_,token_).substr(0,RTTY_SESSION_ID_LENGTH/2).c_str(),RTTY_SESSION_ID_LENGTH);
|
||||
memcpy(&outBuf[RTTY_HDR_SIZE],session_id_,RTTY_SESSION_ID_LENGTH);
|
||||
}
|
||||
try {
|
||||
poco_information(Logger(),fmt::format("{}: Device login", id_));
|
||||
auto Sent = socket_.sendBytes( outBuf, RTTY_HDR_SIZE + (old_rtty_ ? 0 : RTTY_SESSION_ID_LENGTH));
|
||||
return Sent==(int)(RTTY_HDR_SIZE + (old_rtty_ ? 0 : RTTY_SESSION_ID_LENGTH));
|
||||
} catch (const Poco::IOException &E) {
|
||||
return false;
|
||||
} catch (const Poco::Exception &E) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool RTTYS_Device_ConnectionHandler::Logout() {
|
||||
if(!valid_ || !registered_)
|
||||
return false;
|
||||
|
||||
u_char outBuf[4+RTTY_SESSION_ID_LENGTH]{0};
|
||||
outBuf[0] = msgTypeLogout;
|
||||
outBuf[1] = 0;
|
||||
outBuf[2] = session_length_;
|
||||
memcpy(&outBuf[3],session_id_,session_length_);
|
||||
poco_information(Logger(),fmt::format("{}: Logout", id_));
|
||||
try {
|
||||
auto Sent = socket_.sendBytes(outBuf, RTTY_HDR_SIZE + session_length_);
|
||||
return Sent==(int)(RTTY_HDR_SIZE+session_length_);
|
||||
} catch (...) {
|
||||
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string RTTYS_Device_ConnectionHandler::ReadString() {
|
||||
std::string Res;
|
||||
|
||||
while(inBuf_->used()) {
|
||||
char C;
|
||||
inBuf_->read(&C,1);
|
||||
if(C==0) {
|
||||
break;
|
||||
}
|
||||
Res += C;
|
||||
}
|
||||
|
||||
return Res;
|
||||
}
|
||||
|
||||
bool RTTYS_Device_ConnectionHandler::do_msgTypeRegister([[maybe_unused]] std::size_t msg_len) {
|
||||
bool good = true;
|
||||
|
||||
if(deviceIsRegistered_)
|
||||
return false;
|
||||
|
||||
try {
|
||||
// establish if this is an old rtty or a new one.
|
||||
old_rtty_ = ((*inBuf_)[0] != 0x03); // rtty_proto_ver for full session ID inclusion
|
||||
if(old_rtty_) {
|
||||
session_length_ = 1;
|
||||
} else {
|
||||
inBuf_->drain(1); // remove protocol if used.
|
||||
session_length_ = RTTY_SESSION_ID_LENGTH;
|
||||
}
|
||||
|
||||
id_ = ReadString();
|
||||
desc_ = ReadString();
|
||||
token_ = ReadString();
|
||||
|
||||
if(id_.size()!=RTTY_DEVICE_TOKEN_LENGTH || token_.size()!=RTTY_DEVICE_TOKEN_LENGTH || desc_.empty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
poco_information(Logger(),
|
||||
fmt::format("{}: Description:{} Device registration", id_, desc_));
|
||||
if(!RTTYS_server()->NotifyDeviceRegistration(id_,token_,this)) {
|
||||
return false;
|
||||
}
|
||||
u_char OutBuf[8];
|
||||
OutBuf[0] = msgTypeRegister;
|
||||
OutBuf[1] = 0; // Data length
|
||||
OutBuf[2] = 4; //
|
||||
OutBuf[3] = 0; // Error
|
||||
OutBuf[4] = 'O';
|
||||
OutBuf[5] = 'K';
|
||||
OutBuf[6] = 0;
|
||||
if (socket_.sendBytes(OutBuf, 7) != 7) {
|
||||
poco_information(Logger(),
|
||||
fmt::format("{}: Description:{} Could not send data to complete registration",
|
||||
id_, desc_));
|
||||
good = false;
|
||||
}
|
||||
deviceIsRegistered_ = true;
|
||||
} catch (...) {
|
||||
good = false;
|
||||
}
|
||||
return good;
|
||||
}
|
||||
|
||||
bool RTTYS_Device_ConnectionHandler::do_msgTypeLogin([[maybe_unused]] std::size_t msg_len) {
|
||||
poco_information(Logger(),fmt::format("{}: Asking for login", id_));
|
||||
|
||||
if(!deviceIsRegistered_)
|
||||
return false;
|
||||
|
||||
nlohmann::json doc;
|
||||
char Error;
|
||||
if(old_rtty_) {
|
||||
inBuf_->read(&Error, 1);
|
||||
inBuf_->read(&session_id_[0], session_length_);
|
||||
} else {
|
||||
char session[RTTY_SESSION_ID_LENGTH+1]{0};
|
||||
inBuf_->read(&session[0], session_length_);
|
||||
inBuf_->read(&Error, 1);
|
||||
}
|
||||
doc["type"] = "login";
|
||||
doc["err"] = Error;
|
||||
const auto login_msg = to_string(doc);
|
||||
return SendToClient(login_msg);
|
||||
}
|
||||
|
||||
bool RTTYS_Device_ConnectionHandler::do_msgTypeLogout([[maybe_unused]] std::size_t msg_len) {
|
||||
if(!deviceIsRegistered_)
|
||||
return false;
|
||||
|
||||
char session[RTTY_SESSION_ID_LENGTH];
|
||||
if(old_rtty_) {
|
||||
inBuf_->read(&session[0],1);
|
||||
} else {
|
||||
inBuf_->read(&session[0],RTTY_SESSION_ID_LENGTH);
|
||||
}
|
||||
poco_information(Logger(),fmt::format("{}: Logout", id_));
|
||||
return false;
|
||||
}
|
||||
|
||||
bool RTTYS_Device_ConnectionHandler::do_msgTypeTermData(std::size_t msg_len) {
|
||||
|
||||
if(!deviceIsRegistered_)
|
||||
return false;
|
||||
|
||||
bool good;
|
||||
if(waiting_for_bytes_>0) {
|
||||
if(inBuf_->used()<waiting_for_bytes_) {
|
||||
waiting_for_bytes_ = waiting_for_bytes_ - inBuf_->used();
|
||||
good = SendToClient((unsigned char *)inBuf_->begin(), (int) inBuf_->used());
|
||||
inBuf_->drain();
|
||||
} else {
|
||||
good = SendToClient((unsigned char *)inBuf_->begin(), waiting_for_bytes_);
|
||||
inBuf_->drain(waiting_for_bytes_);
|
||||
waiting_for_bytes_ = 0 ;
|
||||
}
|
||||
} else {
|
||||
if(old_rtty_) {
|
||||
inBuf_->drain(1);
|
||||
msg_len -= 1;
|
||||
} else {
|
||||
inBuf_->drain(RTTY_SESSION_ID_LENGTH);
|
||||
msg_len -= RTTY_SESSION_ID_LENGTH;
|
||||
}
|
||||
if(inBuf_->used()<msg_len) {
|
||||
good = SendToClient((unsigned char *)inBuf_->begin(), inBuf_->used());
|
||||
waiting_for_bytes_ = msg_len - inBuf_->used();
|
||||
inBuf_->drain();
|
||||
} else {
|
||||
waiting_for_bytes_ = 0 ;
|
||||
good = SendToClient((unsigned char *)inBuf_->begin(), msg_len);
|
||||
inBuf_->drain(msg_len);
|
||||
}
|
||||
}
|
||||
return good;
|
||||
}
|
||||
|
||||
bool RTTYS_Device_ConnectionHandler::do_msgTypeWinsize([[maybe_unused]] std::size_t msg_len) {
|
||||
if(!deviceIsRegistered_)
|
||||
return false;
|
||||
poco_information(Logger(),fmt::format("{}: Asking for msgTypeWinsize", id_));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RTTYS_Device_ConnectionHandler::do_msgTypeCmd([[maybe_unused]] std::size_t msg_len) {
|
||||
if(!deviceIsRegistered_)
|
||||
return false;
|
||||
poco_information(Logger(),fmt::format("{}: Asking for msgTypeCmd", id_));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RTTYS_Device_ConnectionHandler::do_msgTypeHeartbeat([[maybe_unused]] std::size_t msg_len) {
|
||||
if(!deviceIsRegistered_)
|
||||
return false;
|
||||
u_char MsgBuf[RTTY_HDR_SIZE + 16]{0};
|
||||
if(msg_len)
|
||||
inBuf_->drain(msg_len);
|
||||
MsgBuf[0] = msgTypeHeartbeat;
|
||||
MsgBuf[1] = 0;
|
||||
MsgBuf[2] = 0;
|
||||
auto Sent = socket_.sendBytes(MsgBuf, RTTY_HDR_SIZE);
|
||||
return Sent == RTTY_HDR_SIZE;
|
||||
}
|
||||
|
||||
bool RTTYS_Device_ConnectionHandler::do_msgTypeFile([[maybe_unused]] std::size_t msg_len) {
|
||||
if(!deviceIsRegistered_)
|
||||
return false;
|
||||
poco_information(Logger(),fmt::format("{}: Asking for msgTypeFile", id_));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RTTYS_Device_ConnectionHandler::do_msgTypeHttp([[maybe_unused]] std::size_t msg_len) {
|
||||
if(!deviceIsRegistered_)
|
||||
return false;
|
||||
poco_information(Logger(),fmt::format("{}: Asking for msgTypeHttp", id_));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RTTYS_Device_ConnectionHandler::do_msgTypeAck([[maybe_unused]] std::size_t msg_len) {
|
||||
if(!deviceIsRegistered_)
|
||||
return false;
|
||||
poco_information(Logger(),fmt::format("{}: Asking for msgTypeAck", id_));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RTTYS_Device_ConnectionHandler::do_msgTypeMax([[maybe_unused]] std::size_t msg_len) {
|
||||
poco_information(Logger(),fmt::format("{}: Asking for msgTypeMax", id_));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -1,93 +0,0 @@
|
||||
//
|
||||
// Created by stephane bourque on 2021-11-23.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <array>
|
||||
#include <shared_mutex>
|
||||
|
||||
#include "Poco/Net/SocketReactor.h"
|
||||
#include "Poco/Net/SocketNotification.h"
|
||||
#include "Poco/FIFOBuffer.h"
|
||||
#include "Poco/Net/TCPServerConnectionFactory.h"
|
||||
#include "Poco/Logger.h"
|
||||
|
||||
namespace OpenWifi {
|
||||
|
||||
constexpr std::size_t RTTY_DEVICE_BUFSIZE=64000;
|
||||
constexpr std::size_t RTTY_SESSION_ID_LENGTH=32;
|
||||
constexpr std::size_t RTTY_HDR_SIZE=3;
|
||||
|
||||
class RTTYS_Device_ConnectionHandler{
|
||||
public:
|
||||
enum RTTY_MSG_TYPE {
|
||||
msgTypeRegister = 0,
|
||||
msgTypeLogin,
|
||||
msgTypeLogout,
|
||||
msgTypeTermData,
|
||||
msgTypeWinsize,
|
||||
msgTypeCmd,
|
||||
msgTypeHeartbeat,
|
||||
msgTypeFile,
|
||||
msgTypeHttp,
|
||||
msgTypeAck,
|
||||
msgTypeMax };
|
||||
|
||||
explicit RTTYS_Device_ConnectionHandler(Poco::Net::StreamSocket& socket, Poco::Net::SocketReactor& reactor);
|
||||
~RTTYS_Device_ConnectionHandler();
|
||||
|
||||
bool Login();
|
||||
bool Logout();
|
||||
|
||||
[[nodiscard]] bool SendToClient(const u_char *buf, int len);
|
||||
[[nodiscard]] bool SendToClient(const std::string &S);
|
||||
[[nodiscard]] bool WindowSize(int cols, int rows);
|
||||
[[nodiscard]] bool KeyStrokes(const u_char *buf, size_t len);
|
||||
std::string ReadString();
|
||||
// inline auto SessionID() const { return conn_id_; }
|
||||
|
||||
void onSocketReadable(const Poco::AutoPtr<Poco::Net::ReadableNotification>& pNf);
|
||||
void onSocketShutdown(const Poco::AutoPtr<Poco::Net::ShutdownNotification>& pNf);
|
||||
|
||||
inline Poco::Logger &Logger() { return Logger_; }
|
||||
inline bool Valid() const { return valid_; }
|
||||
|
||||
private:
|
||||
Poco::Net::StreamSocket socket_;
|
||||
Poco::Net::SocketReactor &reactor_;
|
||||
std::unique_ptr<Poco::FIFOBuffer> inBuf_;
|
||||
Poco::Logger &Logger_;
|
||||
|
||||
volatile bool valid_=false;
|
||||
volatile bool old_rtty_=true;
|
||||
Poco::Net::SocketAddress device_address_;
|
||||
std::shared_mutex M_;
|
||||
std::string id_;
|
||||
std::string token_;
|
||||
std::string desc_;
|
||||
char session_id_[RTTY_SESSION_ID_LENGTH+1]{0};
|
||||
std::uint64_t session_length_=1;
|
||||
std::size_t waiting_for_bytes_{0};
|
||||
u_char last_command_=0;
|
||||
volatile bool registered_=false;
|
||||
unsigned char small_buf_[64+RTTY_SESSION_ID_LENGTH];
|
||||
volatile bool deviceIsRegistered_=false;
|
||||
|
||||
void EndConnection() ;
|
||||
void CompleteConnection();
|
||||
void DeRegister();
|
||||
|
||||
[[nodiscard]] bool do_msgTypeRegister(std::size_t msg_len);
|
||||
[[nodiscard]] bool do_msgTypeLogin(std::size_t msg_len);
|
||||
[[nodiscard]] bool do_msgTypeLogout(std::size_t msg_len);
|
||||
[[nodiscard]] bool do_msgTypeTermData(std::size_t msg_len);
|
||||
[[nodiscard]] bool do_msgTypeWinsize(std::size_t msg_len);
|
||||
[[nodiscard]] bool do_msgTypeCmd(std::size_t msg_len);
|
||||
[[nodiscard]] bool do_msgTypeHeartbeat(std::size_t msg_len);
|
||||
[[nodiscard]] bool do_msgTypeFile(std::size_t msg_len);
|
||||
[[nodiscard]] bool do_msgTypeHttp(std::size_t msg_len);
|
||||
[[nodiscard]] bool do_msgTypeAck(std::size_t msg_len);
|
||||
[[nodiscard]] bool do_msgTypeMax(std::size_t msg_len);
|
||||
};
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -12,119 +12,45 @@
|
||||
#include "Poco/NotificationQueue.h"
|
||||
#include "Poco/Timer.h"
|
||||
#include "Poco/Net/HTTPServer.h"
|
||||
#include "Poco/Net/WebSocket.h"
|
||||
|
||||
#include "framework/SubSystemServer.h"
|
||||
#include "framework/utils.h"
|
||||
|
||||
#include "rttys/RTTYS_device.h"
|
||||
#include "rttys/RTTYS_ClientConnection.h"
|
||||
#include <fmt/format.h>
|
||||
|
||||
using namespace std::chrono_literals;
|
||||
|
||||
namespace OpenWifi {
|
||||
|
||||
constexpr uint RTTY_DEVICE_TOKEN_LENGTH=32;
|
||||
constexpr std::size_t RTTY_DEVICE_BUFSIZE=64000;
|
||||
constexpr std::size_t RTTY_SESSION_ID_LENGTH=32;
|
||||
constexpr std::size_t RTTY_HDR_SIZE=3;
|
||||
|
||||
class RTTYS_Device_ConnectionHandler;
|
||||
class RTTYS_ClientConnection;
|
||||
class RTTYS_server;
|
||||
|
||||
template <typename T> class MutexLockerDbg {
|
||||
public:
|
||||
MutexLockerDbg(const std::string &name, T &L) :
|
||||
name_(name),
|
||||
L_(L)
|
||||
{
|
||||
std::cout << name_ << ":L:0:" << Poco::Thread::current()->name() << ":" << Poco::Thread::currentTid() << std::endl;
|
||||
L_.lock();
|
||||
std::cout << name_ << ":L:1:" << Poco::Thread::current()->name() << ":" << Poco::Thread::currentTid() << std::endl;
|
||||
}
|
||||
|
||||
~MutexLockerDbg() {
|
||||
std::cout << name_ << ":U:0:" << Poco::Thread::current()->name() << ":" << Poco::Thread::currentTid() << std::endl;
|
||||
L_.unlock();
|
||||
std::cout << name_ << ":U:1:" << Poco::Thread::current()->name() << ":" << Poco::Thread::currentTid() << std::endl;
|
||||
}
|
||||
|
||||
private:
|
||||
std::string name_;
|
||||
T & L_;
|
||||
};
|
||||
|
||||
enum class RTTYS_Notification_type {
|
||||
unknown,
|
||||
device_disconnection,
|
||||
client_disconnection,
|
||||
client_registration,
|
||||
device_registration
|
||||
};
|
||||
|
||||
class RTTYS_Notification: public Poco::Notification {
|
||||
public:
|
||||
RTTYS_Notification(const RTTYS_Notification_type &type, const std::string &id,
|
||||
RTTYS_Device_ConnectionHandler * device) :
|
||||
type_(type),
|
||||
id_(id),
|
||||
device_(device) {
|
||||
}
|
||||
|
||||
RTTYS_Notification(const RTTYS_Notification_type &type, const std::string &id,
|
||||
RTTYS_ClientConnection * client) :
|
||||
type_(type),
|
||||
id_(id),
|
||||
client_(client) {
|
||||
}
|
||||
|
||||
RTTYS_Notification(const RTTYS_Notification_type &type,
|
||||
const std::string &id,
|
||||
const std::string &token,
|
||||
RTTYS_Device_ConnectionHandler * device) :
|
||||
type_(type),
|
||||
id_(id),
|
||||
token_(token),
|
||||
device_(device) {
|
||||
}
|
||||
|
||||
RTTYS_Notification_type type_=RTTYS_Notification_type::unknown;
|
||||
std::string id_;
|
||||
std::string token_;
|
||||
RTTYS_Device_ConnectionHandler *device_= nullptr;
|
||||
RTTYS_ClientConnection *client_ = nullptr;
|
||||
};
|
||||
class RTTYS_server * RTTYS_server();
|
||||
|
||||
class RTTYS_EndPoint {
|
||||
public:
|
||||
RTTYS_EndPoint(const std::string &Token, const std::string &SerialNumber, const std::string &UserName ):
|
||||
Token_(Token),
|
||||
SerialNumber_(SerialNumber),
|
||||
UserName_(UserName)
|
||||
{
|
||||
Created_ = std::chrono::high_resolution_clock::now();
|
||||
}
|
||||
RTTYS_EndPoint(const std::string &Id, const std::string &Token, const std::string &SerialNumber, const std::string &UserName );
|
||||
~RTTYS_EndPoint();
|
||||
|
||||
inline void SetClient(RTTYS_ClientConnection *Client) {
|
||||
ClientConnected_ = std::chrono::high_resolution_clock::now();
|
||||
Client_ = std::unique_ptr<RTTYS_ClientConnection>(Client);
|
||||
}
|
||||
enum RTTY_MSG_TYPE {
|
||||
msgTypeRegister = 0,
|
||||
msgTypeLogin,
|
||||
msgTypeLogout,
|
||||
msgTypeTermData,
|
||||
msgTypeWinsize,
|
||||
msgTypeCmd,
|
||||
msgTypeHeartbeat,
|
||||
msgTypeFile,
|
||||
msgTypeHttp,
|
||||
msgTypeAck,
|
||||
msgTypeMax };
|
||||
|
||||
inline void SetDevice(RTTYS_Device_ConnectionHandler* Device) {
|
||||
DeviceConnected_ = std::chrono::high_resolution_clock::now();
|
||||
Device_ = std::unique_ptr<RTTYS_Device_ConnectionHandler>(Device);
|
||||
}
|
||||
|
||||
inline bool Login() {
|
||||
if(Device_!= nullptr) {
|
||||
return Device_->Login();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
inline void DisconnectClient() {
|
||||
ClientDisconnected_ = std::chrono::high_resolution_clock::now();
|
||||
}
|
||||
|
||||
inline void DisconnectDevice() {
|
||||
DeviceDisconnected_ = std::chrono::high_resolution_clock::now();
|
||||
}
|
||||
bool Login();
|
||||
bool Logout();
|
||||
|
||||
[[nodiscard]] inline bool TooOld() {
|
||||
std::chrono::time_point<std::chrono::high_resolution_clock> now = std::chrono::high_resolution_clock::now();
|
||||
@@ -141,51 +67,6 @@ namespace OpenWifi {
|
||||
return true;
|
||||
}
|
||||
|
||||
if(!Joined_ && (now-Created_)>30s) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool SendToClient(const u_char *Buf, std::size_t Len) {
|
||||
if(Client_!= nullptr && Client_->Valid()) {
|
||||
Client_->SendData(Buf,Len);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
inline bool KeyStrokes(const u_char *buffer, std::size_t len) {
|
||||
if( Device_!= nullptr && Device_->Valid() )
|
||||
return Device_->KeyStrokes(buffer,len);
|
||||
return false;
|
||||
}
|
||||
|
||||
inline bool WindowSize( int cols, int rows) {
|
||||
if(Device_!= nullptr && Device_->Valid())
|
||||
return Device_->WindowSize(cols,rows);
|
||||
return false;
|
||||
}
|
||||
|
||||
[[nodiscard]] inline bool ValidClient() const {
|
||||
return Client_!= nullptr && Client_->Valid();
|
||||
}
|
||||
|
||||
[[nodiscard]] inline bool ValidDevice() const {
|
||||
return Device_!= nullptr && Device_->Valid();
|
||||
}
|
||||
|
||||
[[nodiscard]] inline bool Joined() volatile const { return Joined_; }
|
||||
void Join() {
|
||||
Joined_=true;
|
||||
}
|
||||
|
||||
inline bool SendToClient(const std::string &S) {
|
||||
if(Client_!= nullptr && Client_->Valid()) {
|
||||
Client_->SendData(S);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -205,20 +86,47 @@ namespace OpenWifi {
|
||||
return std::chrono::duration<double>{ClientDisconnected_ - ClientConnected_}.count();
|
||||
}
|
||||
|
||||
private:
|
||||
std::string Token_;
|
||||
std::string SerialNumber_;
|
||||
std::string UserName_;
|
||||
std::unique_ptr<RTTYS_ClientConnection> Client_;
|
||||
std::unique_ptr<RTTYS_Device_ConnectionHandler> Device_;
|
||||
std::string Id_;
|
||||
[[nodiscard]] bool do_msgTypeRegister(Poco::Net::Socket &Socket, Poco::Buffer<char> &B, [[maybe_unused]] std::size_t msg_len);
|
||||
[[nodiscard]] bool do_msgTypeLogin(std::size_t msg_len);
|
||||
[[nodiscard]] bool do_msgTypeLogout(std::size_t msg_len);
|
||||
[[nodiscard]] bool do_msgTypeTermData(std::size_t msg_len);
|
||||
[[nodiscard]] bool do_msgTypeWinsize(std::size_t msg_len);
|
||||
[[nodiscard]] bool do_msgTypeCmd(std::size_t msg_len);
|
||||
[[nodiscard]] bool do_msgTypeHeartbeat(std::size_t msg_len);
|
||||
[[nodiscard]] bool do_msgTypeFile(std::size_t msg_len);
|
||||
[[nodiscard]] bool do_msgTypeHttp(std::size_t msg_len);
|
||||
[[nodiscard]] bool do_msgTypeAck(std::size_t msg_len);
|
||||
[[nodiscard]] bool do_msgTypeMax(std::size_t msg_len);
|
||||
bool SendToClient(const u_char *buf, int len);
|
||||
bool SendToClient(const std::string &S);
|
||||
[[nodiscard]] bool WindowSize(int cols, int rows);
|
||||
[[nodiscard]] bool KeyStrokes(const u_char *buf, size_t len);
|
||||
|
||||
inline Poco::Logger & Logger() { return Logger_; }
|
||||
Poco::Net::SocketAddress device_address_;
|
||||
std::string Id_;
|
||||
std::string Token_;
|
||||
std::string SerialNumber_;
|
||||
std::string UserName_;
|
||||
std::unique_ptr<Poco::Net::StreamSocket> DeviceSocket_;
|
||||
std::unique_ptr<Poco::Net::WebSocket> WSSocket_;
|
||||
Poco::Logger &Logger_;
|
||||
std::unique_ptr<Poco::FIFOBuffer> DeviceInBuf_;
|
||||
char session_id_[RTTY_SESSION_ID_LENGTH+1]{0};
|
||||
std::uint64_t session_length_=1;
|
||||
std::size_t waiting_for_bytes_{0};
|
||||
u_char last_command_=0;
|
||||
unsigned char small_buf_[64+RTTY_SESSION_ID_LENGTH];
|
||||
std::uint64_t TID_=0;
|
||||
bool old_rtty_=false;
|
||||
bool completed_=false;
|
||||
|
||||
std::chrono::time_point<std::chrono::high_resolution_clock>
|
||||
Created_{0s},DeviceDisconnected_{0s},
|
||||
ClientDisconnected_{0s},DeviceConnected_{0s} ,ClientConnected_{0s};
|
||||
volatile bool Joined_=false;
|
||||
};
|
||||
|
||||
class RTTYS_server : public SubSystemServer, Poco::Runnable
|
||||
class RTTYS_server : public SubSystemServer
|
||||
{
|
||||
public:
|
||||
static auto instance() {
|
||||
@@ -232,77 +140,97 @@ namespace OpenWifi {
|
||||
inline auto UIAssets() { return RTTY_UIAssets_; }
|
||||
|
||||
bool CreateEndPoint(const std::string &Id, const std::string & Token, const std::string & UserName, const std::string & SerialNumber );
|
||||
bool SendKeyStrokes(const std::string &Id, const u_char *buffer, std::size_t s);
|
||||
bool WindowSize(const std::string &Id, int cols, int rows);
|
||||
bool SendToClient(const std::string &id, const u_char *Buf, std::size_t Len);
|
||||
bool SendToClient(const std::string &id, const std::string &s);
|
||||
|
||||
bool ValidId(const std::string &Id);
|
||||
|
||||
void run() final;
|
||||
|
||||
inline void NotifyDeviceDisconnect(const std::string &id, RTTYS_Device_ConnectionHandler *device) {
|
||||
ResponseQueue_.enqueueNotification(new RTTYS_Notification(RTTYS_Notification_type::device_disconnection,id,device));
|
||||
}
|
||||
|
||||
inline void NotifyClientDisconnect(const std::string &id, RTTYS_ClientConnection *client) {
|
||||
ResponseQueue_.enqueueNotification(new RTTYS_Notification(RTTYS_Notification_type::client_disconnection,id,client));
|
||||
}
|
||||
|
||||
inline bool NotifyDeviceRegistration(const std::string &id, const std::string &token, RTTYS_Device_ConnectionHandler *device) {
|
||||
{
|
||||
std::lock_guard G(LocalMutex_);
|
||||
if (EndPoints_.find(id) == end(EndPoints_))
|
||||
return false;
|
||||
}
|
||||
ResponseQueue_.enqueueNotification(new RTTYS_Notification(RTTYS_Notification_type::device_registration,id,token,device));
|
||||
return true;
|
||||
}
|
||||
|
||||
inline void NotifyClientRegistration(const std::string &id, RTTYS_ClientConnection *client) {
|
||||
ResponseQueue_.enqueueNotification(new RTTYS_Notification(RTTYS_Notification_type::client_registration,id,client));
|
||||
}
|
||||
|
||||
void CreateNewClient(Poco::Net::HTTPServerRequest &request,
|
||||
Poco::Net::HTTPServerResponse &response, const std::string &id);
|
||||
|
||||
void onTimer(Poco::Timer & timer);
|
||||
|
||||
inline bool UseInternal() const {
|
||||
return Internal_;
|
||||
}
|
||||
|
||||
inline Poco::Net::SocketReactor & ClientReactor() { return ClientReactor_; }
|
||||
std::string ReadString(unsigned char *buf, int len, int &pos);
|
||||
void onDeviceAccept(const Poco::AutoPtr<Poco::Net::ReadableNotification>& pNf);
|
||||
|
||||
void onDeviceSocketReadable(const Poco::AutoPtr<Poco::Net::ReadableNotification>& pNf);
|
||||
void onDeviceSocketShutdown(const Poco::AutoPtr<Poco::Net::ShutdownNotification>& pNf);
|
||||
void onDeviceSocketError(const Poco::AutoPtr<Poco::Net::ErrorNotification>& pNf);
|
||||
|
||||
void onClientSocketReadable(const Poco::AutoPtr<Poco::Net::ReadableNotification>& pNf);
|
||||
void onClientSocketShutdown(const Poco::AutoPtr<Poco::Net::ShutdownNotification>& pNf);
|
||||
void onClientSocketError(const Poco::AutoPtr<Poco::Net::ErrorNotification>& pNf);
|
||||
|
||||
void RemoveConnectingDeviceEventHandlers(Poco::Net::StreamSocket &Socket);
|
||||
void RemoveClientEventHandlers(Poco::Net::StreamSocket &Socket);
|
||||
void RemoveDeviceEventHandlers(Poco::Net::StreamSocket &Socket);
|
||||
|
||||
void AddConnectingDeviceEventHandlers(Poco::Net::StreamSocket &Socket);
|
||||
void AddClientEventHandlers(Poco::Net::StreamSocket &Socket, std::shared_ptr<RTTYS_EndPoint> EndPoint);
|
||||
void AddDeviceEventHandlers(Poco::Net::StreamSocket &Socket, std::shared_ptr<RTTYS_EndPoint> EndPoint);
|
||||
|
||||
void onConnectingDeviceData(const Poco::AutoPtr<Poco::Net::ReadableNotification> &pNf);
|
||||
void onConnectingDeviceShutdown(const Poco::AutoPtr<Poco::Net::ShutdownNotification> &pNf);
|
||||
void onConnectingDeviceError(const Poco::AutoPtr<Poco::Net::ErrorNotification> &pNf);
|
||||
|
||||
bool do_msgTypeRegister(Poco::Net::StreamSocket &Socket, unsigned char *Buffer, int Len);
|
||||
bool do_msgTypeHeartbeat(Poco::Net::StreamSocket &Socket);
|
||||
|
||||
void CloseDevice(std::shared_ptr<RTTYS_EndPoint> Device);
|
||||
void CloseClient(std::shared_ptr<RTTYS_EndPoint> Client);
|
||||
void CloseConnection(std::shared_ptr<RTTYS_EndPoint> Connection);
|
||||
|
||||
|
||||
inline auto Uptime() const { return Utils::Now() - Started_; }
|
||||
|
||||
void CreateWSClient(
|
||||
Poco::Net::HTTPServerRequest &request,
|
||||
Poco::Net::HTTPServerResponse &response,
|
||||
const std::string &Id);
|
||||
|
||||
Poco::Net::SocketReactor & Reactor() { return Reactor_; }
|
||||
|
||||
void SendData( std::shared_ptr<RTTYS_EndPoint> & Connection, const u_char *Buf, size_t len );
|
||||
void SendData( std::shared_ptr<RTTYS_EndPoint> & Connection, const std::string &s) ;
|
||||
|
||||
inline std::shared_ptr<RTTYS_EndPoint> FindConnection(const std::string &Id,const std::string &Token) {
|
||||
std::shared_ptr<RTTYS_EndPoint> Res;
|
||||
auto EndPoint = EndPoints_.find(Id);
|
||||
if(EndPoint!=end(EndPoints_) && EndPoint->second->Token_==Token) {
|
||||
Res = EndPoint->second;
|
||||
}
|
||||
return Res;
|
||||
}
|
||||
|
||||
void LogStdException(const std::exception &E, const char *msg);
|
||||
|
||||
private:
|
||||
Poco::Net::SocketReactor ClientReactor_;
|
||||
Poco::Net::SocketReactor DeviceReactor_;
|
||||
Poco::Thread ClientReactorThread_;
|
||||
Poco::Net::SocketReactor Reactor_;
|
||||
Poco::Thread ReactorThread_;
|
||||
std::string RTTY_UIAssets_;
|
||||
bool Internal_ = false;
|
||||
bool NoSecurity_=false;
|
||||
volatile bool Running_ = false;
|
||||
|
||||
std::map<std::string,std::unique_ptr<RTTYS_EndPoint>> EndPoints_; // id, endpoint
|
||||
std::unique_ptr<Poco::Net::HTTPServer> WebServer_;
|
||||
std::unique_ptr<Poco::Net::SocketAcceptor<RTTYS_Device_ConnectionHandler>> DeviceAcceptor_;
|
||||
Poco::Thread DeviceReactorThread_;
|
||||
Poco::NotificationQueue ResponseQueue_;
|
||||
std::atomic_bool NotificationManagerRunning_=false;
|
||||
Poco::Thread NotificationManager_;
|
||||
|
||||
std::map<std::string,std::shared_ptr<RTTYS_EndPoint>> EndPoints_; // id, endpoint
|
||||
std::map<int, std::shared_ptr<RTTYS_EndPoint> > Connections_;
|
||||
std::map<int, std::pair<Poco::Net::StreamSocket,std::chrono::time_point<std::chrono::high_resolution_clock>>> ConnectingDevices_;
|
||||
|
||||
Poco::Timer Timer_;
|
||||
std::unique_ptr<Poco::TimerCallback<RTTYS_server>> GCCallBack_;
|
||||
std::list<std::unique_ptr<RTTYS_Device_ConnectionHandler>> FailedDevices;
|
||||
std::list<std::unique_ptr<RTTYS_ClientConnection>> FailedClients;
|
||||
std::recursive_mutex LocalMutex_;
|
||||
std::mutex ServerMutex_;
|
||||
|
||||
std::atomic_uint64_t TotalEndPoints_=0;
|
||||
std::atomic_uint64_t FailedNumDevices_=0;
|
||||
std::atomic_uint64_t FailedNumClients_=0;
|
||||
double TotalConnectedDeviceTime_=0.0;
|
||||
double TotalConnectedClientTime_=0.0;
|
||||
std::chrono::duration<double,std::milli> TotalConnectedDeviceTime_{0ms},
|
||||
TotalConnectedClientTime_{0ms};
|
||||
|
||||
std::atomic_uint64_t Started_=Utils::Now();
|
||||
std::atomic_uint64_t MaxConcurrentSessions_=0;
|
||||
std::unique_ptr<Poco::Net::ServerSocket> DeviceSocket_;
|
||||
std::unique_ptr<Poco::Net::SecureServerSocket> SecureDeviceSocket_;
|
||||
|
||||
static inline std::uint64_t CurrentTID_=0;
|
||||
|
||||
explicit RTTYS_server() noexcept:
|
||||
SubSystemServer("RTTY_Server", "RTTY-SVR", "rtty.server")
|
||||
@@ -310,6 +238,6 @@ namespace OpenWifi {
|
||||
}
|
||||
};
|
||||
|
||||
inline RTTYS_server * RTTYS_server() { return RTTYS_server::instance(); }
|
||||
inline class RTTYS_server * RTTYS_server() { return RTTYS_server::instance(); }
|
||||
|
||||
} // namespace OpenWifi
|
||||
|
||||
@@ -120,6 +120,8 @@ typedef Poco::Tuple<
|
||||
Poco::Data::Keywords::use(SerialNumber),
|
||||
Poco::Data::Keywords::use(Command);
|
||||
Delete.execute();
|
||||
Delete.reset(Sess);
|
||||
|
||||
return true;
|
||||
} catch(const Poco::Exception &E) {
|
||||
Logger().log(E);
|
||||
@@ -205,6 +207,8 @@ typedef Poco::Tuple<
|
||||
ConvertCommandRecord(i, R);
|
||||
Commands.push_back(R);
|
||||
}
|
||||
Select.reset(Sess);
|
||||
|
||||
return true;
|
||||
} catch (const Poco::Exception &E) {
|
||||
Logger().log(E);
|
||||
@@ -237,6 +241,7 @@ typedef Poco::Tuple<
|
||||
|
||||
Delete << IntroStatement + DateSelector;
|
||||
Delete.execute();
|
||||
Delete.reset(Sess);
|
||||
|
||||
return true;
|
||||
} catch (const Poco::Exception &E) {
|
||||
@@ -274,7 +279,7 @@ typedef Poco::Tuple<
|
||||
if (Records.size() < HowMany)
|
||||
Done = true;
|
||||
}
|
||||
|
||||
Select.reset(Sess);
|
||||
return true;
|
||||
} catch (const Poco::Exception &E) {
|
||||
Logger().log(E);
|
||||
@@ -343,6 +348,8 @@ typedef Poco::Tuple<
|
||||
Poco::Data::Keywords::use(Status),
|
||||
Poco::Data::Keywords::use(Window);
|
||||
Update.execute();
|
||||
Update.reset(Sess);
|
||||
|
||||
} catch (const Poco::Exception &E) {
|
||||
Logger().log(E);
|
||||
}
|
||||
@@ -359,6 +366,7 @@ typedef Poco::Tuple<
|
||||
Poco::Data::Keywords::use(Now),
|
||||
Poco::Data::Keywords::use(Window);
|
||||
Update.execute();
|
||||
Update.reset(Sess);
|
||||
} catch (const Poco::Exception &E) {
|
||||
Logger().log(E);
|
||||
}
|
||||
@@ -418,6 +426,11 @@ typedef Poco::Tuple<
|
||||
|
||||
Delete << ConvertParams(St), Poco::Data::Keywords::use(UUID);
|
||||
Delete.execute();
|
||||
Delete.reset(Sess);
|
||||
St = "DELETE FROM FileUploads WHERE UUID=?";
|
||||
Delete << ConvertParams(St), Poco::Data::Keywords::use(UUID);
|
||||
Delete.execute();
|
||||
Delete.reset(Sess);
|
||||
|
||||
return true;
|
||||
} catch (const Poco::Exception &E) {
|
||||
@@ -446,6 +459,7 @@ typedef Poco::Tuple<
|
||||
ConvertCommandRecord(i,R);
|
||||
Commands.push_back(R);
|
||||
}
|
||||
Select.reset(Sess);
|
||||
return true;
|
||||
} catch (const Poco::Exception &E) {
|
||||
Logger().log(E);
|
||||
@@ -586,23 +600,26 @@ typedef Poco::Tuple<
|
||||
|
||||
bool Storage::AttachFileDataToCommand(std::string & UUID, const std::stringstream & FileContent, const std::string &Type) {
|
||||
try {
|
||||
Poco::Data::Session Sess = Pool_->get();
|
||||
auto Now = Utils::Now();
|
||||
uint64_t WaitForFile = 0;
|
||||
|
||||
Poco::Data::Statement Update(Sess);
|
||||
|
||||
uint64_t Size = FileContent.str().size();
|
||||
|
||||
std::string St{
|
||||
"UPDATE CommandList SET WaitingForFile=?, AttachDate=?, AttachSize=? WHERE UUID=?"};
|
||||
Poco::Data::Session Sess = Pool_->get();
|
||||
Poco::Data::Statement Statement(Sess);
|
||||
|
||||
Update << ConvertParams(St),
|
||||
std::string StatementStr;
|
||||
|
||||
// Get the existing command
|
||||
|
||||
|
||||
StatementStr = "UPDATE CommandList SET WaitingForFile=?, AttachDate=?, AttachSize=? WHERE UUID=?";
|
||||
|
||||
Statement << ConvertParams(StatementStr),
|
||||
Poco::Data::Keywords::use(WaitForFile),
|
||||
Poco::Data::Keywords::use(Now),
|
||||
Poco::Data::Keywords::use(Size),
|
||||
Poco::Data::Keywords::use(UUID);
|
||||
Update.execute();
|
||||
Statement.execute();
|
||||
|
||||
if (Size < FileUploader()->MaxSize()) {
|
||||
|
||||
@@ -644,9 +661,11 @@ typedef Poco::Tuple<
|
||||
Poco::Data::Statement Select1(Sess);
|
||||
|
||||
std::string TmpSerialNumber;
|
||||
std::string st1{"SELECT SerialNumber FROM CommandList WHERE UUID=?"};
|
||||
std::string st1{"SELECT SerialNumber, Command FROM CommandList WHERE UUID=?"};
|
||||
std::string Command;
|
||||
Select1 << ConvertParams(st1),
|
||||
Poco::Data::Keywords::into(TmpSerialNumber),
|
||||
Poco::Data::Keywords::into(Command),
|
||||
Poco::Data::Keywords::use(UUID);
|
||||
Select1.execute();
|
||||
|
||||
@@ -655,15 +674,18 @@ typedef Poco::Tuple<
|
||||
}
|
||||
|
||||
std::string St2{"SELECT FileContent, Type FROM FileUploads WHERE UUID=?"};
|
||||
|
||||
Poco::Data::Statement Select2(Sess);
|
||||
Select2 << ConvertParams(St2),
|
||||
Poco::Data::Keywords::into(L),
|
||||
Poco::Data::Keywords::into(Type),
|
||||
Poco::Data::Keywords::use(UUID);
|
||||
Select2.execute();
|
||||
|
||||
FileContent.assign(L.content().begin(),L.content().end());
|
||||
|
||||
if(Command=="script")
|
||||
Type = "gzip";
|
||||
else if(Command=="trace")
|
||||
Type = "pcap";
|
||||
return true;
|
||||
} catch (const Poco::Exception &E) {
|
||||
Logger().log(E);
|
||||
@@ -712,6 +734,21 @@ typedef Poco::Tuple<
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Storage::RemoveUploadedFilesRecordsOlderThan(uint64_t Date) {
|
||||
try {
|
||||
Poco::Data::Session Sess = Pool_->get();
|
||||
Poco::Data::Statement Delete(Sess);
|
||||
|
||||
std::string St1{"delete from FileUploads where Created<?"};
|
||||
Delete << ConvertParams(St1), Poco::Data::Keywords::use(Date);
|
||||
Delete.execute();
|
||||
return true;
|
||||
} catch (const Poco::Exception &E) {
|
||||
Logger().log(E);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Storage::RemoveCommandListRecordsOlderThan(uint64_t Date) {
|
||||
try {
|
||||
Poco::Data::Session Sess = Pool_->get();
|
||||
|
||||
@@ -48,7 +48,10 @@ namespace OpenWifi {
|
||||
"entity, "
|
||||
"modified, "
|
||||
"locale,"
|
||||
"restrictedDevice"
|
||||
"restrictedDevice,"
|
||||
"pendingConfiguration, "
|
||||
"pendingConfigurationCmd, "
|
||||
"restrictionDetails "
|
||||
};
|
||||
|
||||
const static std::string DB_DeviceUpdateFields{
|
||||
@@ -74,10 +77,13 @@ namespace OpenWifi {
|
||||
"entity=?, "
|
||||
"modified=?, "
|
||||
"locale=?, "
|
||||
"restrictedDevice=?"
|
||||
"restrictedDevice=?, "
|
||||
"pendingConfiguration=?, "
|
||||
"pendingConfigurationCmd=?, "
|
||||
"restrictionDetails=? "
|
||||
};
|
||||
|
||||
const static std::string DB_DeviceInsertValues{" VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?) "};
|
||||
const static std::string DB_DeviceInsertValues{" VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?) "};
|
||||
|
||||
typedef Poco::Tuple<
|
||||
std::string,
|
||||
@@ -102,7 +108,10 @@ namespace OpenWifi {
|
||||
std::string,
|
||||
uint64_t,
|
||||
std::string,
|
||||
bool
|
||||
bool,
|
||||
std::string,
|
||||
std::string,
|
||||
std::string
|
||||
> DeviceRecordTuple;
|
||||
typedef std::vector<DeviceRecordTuple> DeviceRecordList;
|
||||
|
||||
@@ -130,6 +139,9 @@ namespace OpenWifi {
|
||||
D.modified = R.get<20>();
|
||||
D.locale = R.get<21>();
|
||||
D.restrictedDevice = R.get<22>();
|
||||
D.pendingConfiguration = R.get<23>();
|
||||
D.pendingConfigurationCmd = R.get<24>();
|
||||
D.restrictionDetails = RESTAPI_utils::to_object<OpenWifi::GWObjects::DeviceRestrictions>(R.get<25>());
|
||||
}
|
||||
|
||||
void ConvertDeviceRecord(const GWObjects::Device &D, DeviceRecordTuple & R) {
|
||||
@@ -156,6 +168,9 @@ namespace OpenWifi {
|
||||
R.set<20>(D.modified);
|
||||
R.set<21>(D.locale);
|
||||
R.set<22>(D.restrictedDevice);
|
||||
R.set<23>(D.pendingConfiguration);
|
||||
R.set<24>(D.pendingConfigurationCmd);
|
||||
R.set<25>(RESTAPI_utils::to_string(D.restrictionDetails));
|
||||
}
|
||||
|
||||
bool Storage::GetDeviceCount(uint64_t &Count) {
|
||||
|
||||
@@ -98,6 +98,7 @@ namespace OpenWifi {
|
||||
ConvertHealthCheckRecord(i,R);
|
||||
Checks.push_back(R);
|
||||
}
|
||||
Select.reset(Sess);
|
||||
return true;
|
||||
}
|
||||
catch (const Poco::Exception &E) {
|
||||
@@ -125,6 +126,7 @@ namespace OpenWifi {
|
||||
ConvertHealthCheckRecord(i,R);
|
||||
Checks.push_back(R);
|
||||
}
|
||||
Select.reset(Sess);
|
||||
return true;
|
||||
}
|
||||
catch (const Poco::Exception &E) {
|
||||
|
||||
@@ -107,6 +107,7 @@ namespace OpenWifi {
|
||||
ConvertLogsRecord(i,R);
|
||||
Stats.push_back(R);
|
||||
}
|
||||
Select.reset(Sess);
|
||||
return true;
|
||||
}
|
||||
catch (const Poco::Exception &E) {
|
||||
@@ -144,6 +145,7 @@ namespace OpenWifi {
|
||||
Delete << StatementStr + DateSelector + TypeSelector;
|
||||
|
||||
Delete.execute();
|
||||
Delete.reset(Sess);
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -172,6 +174,7 @@ namespace OpenWifi {
|
||||
ConvertLogsRecord(i,R);
|
||||
Stats.push_back(R);
|
||||
}
|
||||
Select.reset(Sess);
|
||||
return true;
|
||||
}
|
||||
catch (const Poco::Exception &E) {
|
||||
|
||||
136
src/storage/storage_scripts.cpp
Normal file
136
src/storage/storage_scripts.cpp
Normal file
@@ -0,0 +1,136 @@
|
||||
//
|
||||
// Created by stephane bourque on 2022-11-21.
|
||||
//
|
||||
|
||||
#include "storage_scripts.h"
|
||||
|
||||
#include "framework/RESTAPI_utils.h"
|
||||
#include "fmt/format.h"
|
||||
#include "framework/AppServiceRegistry.h"
|
||||
|
||||
namespace OpenWifi {
|
||||
static ORM::FieldVec ScriptDB_Fields{
|
||||
ORM::Field{"id", 36, true},
|
||||
ORM::Field{"name", ORM::FieldType::FT_TEXT},
|
||||
ORM::Field{"description", ORM::FieldType::FT_TEXT},
|
||||
ORM::Field{"uri", ORM::FieldType::FT_TEXT},
|
||||
ORM::Field{"content", ORM::FieldType::FT_TEXT},
|
||||
ORM::Field{"version", ORM::FieldType::FT_TEXT},
|
||||
ORM::Field{"type", ORM::FieldType::FT_TEXT},
|
||||
ORM::Field{"created", ORM::FieldType::FT_BIGINT},
|
||||
ORM::Field{"modified", ORM::FieldType::FT_BIGINT},
|
||||
ORM::Field{"author", ORM::FieldType::FT_TEXT},
|
||||
ORM::Field{"restricted", ORM::FieldType::FT_TEXT},
|
||||
ORM::Field{"deferred", ORM::FieldType::FT_BOOLEAN},
|
||||
ORM::Field{"timeout", ORM::FieldType::FT_BIGINT},
|
||||
ORM::Field{"defaultUploadURI", ORM::FieldType::FT_TEXT}
|
||||
};
|
||||
|
||||
static ORM::IndexVec MakeIndices(const std::string & shortname) {
|
||||
return ORM::IndexVec{
|
||||
{std::string(shortname + "_name_index"),
|
||||
ORM::IndexEntryVec{
|
||||
{
|
||||
std::string("name"),
|
||||
ORM::Indextype::ASC }}}
|
||||
};
|
||||
};
|
||||
|
||||
ScriptDB::ScriptDB( const std::string &TableName, const std::string &Shortname ,OpenWifi::DBType T,
|
||||
Poco::Data::SessionPool &P, Poco::Logger &L) :
|
||||
DB(T, TableName.c_str(), ScriptDB_Fields, MakeIndices(Shortname), P, L, Shortname.c_str()) {
|
||||
}
|
||||
|
||||
bool ScriptDB::Upgrade([[maybe_unused]] uint32_t from, uint32_t &to) {
|
||||
to = Version();
|
||||
std::vector<std::string> Script{
|
||||
};
|
||||
|
||||
for(const auto &i:Script) {
|
||||
try {
|
||||
auto Session = Pool_.get();
|
||||
Session << i , Poco::Data::Keywords::now;
|
||||
} catch (...) {
|
||||
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void ScriptDB::Initialize() {
|
||||
bool Initialized = false;
|
||||
AppServiceRegistry().Get("script_db_initialized",Initialized);
|
||||
if(Initialized)
|
||||
return;
|
||||
GWObjects::ScriptEntry SE;
|
||||
|
||||
SE.id = MicroServiceCreateUUID();
|
||||
SE.name = "ASB Bundle";
|
||||
SE.description = "Automated on-demand detailed debugging information collection from an AP";
|
||||
SE.uri = "https://telecominfraproject.atlassian.net/wiki/spaces/WIFI/pages/1678147585/AP+Support+Bundle+ASB";
|
||||
SE.version = "1.0";
|
||||
SE.author = "blogic";
|
||||
SE.modified = SE.created = Utils::Now();
|
||||
SE.type = "bundle";
|
||||
SE.deferred = true;
|
||||
SE.timeout = 30;
|
||||
SE.content = std::string{
|
||||
R"lit(
|
||||
bundle.wifi();
|
||||
let paths = [
|
||||
[ 'network.wireless', 'status' ],
|
||||
[ 'network.device', 'status' ],
|
||||
[ 'network.interface', 'dump' ],
|
||||
[ 'log', 'read', { stream: false } ],
|
||||
];
|
||||
for (let path in paths)
|
||||
bundle.ubus(path[0], path[1], path[2]);
|
||||
for (let config in [ 'network', 'wireless', 'dhcp', 'firewall', 'system' ])
|
||||
bundle.uci(config);
|
||||
for (let cmd in [ "route", "ifconfig", "logread" ])
|
||||
bundle.shell(cmd);
|
||||
)lit"};
|
||||
|
||||
if(CreateRecord(SE)) {
|
||||
AppServiceRegistry().Set("script_db_initialized",true);
|
||||
poco_information(Logger(), "Script DB has been in initialized.");
|
||||
return;
|
||||
}
|
||||
poco_error(Logger(), "Script DB could not be initialized.");
|
||||
}
|
||||
|
||||
} // OpenWifi
|
||||
|
||||
template<> void ORM::DB<OpenWifi::ScriptRecordTuple, OpenWifi::GWObjects::ScriptEntry>::Convert(const OpenWifi::ScriptRecordTuple &In, OpenWifi::GWObjects::ScriptEntry &Out) {
|
||||
Out.id = In.get<0>();
|
||||
Out.name = In.get<1>();
|
||||
Out.description = In.get<2>();
|
||||
Out.uri = In.get<3>();
|
||||
Out.content = In.get<4>();
|
||||
Out.version = In.get<5>();
|
||||
Out.type = In.get<6>();
|
||||
Out.created = In.get<7>();
|
||||
Out.modified = In.get<8>();
|
||||
Out.author = In.get<9>();
|
||||
Out.restricted = OpenWifi::RESTAPI_utils::to_object_array(In.get<10>());
|
||||
Out.deferred = In.get<11>();
|
||||
Out.timeout = In.get<12>();
|
||||
Out.defaultUploadURI = In.get<13>();
|
||||
}
|
||||
|
||||
template<> void ORM::DB<OpenWifi::ScriptRecordTuple, OpenWifi::GWObjects::ScriptEntry>::Convert(const OpenWifi::GWObjects::ScriptEntry &In, OpenWifi::ScriptRecordTuple &Out) {
|
||||
Out.set<0>(In.id);
|
||||
Out.set<1>(In.name);
|
||||
Out.set<2>(In.description);
|
||||
Out.set<3>(In.uri);
|
||||
Out.set<4>(In.content);
|
||||
Out.set<5>(In.version);
|
||||
Out.set<6>(In.type);
|
||||
Out.set<7>(In.created);
|
||||
Out.set<8>(In.modified);
|
||||
Out.set<9>(In.author);
|
||||
Out.set<10>(OpenWifi::RESTAPI_utils::to_string(In.restricted));
|
||||
Out.set<11>(In.deferred);
|
||||
Out.set<12>(In.timeout);
|
||||
Out.set<13>(In.defaultUploadURI);
|
||||
}
|
||||
42
src/storage/storage_scripts.h
Normal file
42
src/storage/storage_scripts.h
Normal file
@@ -0,0 +1,42 @@
|
||||
//
|
||||
// Created by stephane bourque on 2022-11-21.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "framework/orm.h"
|
||||
#include "RESTObjects/RESTAPI_GWobjects.h"
|
||||
|
||||
namespace OpenWifi {
|
||||
|
||||
typedef Poco::Tuple<
|
||||
std::string, // id
|
||||
std::string, // name
|
||||
std::string, // description
|
||||
std::string, // uri
|
||||
std::string, // content
|
||||
std::string, // version
|
||||
std::string, // type
|
||||
uint64_t, // created = 0;
|
||||
uint64_t, // modified = 0;
|
||||
std::string, // author
|
||||
std::string, // restricted
|
||||
bool, // deferred
|
||||
uint64_t, // timeout
|
||||
std::string
|
||||
> ScriptRecordTuple;
|
||||
typedef std::vector <ScriptRecordTuple> ScriptRecordTupleList;
|
||||
|
||||
class ScriptDB : public ORM::DB<ScriptRecordTuple, GWObjects::ScriptEntry> {
|
||||
public:
|
||||
ScriptDB( const std::string &name, const std::string &shortname, OpenWifi::DBType T, Poco::Data::SessionPool & P, Poco::Logger &L);
|
||||
virtual ~ScriptDB() {}
|
||||
inline uint32_t Version() override {
|
||||
return 1;
|
||||
}
|
||||
|
||||
bool Upgrade(uint32_t from, uint32_t &to) override;
|
||||
void Initialize();
|
||||
};
|
||||
|
||||
}
|
||||
@@ -130,11 +130,13 @@ namespace OpenWifi {
|
||||
ConvertStatsRecord(i,R);
|
||||
Stats.emplace_back(R);
|
||||
}
|
||||
Select.reset(Sess);
|
||||
return true;
|
||||
}
|
||||
catch (const Poco::Exception &E) {
|
||||
poco_warning(Logger(),fmt::format("{}: Failed with: {}", std::string(__func__), E.displayText()));
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -81,7 +81,11 @@ namespace OpenWifi {
|
||||
"subscriber VARCHAR(64), "
|
||||
"entity VARCHAR(64), "
|
||||
"modified BIGINT,"
|
||||
"locale varchar(32) "
|
||||
"locale varchar(32), "
|
||||
"restrictedDevice BOOLEAN, "
|
||||
"pendingConfiguration TEXT, "
|
||||
"pendingConfigurationCmd VARCHAR(64), "
|
||||
"restrictionDetails TEXT "
|
||||
",INDEX DeviceOwner (Owner ASC),"
|
||||
"INDEX LocationIndex (Location ASC))", Poco::Data::Keywords::now;
|
||||
} else if(dbType_==sqlite || dbType_==pgsql) {
|
||||
@@ -108,7 +112,10 @@ namespace OpenWifi {
|
||||
"entity VARCHAR(64) , "
|
||||
"modified BIGINT,"
|
||||
"locale varchar(32), "
|
||||
"restrictedDevice BOOLEAN "
|
||||
"restrictedDevice BOOLEAN, "
|
||||
"pendingConfiguration TEXT,"
|
||||
"pendingConfigurationCmd VARCHAR(64), "
|
||||
"restrictionDetails TEXT "
|
||||
")", Poco::Data::Keywords::now;
|
||||
Sess << "CREATE INDEX IF NOT EXISTS DeviceOwner ON Devices (Owner ASC)", Poco::Data::Keywords::now;
|
||||
Sess << "CREATE INDEX IF NOT EXISTS DeviceLocation ON Devices (Location ASC)", Poco::Data::Keywords::now;
|
||||
@@ -121,6 +128,9 @@ namespace OpenWifi {
|
||||
"alter table devices add column modified bigint",
|
||||
"alter table devices add column locale varchar(32)",
|
||||
"alter table devices add column restrictedDevice boolean",
|
||||
"alter table devices add column pendingConfiguration TEXT",
|
||||
"alter table devices add column pendingConfigurationCmd VARCHAR(64)",
|
||||
"alter table devices add column restrictionDetails TEXT",
|
||||
};
|
||||
|
||||
for(const auto &i:Script) {
|
||||
|
||||
@@ -794,6 +794,22 @@ stats7count() {
|
||||
jq < ${result_file}
|
||||
}
|
||||
|
||||
listscripts() {
|
||||
curl ${FLAGS} -X GET "https://${OWGW}/api/v1/scripts" \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "Accept: application/json" \
|
||||
-H "Authorization: Bearer ${token}" > ${result_file}
|
||||
jq < ${result_file}
|
||||
}
|
||||
|
||||
getscript() {
|
||||
curl ${FLAGS} -X GET "https://${OWGW}/api/v1/script/$1" \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "Accept: application/json" \
|
||||
-H "Authorization: Bearer ${token}" > ${result_file}
|
||||
jq < ${result_file}
|
||||
}
|
||||
|
||||
check_response() {
|
||||
|
||||
if [ -s "$1" ]; then
|
||||
@@ -1065,6 +1081,8 @@ case "$1" in
|
||||
"notifications") login; notifications "$2"; logout;;
|
||||
"stats7") login; stats7 "$2"; logout;;
|
||||
"stats7count") login; stats7count "$2"; logout;;
|
||||
"listscripts") login; listscripts; logout;;
|
||||
"getscript") login; getscript "$2"; logout;;
|
||||
"testtoken") testtoken;;
|
||||
*) help ;;
|
||||
esac
|
||||
|
||||
9
test_scripts/key_generation/generate_key.sh
Executable file
9
test_scripts/key_generation/generate_key.sh
Executable file
@@ -0,0 +1,9 @@
|
||||
#!/bin/bash
|
||||
|
||||
private_key_name="$1"-private-key.pem
|
||||
public_key_name="$1"-public-key.pem
|
||||
|
||||
echo "Generating private key..."
|
||||
openssl genrsa -out ${private_key_name} 2048
|
||||
echo "Extracting public key"
|
||||
openssl rsa -in ${private_key_name} -outform PEM -pubout -out ${public_key_name}
|
||||
27
test_scripts/key_generation/test1-private-key.pem
Normal file
27
test_scripts/key_generation/test1-private-key.pem
Normal file
@@ -0,0 +1,27 @@
|
||||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIEpAIBAAKCAQEAvDyH5dKXDH6inAB6HeKekywaPoHi/kogKtsezOEaSoijdrJm
|
||||
8k3ohC4NzmmXzMa9taaQCE5DMDq1ZWuv8uKyCyRSqhnBIqj6Oa7KRzVnYDpk4Vkd
|
||||
FS+A++VpYhYVFeUFhtb6Ey1gkXVjOXiy3UiJuEv9aeX2PzL3IUF+o4cfkOe42QQB
|
||||
k3hgWFhinjb39TtssrhUt1+/kq2EEFZmjKK7szTqpjBTZKgfvL7pkjtZ1+V7/G5R
|
||||
pkYCrITh9WqyBp2lFyQbnN4GIrPVc+pr1Tk0ZbgAyRnkNaijLm79akNt3xIBzJSB
|
||||
46kAUjZsKJY/Kh3FM4OoqvJRwYcWvoMXb8rRaQIDAQABAoIBAQCVgS4ep0g5MEtO
|
||||
xEI5gkiYc6rUgq0bcxxhbW/lIdST5jqOh9ukD6ThdwKYMt3SUvdSU1yKfD55C+gP
|
||||
CZzRuKPYnZzaZWI0eSlkryMRs6TLlRWStgiXTwePCgLNWOSeYywkkJJGsP/GCAor
|
||||
F2ZYwsg/jHtVpMQUJhKKY06F60hy+Xtpe8fYEkbLfh1j7OzwBKGZOn+lp2YXXJBU
|
||||
3ccSwwIpJQu/O9SM8rMchL7izNU60zONYlswr3fF148mMwDS9RYMBMCPqb6wNfNm
|
||||
EhmMPR7PlsJmlV96rlniwbTh0/I67w7xEThFM2xRx2JZjBZVYD5GMNWE3tKBQnwX
|
||||
H23PXzuRAoGBAOfWBTxDJZzAMXU8EK12su8bhFOv13D7HlGUA+Y2a9ngzs/rOZmg
|
||||
buNTjLyod50dSPjZm2b2TDZOXPrA13b3HR+NTfDYzhMElzr4DWPF/X4c2qRylWqb
|
||||
8G8xrrTsq1HQYTWbJI60zuorD8s+w3Kt/G2w6Iq590Q4Iw7uHMra8IbvAoGBAM/b
|
||||
KX5BxliqNQIv3+XnSEBhQqLbE7VjPJztXtsknAO8mv/vUJJWta9NjoCGKdaKh4KF
|
||||
9u88ixkfvOYYVZTbQwUhNCj5PuqW+i2ikmAucMsiVoPBXFUqnoIA5274+hQ7sf0K
|
||||
JndP7FDKiJkAGb0nF6okmEQO+tHji6oL31ITde0nAoGASEyQOWjfU/ED+4GN2erI
|
||||
hpTYQZj24P8PR3WXebXDEKFxHZpHzkcgDbjCjRskolS9qw2BzyxEPDNX/8Mf7rPF
|
||||
208f3VpfecLWvscYteLK2Qd6kApD2oljA+pEh5u/GbaYejU1w2NTm+dt935NSXhE
|
||||
3phrDMhN+nJfTIqpZAG/PPUCgYEAi5tWSTkAcbkQlYF2TsKDIsqwqRWgLSqUIYrF
|
||||
NUdnipL5QIGKil+29CGRXv29yB2PWrmD27e8bYmFpL4fbTW/1AgzMnoGKiZxrokM
|
||||
65EFrUpI9YG/9GwFvqfAyiZsQX6+04gnwedqf/EowirxHrzNBjhCFSRCjwrYWcRT
|
||||
oJr1j+0CgYA7LktUigAIoLTlo09nGoN7UBySRBRCn6e+vSSyasWLVQ3KPX9tmKDH
|
||||
UXSSFoki+vcbFG/IgrwfawhmPlcXUPxa021Kj0HPiNGrKK/klhuSmkWulP9xzuAM
|
||||
8SqN58+BnOYxFQDXJq2ui6NJ+I1O7Mj+uaSiNzpMgqcHazRQy5c+cQ==
|
||||
-----END RSA PRIVATE KEY-----
|
||||
9
test_scripts/key_generation/test1-public-key.pem
Normal file
9
test_scripts/key_generation/test1-public-key.pem
Normal file
@@ -0,0 +1,9 @@
|
||||
-----BEGIN PUBLIC KEY-----
|
||||
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvDyH5dKXDH6inAB6HeKe
|
||||
kywaPoHi/kogKtsezOEaSoijdrJm8k3ohC4NzmmXzMa9taaQCE5DMDq1ZWuv8uKy
|
||||
CyRSqhnBIqj6Oa7KRzVnYDpk4VkdFS+A++VpYhYVFeUFhtb6Ey1gkXVjOXiy3UiJ
|
||||
uEv9aeX2PzL3IUF+o4cfkOe42QQBk3hgWFhinjb39TtssrhUt1+/kq2EEFZmjKK7
|
||||
szTqpjBTZKgfvL7pkjtZ1+V7/G5RpkYCrITh9WqyBp2lFyQbnN4GIrPVc+pr1Tk0
|
||||
ZbgAyRnkNaijLm79akNt3xIBzJSB46kAUjZsKJY/Kh3FM4OoqvJRwYcWvoMXb8rR
|
||||
aQIDAQAB
|
||||
-----END PUBLIC KEY-----
|
||||
27
test_scripts/key_generation/test2-private-key.pem
Normal file
27
test_scripts/key_generation/test2-private-key.pem
Normal file
@@ -0,0 +1,27 @@
|
||||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIEpAIBAAKCAQEAvPbxCM3RvHaAZq0G9yXgzaHy9q/RzuIKiCC8cmVQ2PsTvx2m
|
||||
YP75Ech0omMbWr+nfcgNGHrIxmTXM8Jr77oH9J1pUiBZj0plWp3Bj6S4on7OfRBi
|
||||
tq6rFUvjyGVg08Khp+KLnPE2Ga+YksC/mK7oXjYRyjH99uX9pOCPJDj1rFpsvDjP
|
||||
0xu9nkgvhWfzqPvLsLZv5RHM+a1TigckSGl3CpWUNkU/o7ozfvMUQgTBvalbCSTY
|
||||
9PE3JvkoPd2DARoOmtpAsUkCVx5V18+j5aCxYIG8tPONh8addblLYeskKI9PvzSE
|
||||
hmazT5deaQHSSLwZo96qtXcdMPIilcSqet9NfQIDAQABAoIBABSEi691Caz5AQAl
|
||||
EXiMeFhbmVIHzTQ1fwdA5rVVIu4sdPxvb71gchLoPSHUuQelf748lo9t5ZcFJAjO
|
||||
t4GUJYD+Bo2QTaktXsv0DSxXqmSaeDlEKjPDy3fIgbckqtrTa1IbWyVzW3h2hI6K
|
||||
t0MQ2tI/9LaLrxO77UqVx3UbajGIf/M2GI91ZChaEa37YpIDu1so4NNZIzGQV3oT
|
||||
Gq+XpWOtmw/6Dk2AEQHdibytge58yTXZLoe49n02X2UepHNd9Bnwv5WvmJZqgA+r
|
||||
UI67YCfg35NoT45p7RMYcZCHvZU7+nYMCgDxV9o91VpylZ99plhFVRZSCfI0Ynrq
|
||||
t9aX4tECgYEA9QSTbTGDZwzmKHHc75ZapjJKkATnszOYF7pgRqOv+5UWayhy3J/z
|
||||
hyTAGjGr2FQH5HwGAvAwVsJ1WhQHedk/W8lqea+EqCHSau/HGsYQKD061jP0x2G6
|
||||
zSiBKi0sHxFDRztV9Llny2eCLHGBR+yFQRZW1DwLwpsFg8EeYIcmoV8CgYEAxW8w
|
||||
sJHW8uz3wW0ntE0dSKVEKImb+pgNI0LS30X0KJilDTliNLHPphhYQvEl4H2t2XXd
|
||||
x3O4KbQ0fnXi7iyEO6v95ZH8P4OcjpZ2wXV51t8H5DD9hCTXc7yLR+FhaH3XoNVf
|
||||
EETjiTwPdCa0MsswKRF/39chYQ1sF5a6n6t+MqMCgYEA8jPjyDz5uBR4L+Lek7f9
|
||||
Q+zS6CrxH6QQ5OPH6AxHGlr2HleNs6oqAZ3CiCIxzVbDtokjKCRmpFz1xGWoPjsS
|
||||
9pjUOBXY/JrydeMw3raLojtkvfn+LlndXpB7nkWpJ8zYxMFS5uegQuG/PE+3jHGy
|
||||
B/UdQA9bULQNb4CnlqQC++ECgYEAunNWFPm1d7aoBygRXemRZSCF7I6AGjjr90fN
|
||||
IwPKH2iAPqvZfZAKXH4TJCzeK1IlEv+HkStMWT4QcPjddTXfLwcvAFVMVaLx/4pC
|
||||
3lIV3QDFUA+f6uJsAaWmFxzWQ7rMHtxCKXgVNW3d3kAK3wkaEz6ud3KP2Dq3wNMc
|
||||
rVtkE2cCgYB5cNbmStIlmc/bpBGkfW7Sv1RwPVCV3U5Vv4NDoM+EDJ4UDmRKB0Ht
|
||||
cG5bfym6bgcBOWVAQNsNgpGJGAfF3RIVzeFgiD/cDDG04dIia9T7HuSbsJSoXYde
|
||||
gSI068hPzfh3xksus0RPPr5DDKlTUsD5e02ZgrlmRez6ILV2dMhyCQ==
|
||||
-----END RSA PRIVATE KEY-----
|
||||
9
test_scripts/key_generation/test2-public-key.pem
Normal file
9
test_scripts/key_generation/test2-public-key.pem
Normal file
@@ -0,0 +1,9 @@
|
||||
-----BEGIN PUBLIC KEY-----
|
||||
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvPbxCM3RvHaAZq0G9yXg
|
||||
zaHy9q/RzuIKiCC8cmVQ2PsTvx2mYP75Ech0omMbWr+nfcgNGHrIxmTXM8Jr77oH
|
||||
9J1pUiBZj0plWp3Bj6S4on7OfRBitq6rFUvjyGVg08Khp+KLnPE2Ga+YksC/mK7o
|
||||
XjYRyjH99uX9pOCPJDj1rFpsvDjP0xu9nkgvhWfzqPvLsLZv5RHM+a1TigckSGl3
|
||||
CpWUNkU/o7ozfvMUQgTBvalbCSTY9PE3JvkoPd2DARoOmtpAsUkCVx5V18+j5aCx
|
||||
YIG8tPONh8addblLYeskKI9PvzSEhmazT5deaQHSSLwZo96qtXcdMPIilcSqet9N
|
||||
fQIDAQAB
|
||||
-----END PUBLIC KEY-----
|
||||
Reference in New Issue
Block a user