Compare commits

...

149 Commits

Author SHA1 Message Date
jaspreetsachdev
9dde85495e Updated values to RC3 for ucentralgw 2021-09-07 15:55:32 -04:00
Stephane Bourque
6faec0718b Merge pull request #50 from Telecominfraproject/master
Fixes for AP disconnects
2021-09-07 11:47:37 -07:00
stephb9959
e4e2075021 Merge remote-tracking branch 'origin/master' 2021-09-03 08:03:23 -07:00
stephb9959
314ae21d6a Fixing disconnection bug. 2021-09-03 08:03:12 -07:00
Johann Hoffmann
935cc78bb4 [WIFI-3016] Add support for configuration through environment variables (#48)
* Add template and envsubst call in docker-entrypoint.sh

* Fix env variable name
2021-09-02 19:01:36 +02:00
jaspreetsachdev
417d94476b Updated to 2.1.0-RC2 2021-09-01 23:24:59 -04:00
Stephane Bourque
6318cd0c33 Merge pull request #49 from Telecominfraproject/master
Fix for disconnects
2021-09-01 19:31:37 -07:00
stephb9959
7892489e96 Addressing the failure to close a socket and duplicte logs messages. Docker problem. 2021-09-01 17:25:27 -07:00
stephb9959
24785e2f63 Addressing the failure to close a socket and duplicte logs messages. Docker problem. 2021-09-01 17:05:03 -07:00
stephb9959
52736f4a4c Addressing the failure to close a socket and duplicte logs messages. Docker problem. 2021-09-01 16:38:13 -07:00
stephb9959
e7334122b5 Addressing the failure to close a socket and duplicte logs messages. Docker problem. 2021-09-01 16:14:25 -07:00
stephb9959
33168f35d5 Addressing the failure to close a socket and duplicte logs messages. Docker problem. 2021-09-01 12:05:32 -07:00
oblom0v
cf69a47195 Change image tag to rc version 2021-08-30 18:53:41 +02:00
Johann Hoffmann
df71d60c2c Change ownership of uCentralGW root directory inside Dockerfile (#47) 2021-08-30 14:52:35 +02:00
Dmitry Dunaev
9eef500eb9 [WIFI-3202] Fix: helm path for fileuploader should be in persist dir 2021-08-30 12:11:40 +03:00
Stephane Bourque
8172b9c55e Merge pull request #46 from Telecominfraproject/dev-2.1
Fixing uploads dir
2021-08-26 09:25:06 -07:00
stephb9959
a35d3d73c2 Fixing DB setup 2021-08-26 09:22:21 -07:00
Stephane Bourque
5ae99dd04b Merge pull request #45 from Telecominfraproject/dev-2.1
Merging Dev 2.1 into master
2021-08-26 08:21:19 -07:00
Dmitry Dunaev
5f118b51d4 Merge pull request #42 from Telecominfraproject/feature/wifi-5150--external-db
[WIFI-3150] Add: external databases as optional dependencies for Helm chart
2021-08-24 14:21:48 +03:00
stephb9959
b7a762ad44 Fixing DB setup 2021-08-23 21:42:18 -07:00
stephb9959
a236bd7e4a Fixing DB setup 2021-08-22 08:30:28 -07:00
stephb9959
25af9bee46 Fixing wrong microservice type 2021-08-21 15:15:31 -07:00
stephb9959
897f5076b2 Fixing wrong microservice type 2021-08-21 14:40:03 -07:00
stephb9959
dd7a7bbc74 Moving to OpenWifi namespace 2021-08-21 11:42:36 -07:00
stephb9959
ef4af5b379 Adding example to OpenAPI 2021-08-19 07:45:15 -07:00
stephb9959
cfb562bb7a Fixing the eventqueue command 2021-08-19 07:42:15 -07:00
stephb9959
0675192f2c Microservice bus cleanup 2021-08-18 23:21:41 -07:00
stephb9959
27f0c5fe75 Microservice bus cleanup 2021-08-18 23:21:30 -07:00
stephb9959
5153f16d00 Microservice bus cleanup 2021-08-17 14:24:16 -07:00
stephb9959
deff8e5253 Microservice bus cleanup 2021-08-17 14:15:47 -07:00
stephb9959
152ba10a13 Fixing dashboard associations not being reset between runs. 2021-08-17 09:23:44 -07:00
Dmitry Dunaev
36cb68fef7 [WIFI-3150] Add: external databases as optional dependencies for Helm chart 2021-08-17 13:08:34 +03:00
stephb9959
7874cf3bd0 Adding authenticated web socket interface. 2021-08-13 11:15:42 -07:00
stephb9959
6ea7e93cb0 Adding authenticated web socket interface. 2021-08-13 09:25:33 -07:00
stephb9959
3520fb5ed4 Adding authenticated web socket interface. 2021-08-13 09:20:55 -07:00
stephb9959
c2266581b9 Adding authenticated web socket interface. 2021-08-13 09:02:43 -07:00
stephb9959
389de28cfb Adding authenticated web socket interface. 2021-08-13 08:58:15 -07:00
stephb9959
595dc5d42b Adding authenticated web socket interface. 2021-08-13 08:48:49 -07:00
stephb9959
c1d75c09be Adding authenticated web socket interface. 2021-08-13 08:41:35 -07:00
stephb9959
c0941512ae Adding authenticated web socket interface. 2021-08-13 08:39:38 -07:00
stephb9959
1f83f954dd Adding a command to test the WebSocket interface: wstest 2021-08-12 23:43:31 -07:00
stephb9959
3f7385d248 Fixing WebSocket interface for serial number cache. 2021-08-12 23:34:07 -07:00
stephb9959
25d13d3cb2 Fixing WebSocket interface for serial number cache. 2021-08-12 23:30:46 -07:00
stephb9959
5120b2cb64 Fixing WebSocket interface for serial number cache. 2021-08-12 23:26:09 -07:00
stephb9959
bca4f6cfcd Fixing WebSocket interface for serial number cache. 2021-08-12 22:47:56 -07:00
stephb9959
0b2ca909ed Adding WebSocket generic interface for SerialNumber Search for inventory. 2021-08-12 10:58:11 -07:00
stephb9959
3a5a5ae7bc Adding WebSocket generic interface for SerialNumber Search for inventory. 2021-08-12 10:12:41 -07:00
stephb9959
1d102cf1e9 Adding WebSocket generic interface for SerialNumber Search for inventory. 2021-08-12 10:04:45 -07:00
stephb9959
4644d231c4 Fixing no associations returned for not connected devices. 2021-08-11 15:56:03 -07:00
stephb9959
c50ed2f252 Fixing no associations returned for not connected devices. 2021-08-11 15:42:44 -07:00
stephb9959
7bba3da732 Fixing no associations returned for not connected devices. 2021-08-11 14:15:33 -07:00
stephb9959
6f9abd32e7 Fixing bug where we were still expecting a file after a trace that generated an error. 2021-08-11 09:45:36 -07:00
stephb9959
1c3e98619a Adding Associations in device status. 2021-08-11 08:45:29 -07:00
stephb9959
20fe93fcdc Fixing return values for delete 2021-08-11 07:54:07 -07:00
stephb9959
57a9114ac5 Fixing some minor corner cases error validation for REST calls. 2021-08-05 08:26:16 -07:00
stephb9959
4b2eecf8b0 Addressing Trace issues. 2021-08-04 20:04:38 -07:00
stephb9959
ed88cbfce6 Addressing Trace issues. 2021-08-04 19:52:00 -07:00
stephb9959
f7e70f5839 Addressing Trace issues. 2021-08-04 19:50:11 -07:00
stephb9959
d76ef5e1d0 Addressing Trace issues. 2021-08-04 19:40:47 -07:00
stephb9959
a4cf28c858 Addressing Trace issues. 2021-08-04 11:40:13 -07:00
stephb9959
4f5e21d658 Merge remote-tracking branch 'origin/master' 2021-08-04 11:39:32 -07:00
stephb9959
bd5f7cd373 Addressing Trace issues. 2021-08-04 11:39:24 -07:00
Dmitry Dunaev
d74795fd96 Merge pull request #41 from Telecominfraproject/fix/k8s-security-context
Fix: add securityContext to make mounted volumes accessible by the application user
2021-08-04 18:12:40 +03:00
stephb9959
3fe17e58de Addressing Trace issues. 2021-08-03 23:34:14 -07:00
stephb9959
adba0fbe22 Addressing Trace issues. 2021-08-03 23:22:05 -07:00
stephb9959
64a99e5079 Addressing Trace issues. 2021-08-03 23:12:42 -07:00
stephb9959
34def33f69 Addressing Trace issues. 2021-08-03 23:04:29 -07:00
stephb9959
de34051cd4 Addressing Trace issues. 2021-08-03 22:56:42 -07:00
stephb9959
346d845ee9 Addressing Trace issues. 2021-08-03 22:36:26 -07:00
stephb9959
83ada431de Fixing DB Range settings 2021-08-03 15:38:53 -07:00
stephb9959
2563d7e9b3 Fixing DB Range settings 2021-08-03 15:35:27 -07:00
stephb9959
1f0f3e8f38 Fixing DB Range settings 2021-08-03 14:57:28 -07:00
stephb9959
f13ecd0d1c Fixing DB Range settings 2021-08-03 14:54:37 -07:00
stephb9959
54f35de99f Fixing DB Range settings 2021-08-03 14:53:52 -07:00
stephb9959
f7b6c6f90f Fixing DB Range settings 2021-08-03 14:16:41 -07:00
stephb9959
f003149b8d Fixing DB Range settings 2021-08-03 14:07:11 -07:00
stephb9959
4f9e7c9677 Fixing DB Range settings 2021-08-03 14:05:08 -07:00
stephb9959
14d7aad56c Fixing DB Range settings 2021-08-03 14:00:08 -07:00
stephb9959
aa4d2ae764 Fixing DB Range settings 2021-08-03 12:35:22 -07:00
stephb9959
4e60b248ca Fixing DB Range settings 2021-08-03 12:13:44 -07:00
stephb9959
685f9024d7 Fixing DB Range settings 2021-08-03 11:47:15 -07:00
stephb9959
104d429b69 Fixing DB Range settings 2021-08-03 11:30:51 -07:00
stephb9959
8cf5672a73 Improving OpenSSL support. 2021-08-03 10:48:55 -07:00
stephb9959
186f7624a6 Improving OpenSSL support. 2021-08-03 10:28:42 -07:00
stephb9959
8986cde273 Improving OpenSSL support. 2021-08-03 10:11:02 -07:00
stephb9959
0abc3de4cd Improving OpenSSL support. 2021-08-03 10:07:49 -07:00
stephb9959
d219fab455 Improving OpenSSL support. 2021-08-03 09:54:45 -07:00
stephb9959
3b3e79ac14 Improving OpenSSL support. 2021-08-03 09:39:30 -07:00
stephb9959
2ff32a69e6 Improving OpenSSL support. 2021-08-03 09:32:18 -07:00
stephb9959
2b66f15bda Improving OpenSSL support. 2021-08-03 09:28:14 -07:00
stephb9959
508ff00663 Improving OpenSSL support. 2021-08-03 09:21:32 -07:00
stephb9959
d0fc391cde Improving OpenSSL support. 2021-08-03 09:14:29 -07:00
Dmitry Dunaev
77a031eaa3 [WIFI-3332] Fix: add securityContext to make mounted volumes accessible by the application user 2021-08-03 18:47:59 +03:00
stephb9959
a6f6421992 Improving OpenSSL support. 2021-08-03 08:03:14 -07:00
stephb9959
fdf497397e Improving OpenSSL support. 2021-08-03 07:54:43 -07:00
stephb9959
ab605655e1 Improving OpenSSL support. 2021-08-03 07:47:28 -07:00
stephb9959
422574ed65 Improving OpenSSL support. 2021-08-03 07:38:12 -07:00
stephb9959
34f9b6f761 Improving OpenSSL support. 2021-08-03 07:33:31 -07:00
stephb9959
27e8178444 Improving OpenSSL support. 2021-08-03 07:29:08 -07:00
stephb9959
ba6796cd16 Improving OpenSSL support. 2021-08-03 07:25:13 -07:00
stephb9959
816d5da3ba Improving OpenSSL support. 2021-08-03 07:17:47 -07:00
stephb9959
c9c3c16e0b Improving OpenSSL support. 2021-08-02 23:00:13 -07:00
stephb9959
35dc055c40 Improving OpenSSL support. 2021-08-02 22:57:48 -07:00
stephb9959
6760ca1da1 Improving OpenSSL support. 2021-08-02 22:47:58 -07:00
stephb9959
36e6ee3ac4 Improving OpenSSL support. 2021-08-02 22:18:09 -07:00
stephb9959
362d97de1f Improving OpenSSL support. 2021-08-02 22:15:23 -07:00
stephb9959
530a2bb772 Improving OpenSSL support. 2021-08-02 22:12:15 -07:00
stephb9959
b333af3465 Improving OpenSSL support. 2021-08-02 22:10:46 -07:00
stephb9959
1b405987bf Improving OpenSSL support. 2021-08-02 22:07:29 -07:00
stephb9959
6dd52f86b9 Improving OpenSSL support. 2021-08-02 21:12:38 -07:00
stephb9959
76081e82af Improving OpenSSL support. 2021-08-02 20:54:47 -07:00
stephb9959
ebe2d16a87 Improving OpenSSL support. 2021-08-02 15:40:34 -07:00
stephb9959
60e4ced29a Improving OpenSSL support. 2021-08-02 15:33:24 -07:00
stephb9959
5683054349 Improving OpenSSL support. 2021-08-02 15:29:44 -07:00
stephb9959
210a96c143 Improving OpenSSL support. 2021-08-02 15:00:54 -07:00
stephb9959
92e108aa6b Improving OpenSSL support. 2021-08-02 14:54:49 -07:00
stephb9959
691b82589d Improving OpenSSL support. 2021-08-02 14:54:01 -07:00
stephb9959
4b471af065 Improving OpenSSL support. 2021-08-02 14:51:15 -07:00
stephb9959
3c556da991 Improving OpenSSL support. 2021-08-02 14:48:04 -07:00
stephb9959
9ddd371c86 Improving OpenSSL support. 2021-08-02 14:42:52 -07:00
stephb9959
5391468ea2 Improving OpenSSL support. 2021-08-02 14:37:36 -07:00
stephb9959
8daffc2ccf Improving OpenSSL support. 2021-08-02 14:36:15 -07:00
stephb9959
f58c204f51 Improving OpenSSL support. 2021-08-02 14:28:13 -07:00
stephb9959
5e857d6019 Improving OpenSSL support. 2021-08-02 14:16:47 -07:00
stephb9959
a7fe50f956 Improving OpenSSL support. 2021-08-02 14:15:07 -07:00
stephb9959
40239079a4 Improving OpenSSL support. 2021-08-02 10:09:42 -07:00
stephb9959
27c4602fca Improving OpenSSL support. 2021-08-02 09:52:38 -07:00
stephb9959
c107c6da93 Improving OpenSSL support. 2021-08-02 09:50:29 -07:00
stephb9959
f67995b4a9 Improving OpenSSL support. 2021-08-02 09:49:19 -07:00
stephb9959
851fdb1f1d Improving OpenSSL support. 2021-08-02 09:43:17 -07:00
stephb9959
8f52dc57ba Improving OpenSSL support. 2021-08-02 09:39:52 -07:00
stephb9959
427ee37b16 Improving OpenSSL support. 2021-08-02 09:37:29 -07:00
stephb9959
fc153f7fc9 Merge remote-tracking branch 'origin/master' 2021-08-02 09:31:04 -07:00
stephb9959
5c9f571565 Improving OpenSSL support. 2021-08-02 09:30:52 -07:00
stephb9959
ab3905f6d8 Improving OpenSSL support. 2021-08-02 09:29:56 -07:00
Dmitry Dunaev
9cee7d4588 [WIFI-3286] Fix: set default logging to stdout 2021-08-02 15:32:43 +03:00
stephb9959
dd95731b22 Improving OpenSSL support. 2021-08-01 22:43:01 -07:00
stephb9959
101384d595 Improving OpenSSL support. 2021-08-01 22:41:21 -07:00
stephb9959
77297d5a3e Improving OpenSSL support. 2021-08-01 22:36:53 -07:00
stephb9959
8b3c3a50ed Improving OpenSSL support. 2021-08-01 22:29:28 -07:00
stephb9959
4b5128e41d Trying to improve connection speed. 2021-07-31 20:38:33 -07:00
stephb9959
b11d713e5b Adding associations in the dashboard 2021-07-30 22:17:18 -07:00
stephb9959
143c4078d4 Fixing dashboard. 2021-07-29 22:24:50 -07:00
stephb9959
b6babaa2f8 Fixing dashboard. 2021-07-29 16:28:47 -07:00
stephb9959
57f0425bc0 Chaning mutex types. 2021-07-29 14:29:05 -07:00
stephb9959
c28159ebe7 Chaning mutex types. 2021-07-29 14:18:37 -07:00
stephb9959
2a0be33c23 Chaning mutex types. 2021-07-29 13:24:46 -07:00
stephb9959
f1c77c0a63 Chaning mutex types. 2021-07-29 11:47:59 -07:00
stephb9959
64fd80f489 Changing version 2021-07-28 11:08:11 -07:00
113 changed files with 1966 additions and 1225 deletions

3
.gitignore vendored
View File

@@ -25,3 +25,6 @@ _deps
test_scripts/curl/token.json
.vscode/c_cpp_properties.json
test_scripts/curl/result.json
*.swp
helm/charts/*
!helm/charts/.gitkeep

View File

@@ -1,5 +1,5 @@
cmake_minimum_required(VERSION 3.13)
project(ucentralgw VERSION 2.0.0)
project(ucentralgw VERSION 2.1.0)
set(CMAKE_CXX_STANDARD 17)
@@ -73,21 +73,29 @@ add_executable( ucentralgw
src/RESTAPI_command.cpp src/RESTAPI_command.h
src/FileUploader.cpp src/FileUploader.h
src/RESTAPI_file.cpp src/RESTAPI_file.h
src/CommandChannel.cpp src/CommandChannel.h
src/RESTAPI_system_command.cpp src/RESTAPI_system_command.h
src/RESTAPI_BlackList.cpp src/RESTAPI_BlackList.h
src/Utils.h src/Utils.cpp src/storage_blacklist.cpp
src/storage_command.cpp src/storage_healthcheck.cpp src/storage_statistics.cpp src/storage_logs.cpp
src/storage_device.cpp src/storage_capabilities.cpp src/storage_defconfig.cpp src/storage_sqlite.cpp
src/storage_mysql.cpp src/storage_pgql.cpp src/storage_tables.cpp
src/storage_device.cpp src/storage_capabilities.cpp src/storage_defconfig.cpp
src/storage_tables.cpp
src/storage_setup.cpp
src/StateProcessor.cpp src/StateProcessor.h
src/storage_lifetime_stats.cpp src/uCentralProtocol.h src/RESTAPI_protocol.h
src/ALBHealthCheckServer.h src/Kafka_topics.h src/uCentralTypes.h
src/ALBHealthCheckServer.h src/Kafka_topics.h
src/OUIServer.cpp src/OUIServer.h
src/RESTAPI_ouis.cpp src/RESTAPI_ouis.h
src/MicroService.cpp src/MicroService.h
src/RESTAPI_RPC.cpp src/RESTAPI_RPC.h src/AuthClient.cpp src/AuthClient.h src/OpenAPIRequest.cpp src/OpenAPIRequest.h
src/RESTAPI_utils.h src/RESTAPI_utils.cpp src/StorageArchiver.cpp src/StorageArchiver.h src/Dashboard.cpp src/Dashboard.h src/RESTAPI_deviceDashboardHandler.cpp src/RESTAPI_deviceDashboardHandler.h)
src/RESTAPI_RPC.cpp src/RESTAPI_RPC.h
src/AuthClient.cpp src/AuthClient.h
src/OpenAPIRequest.cpp src/OpenAPIRequest.h
src/RESTAPI_utils.h src/RESTAPI_utils.cpp
src/StorageArchiver.cpp src/StorageArchiver.h
src/Dashboard.cpp src/Dashboard.h
src/RESTAPI_deviceDashboardHandler.cpp src/RESTAPI_deviceDashboardHandler.h
src/SerialNumberCache.cpp src/SerialNumberCache.h
src/RESTAPI_webSocketServer.cpp src/RESTAPI_webSocketServer.h
src/OpenWifiTypes.h)
if(NOT SMALL_BUILD)
target_sources(ucentralgw PUBLIC src/KafkaManager.cpp src/KafkaManager.h)

View File

@@ -46,12 +46,15 @@ RUN addgroup -S "$UCENTRALGW_USER" && \
adduser -S -G "$UCENTRALGW_USER" "$UCENTRALGW_USER"
RUN mkdir /ucentral
RUN mkdir -p "$UCENTRALGW_ROOT" "$UCENTRALGW_CONFIG"
RUN apk add --update --no-cache librdkafka mariadb-connector-c libpq unixodbc su-exec
RUN mkdir -p "$UCENTRALGW_ROOT" "$UCENTRALGW_CONFIG" && \
chown "$UCENTRALGW_USER": "$UCENTRALGW_ROOT" "$UCENTRALGW_CONFIG"
RUN apk add --update --no-cache librdkafka mariadb-connector-c libpq unixodbc su-exec gettext
COPY --from=builder /ucentralgw/cmake-build/ucentralgw /ucentral/ucentralgw
COPY --from=builder /cppkafka/cmake-build/src/lib/* /lib/
COPY --from=builder /poco/cmake-build/lib/* /lib/
COPY ucentralgw.properties.tmpl ${UCENTRALGW_CONFIG}/
COPY docker-entrypoint.sh /
EXPOSE 15002 16002 16003 17002 16102

View File

@@ -26,9 +26,9 @@ Poco may take several minutes depending on the platform you are building on.
### Ubuntu
These instructions have proven to work on Ubuntu 20.4.
```
sudo apt install git cmake g++ libssl-dev libmariabd-dev unixodbc-dev
sudo apt install git cmake g++ libssl-dev libmariadb-dev unixodbc-dev
sudo apt install libpq-dev libaprutil1-dev apache2-dev libboost-all-dev
sudo apt install librdkafka-dev liblua5.3-dev
sudo apt install librdkafka-dev liblua5.3-dev libmysqlclient-dev
git clone https://github.com/stephb9959/poco
cd poco
@@ -153,8 +153,8 @@ cmake -DSMALL_BUILD=1 ..
make
```
### After the build step is completed
Once your build is done. You can remove the Poco source as it is no longer needed.
### After completing the build
After completing the build, you can remove the Poco source as it is no longer needed.
#### Expected directory layout
From the directory where your cloned source is, you will need to create the `certs`, `logs`, and `uploads` directories.
@@ -220,13 +220,13 @@ in your browner
#### Configuration
The configuration for this service is kept in a properties file. This file is called `ucentralgw.properties` and you can
see the latest version [here](https://github.com/Telecominfraproject/wlan-cloud-ucentralgw/blob/main/ucentralgw.properties). The file will be loaded from
the directory set by the environment variable `UCENTRAL_CONFIG`. To use environment variables in the configuration,
the directory set by the environment variable `UCENTRALGW_CONFIG`. To use environment variables in the configuration,
you must use `$<varname>`. Only `path names` support the use of environment variables. The sample configuration requires very
little changes if you keep the suggested directory structure. For the sample configuration to work, you need to define 2
environment variables.
```
export UCENTRAL_ROOT=`pwd`
export UCENTRAL_CONFIG=`pwd`
export UCENTRALGW_ROOT=`pwd`
export UCENTRALGW_CONFIG=`pwd`
```
If you current working directory is the root of the project, this will set the variables properly. Otherwise, you can set the variables
to point to wherever is necessary.
@@ -234,7 +234,7 @@ to point to wherever is necessary.
##### Important config entries
###### This is the logging directory
```
logging.channels.c2.path = $UCENTRAL_ROOT/logs/sample.log
logging.channels.c2.path = $UCENTRALGW_ROOT/logs/sample.log
```
###### This is the type of storage in use
@@ -255,11 +255,11 @@ ucentral.devicetypes.2 = IOT:esp32
```asm
ucentral.restapi.host.0.backlog = 100
ucentral.restapi.host.0.security = relaxed
ucentral.restapi.host.0.rootca = $UCENTRAL_ROOT/certs/restapi-ca.pem
ucentral.restapi.host.0.rootca = $UCENTRALGW_ROOT/certs/restapi-ca.pem
ucentral.restapi.host.0.address = *
ucentral.restapi.host.0.port = 16002
ucentral.restapi.host.0.cert = $UCENTRAL_ROOT/certs/restapi-cert.pem
ucentral.restapi.host.0.key = $UCENTRAL_ROOT/certs/restapi-key.pem
ucentral.restapi.host.0.cert = $UCENTRALGW_ROOT/certs/restapi-cert.pem
ucentral.restapi.host.0.key = $UCENTRALGW_ROOT/certs/restapi-key.pem
ucentral.restapi.host.0.key.password = mypassword
```
@@ -309,12 +309,12 @@ You will need to get the `cert.pem` and `key.pem` from Digicert. The rest is her
```asm
ucentral.websocket.host.0.backlog = 500
ucentral.websocket.host.0.rootca = $UCENTRAL_ROOT/certs/root.pem
ucentral.websocket.host.0.issuer = $UCENTRAL_ROOT/certs/issuer.pem
ucentral.websocket.host.0.cert = $UCENTRAL_ROOT/certs/websocket-cert.pem
ucentral.websocket.host.0.key = $UCENTRAL_ROOT/certs/websocket-key.pem
ucentral.websocket.host.0.clientcas = $UCENTRAL_ROOT/certs/clientcas.pem
ucentral.websocket.host.0.cas = $UCENTRAL_ROOT/certs/cas
ucentral.websocket.host.0.rootca = $UCENTRALGW_ROOT/certs/root.pem
ucentral.websocket.host.0.issuer = $UCENTRALGW_ROOT/certs/issuer.pem
ucentral.websocket.host.0.cert = $UCENTRALGW_ROOT/certs/websocket-cert.pem
ucentral.websocket.host.0.key = $UCENTRALGW_ROOT/certs/websocket-key.pem
ucentral.websocket.host.0.clientcas = $UCENTRALGW_ROOT/certs/clientcas.pem
ucentral.websocket.host.0.cas = $UCENTRALGW_ROOT/certs/cas
ucentral.websocket.host.0.address = *
ucentral.websocket.host.0.port = 15002
ucentral.websocket.host.0.security = strict
@@ -325,15 +325,15 @@ ucentral.websocket.maxreactors = 20
###### This is the end point for the devices when uploading files
```asm
ucentral.fileuploader.host.0.backlog = 100
ucentral.fileuploader.host.0.rootca = $UCENTRAL_ROOT/certs/restapi-ca.pem
ucentral.fileuploader.host.0.rootca = $UCENTRALGW_ROOT/certs/restapi-ca.pem
ucentral.fileuploader.host.0.security = relaxed
ucentral.fileuploader.host.0.address = *
ucentral.fileuploader.host.0.name = 192.168.1.176
ucentral.fileuploader.host.0.port = 16003
ucentral.fileuploader.host.0.cert = $UCENTRAL_ROOT/certs/restapi-cert.pem
ucentral.fileuploader.host.0.key = $UCENTRAL_ROOT/certs/restapi-key.pem
ucentral.fileuploader.host.0.cert = $UCENTRALGW_ROOT/certs/restapi-cert.pem
ucentral.fileuploader.host.0.key = $UCENTRALGW_ROOT/certs/restapi-key.pem
ucentral.fileuploader.host.0.key.password = mypassword
ucentral.fileuploader.path = $UCENTRAL_ROOT/uploads
ucentral.fileuploader.path = $UCENTRALGW_ROOT/uploads
ucentral.fileuploader.maxsize = 10000
```
@@ -369,7 +369,7 @@ can be any of the keys you are already using. You must keep that keep secret and
this is the entry
```asm
ucentral.service.key = $UCENTRAL_ROOT/certs/websocket-key.pem
ucentral.service.key = $UCENTRALGW_ROOT/certs/websocket-key.pem
```
#### Command line options
@@ -391,7 +391,7 @@ A uCentral gateway implementation for TIP.
```
##### file
This allows you to point to another file without specifying the UCENTRAL_CONFIG variable. The file name must end in `.properties`.
This allows you to point to another file without specifying the UCENTRALGW_CONFIG variable. The file name must end in `.properties`.
##### daemon
Run this as a UNIX service
##### pidfile
@@ -452,7 +452,7 @@ docker run -d -p 15002:15002 \
--init \
--volume="$PWD:/ucentral-data" \
-e UCENTRAL_ROOT="/ucentral-data" \
-e UCENTRAL_CONFIG="/ucentral-data" \
-e UCENTRALGW_CONFIG="/ucentral-data" \
--name="ucentralgw" $DOCKER_NAME
```
@@ -493,7 +493,7 @@ Please refer to the `certs` directory from the sections above.
The configuration for this service is kept in a properties file. Currently, this configuration file must be kept in the
current directory of uCentral or one level up. This file is called `ucentralgw.properties` and you can see the latest version
[here](https://github.com/Telecominfraproject/wlan-cloud-ucentralgw/blob/main/ucentralgw.properties). The file will be loaded from
the directory set by the environment variable `UCENTRAL_CONFIG`. To use environment variables in the configuration,
the directory set by the environment variable `UCENTRALGW_CONFIG`. To use environment variables in the configuration,
you must use `$<varname>`. The path for the logs for the service must exist prior to starting the
service. The path is defined under `logging.channels.c2.path`. Only `path names` support the use of
environment variables. Here is a sample configuration:

2
build
View File

@@ -1 +1 @@
1
48

View File

@@ -1,6 +1,60 @@
#!/bin/sh
set -e
if [[ "$TEMPLATE_CONFIG" = 'true' && ! -f "$UCENTRALGW_CONFIG"/ucentralgw.properties ]]; then
WEBSOCKET_HOST_ROOTCA=${WEBSOCKET_HOST_ROOTCA:-"\$UCENTRALGW_ROOT/certs/root.pem"} \
WEBSOCKET_HOST_ISSUER=${WEBSOCKET_HOST_ISSUER:-"\$UCENTRALGW_ROOT/certs/issuer.pem"} \
WEBSOCKET_HOST_CERT=${WEBSOCKET_HOST_CERT:-"\$UCENTRALGW_ROOT/certs/websocket-cert.pem"} \
WEBSOCKET_HOST_KEY=${WEBSOCKET_HOST_KEY:-"\$UCENTRALGW_ROOT/certs/websocket-key.pem"} \
WEBSOCKET_HOST_CLIENTCAS=${WEBSOCKET_HOST_CLIENTCAS:-"\$UCENTRALGW_ROOT/certs/clientcas.pem"} \
WEBSOCKET_HOST_CAS=${WEBSOCKET_HOST_CAS:-"\$UCENTRALGW_ROOT/certs/cas"} \
WEBSOCKET_HOST_PORT=${WEBSOCKET_HOST_PORT:-"15002"} \
WEBSOCKET_HOST_KEY_PASSWORD=${WEBSOCKET_HOST_KEY_PASSWORD:-"mypassword"} \
RESTAPI_HOST_ROOTCA=${RESTAPI_HOST_ROOTCA:-"\$UCENTRALGW_ROOT/certs/restapi-ca.pem"} \
RESTAPI_HOST_PORT=${RESTAPI_HOST_PORT:-"16002"} \
RESTAPI_HOST_CERT=${RESTAPI_HOST_CERT:-"\$UCENTRALGW_ROOT/certs/restapi-cert.pem"} \
RESTAPI_HOST_KEY=${RESTAPI_HOST_KEY:-"\$UCENTRALGW_ROOT/certs/restapi-key.pem"} \
RESTAPI_HOST_KEY_PASSWORD=${RESTAPI_HOST_KEY_PASSWORD:-"mypassword"} \
INTERNAL_RESTAPI_HOST_ROOTCA=${INTERNAL_RESTAPI_HOST_ROOTCA:-"\$UCENTRALGW_ROOT/certs/restapi-ca.pem"} \
INTERNAL_RESTAPI_HOST_PORT=${INTERNAL_RESTAPI_HOST_PORT:-"17002"} \
INTERNAL_RESTAPI_HOST_CERT=${INTERNAL_RESTAPI_HOST_CERT:-"\$UCENTRALGW_ROOT/certs/restapi-cert.pem"} \
INTERNAL_RESTAPI_HOST_KEY=${INTERNAL_RESTAPI_HOST_KEY:-"\$UCENTRALGW_ROOT/certs/restapi-key.pem"} \
INTERNAL_RESTAPI_HOST_KEY_PASSWORD=${INTERNAL_RESTAPI_HOST_KEY_PASSWORD:-"mypassword"} \
FILEUPLOADER_HOST_ROOTCA=${FILEUPLOADER_HOST_ROOTCA:-"\$UCENTRALGW_ROOT/certs/restapi-ca.pem"} \
FILEUPLOADER_HOST_NAME=${FILEUPLOADER_HOST_NAME:-"localhost"} \
FILEUPLOADER_HOST_PORT=${FILEUPLOADER_HOST_PORT:-"16003"} \
FILEUPLOADER_HOST_CERT=${FILEUPLOADER_HOST_CERT:-"\$UCENTRALGW_ROOT/certs/restapi-cert.pem"} \
FILEUPLOADER_HOST_KEY=${FILEUPLOADER_HOST_KEY:-"\$UCENTRALGW_ROOT/certs/restapi-key.pem"} \
FILEUPLOADER_HOST_KEY_PASSWORD=${FILEUPLOADER_HOST_KEY_PASSWORD:-"mypassword"} \
FILEUPLOADER_PATH=${FILEUPLOADER_PATH:-"\$UCENTRALGW_ROOT/uploads"} \
SERVICE_KEY=${SERVICE_KEY:-"\$UCENTRALGW_ROOT/certs/restapi-key.pem"} \
SERVICE_KEY_PASSWORD=${SERVICE_KEY_PASSWORD:-"mypassword"} \
SYSTEM_DATA=${SYSTEM_DATA:-"\$UCENTRALGW_ROOT/data"} \
SYSTEM_URI_PRIVATE=${SYSTEM_URI_PRIVATE:-"https://localhost:17002"} \
SYSTEM_URI_PUBLIC=${SYSTEM_URI_PUBLIC:-"https://localhost:16002"} \
SYSTEM_URI_UI=${SYSTEM_URI_UI:-"http://localhost"} \
RTTY_ENABLED=${RTTY_ENABLED:-"false"} \
RTTY_SERVER=${RTTY_SERVER:-"localhost"} \
RTTY_PORT=${RTTY_PORT:-"5912"} \
RTTY_TOKEN=${RTTY_TOKEN:-"96181c567b4d0d98c50f127230068fa8"} \
RTTY_TIMEOUT=${RTTY_TIMEOUT:-"60"} \
RTTY_VIEWPORT=${RTTY_VIEWPORT:-"5913"} \
KAFKA_ENABLE=${KAFKA_ENABLE:-"true"} \
KAFKA_BROKERLIST=${KAFKA_BROKERLIST:-"localhost:9092"} \
STORAGE_TYPE=${STORAGE_TYPE:-"sqlite"} \
STORAGE_TYPE_POSTGRESQL_HOST=${STORAGE_TYPE_POSTGRESQL_HOST:-"localhost"} \
STORAGE_TYPE_POSTGRESQL_USERNAME=${STORAGE_TYPE_POSTGRESQL_USERNAME:-"ucentralgw"} \
STORAGE_TYPE_POSTGRESQL_PASSWORD=${STORAGE_TYPE_POSTGRESQL_PASSWORD:-"ucentralgw"} \
STORAGE_TYPE_POSTGRESQL_DATABASE=${STORAGE_TYPE_POSTGRESQL_DATABASE:-"ucentralgw"} \
STORAGE_TYPE_POSTGRESQL_PORT=${STORAGE_TYPE_POSTGRESQL_PORT:-"5432"} \
STORAGE_TYPE_MYSQL_HOST=${STORAGE_TYPE_MYSQL_HOST:-"localhost"} \
STORAGE_TYPE_MYSQL_USERNAME=${STORAGE_TYPE_MYSQL_USERNAME:-"ucentralgw"} \
STORAGE_TYPE_MYSQL_PASSWORD=${STORAGE_TYPE_MYSQL_PASSWORD:-"ucentralgw"} \
STORAGE_TYPE_MYSQL_DATABASE=${STORAGE_TYPE_MYSQL_DATABASE:-"ucentralgw"} \
STORAGE_TYPE_MYSQL_PORT=${STORAGE_TYPE_MYSQL_PORT:-"3306"} \
envsubst < $UCENTRALGW_CONFIG/ucentralgw.properties.tmpl > $UCENTRALGW_CONFIG/ucentralgw.properties
fi
if [ "$1" = '/ucentral/ucentralgw' -a "$(id -u)" = '0' ]; then
if [ "$RUN_CHOWN" = 'true' ]; then
chown -R "$UCENTRALGW_USER": "$UCENTRALGW_ROOT" "$UCENTRALGW_CONFIG"

View File

@@ -26,7 +26,7 @@ then
exit 1
fi
if [[ ! -f ucentral.properties ]]
if [[ ! -f ucentralgw.properties ]]
then
echo "Configuration file ucentral.properties is missing in the current directory"
exit 2
@@ -37,7 +37,7 @@ docker run -d -p 15002:15002 \
-p 16003:16003 \
--init \
--volume="$PWD:/ucentral-data" \
-e UCENTRAL_ROOT="/ucentral-data" \
-e UCENTRAL_CONFIG="/ucentral-data" \
-e UCENTRALGW_ROOT="/ucentral-data" \
-e UCENTRALGW_CONFIG="/ucentral-data" \
--name="ucentralgw" $DOCKER_NAME

0
helm/.gitkeep Normal file
View File

12
helm/Chart.lock Normal file
View File

@@ -0,0 +1,12 @@
dependencies:
- name: postgresql
repository: https://charts.bitnami.com/bitnami
version: 10.9.2
- name: mysql
repository: https://charts.bitnami.com/bitnami
version: 8.8.3
- name: mariadb
repository: https://charts.bitnami.com/bitnami
version: 9.4.2
digest: sha256:1fdae7cbea906e41dccd8618ff9e2c68d0c684724ae27c79a12bb6089968df5c
generated: "2021-08-17T12:18:40.341427893+03:00"

View File

@@ -1,5 +1,18 @@
apiVersion: v1
apiVersion: v2
appVersion: "1.0"
description: A Helm chart for Kubernetes
name: ucentralgw
version: 0.1.0
dependencies:
- name: postgresql
repository: https://charts.bitnami.com/bitnami
version: 10.9.2
condition: postgresql.enabled
- name: mysql
repository: https://charts.bitnami.com/bitnami
version: 8.8.3
condition: mysql.enabled
- name: mariadb
repository: https://charts.bitnami.com/bitnami
version: 9.4.2
condition: mariadb.enabled

View File

@@ -83,6 +83,11 @@ spec:
{{- toYaml . | nindent 12 }}
{{- end }}
{{- with .Values.securityContext }}
securityContext:
{{- toYaml . | nindent 8 }}
{{- end }}
imagePullSecrets:
{{- range $image, $imageValue := .Values.images }}
{{- if $imageValue.regcred }}

View File

@@ -8,7 +8,7 @@ fullnameOverride: ""
images:
ucentralgw:
repository: tip-tip-wlan-cloud-ucentral.jfrog.io/ucentralgw
tag: master
tag: v2.1.0-RC3
pullPolicy: Always
# regcred:
# registry: tip-tip-wlan-cloud-ucentral.jfrog.io
@@ -109,6 +109,9 @@ resources: {}
# cpu: 100m
# memory: 128Mi
securityContext:
fsGroup: 101
nodeSelector: {}
tolerations: []
@@ -168,7 +171,7 @@ configProperties:
ucentral.fileuploader.host.0.port: 16003
ucentral.fileuploader.host.0.cert: $UCENTRALGW_ROOT/certs/restapi-cert.pem
ucentral.fileuploader.host.0.key: $UCENTRALGW_ROOT/certs/restapi-key.pem
ucentral.fileuploader.path: $UCENTRALGW_ROOT/uploads
ucentral.fileuploader.path: $UCENTRALGW_ROOT/persist/uploads
ucentral.fileuploader.maxsize: 10000
# Auto provisioning
ucentral.autoprovisioning: "true"
@@ -227,7 +230,7 @@ configProperties:
ucentral.system.commandchannel: /tmp/app_ucentralgw
# Logging
logging.formatters.f1.class: PatternFormatter
logging.formatters.f1.pattern: "%s: [%p] %t"
logging.formatters.f1.pattern: "%Y-%m-%d %H:%M:%S %s: [%p] %t"
logging.formatters.f1.times: UTC
logging.channels.c1.class: ConsoleChannel
logging.channels.c1.formatter: f1
@@ -240,7 +243,7 @@ configProperties:
logging.channels.c2.purgeCount: 20
logging.channels.c3.class: ConsoleChannel
logging.channels.c3.pattern: "%s: [%p] %t"
logging.loggers.root.channel: c2
logging.loggers.root.channel: c1
logging.loggers.root.level: debug
# -> Secret part
@@ -425,3 +428,64 @@ certsCAs:
L+/DtiR5fDVMNdBSGU89UNTi0wHY9+RFuNlIuvZC+x/swF0V9R5mN+ywquTPtDLA
5IOM7ItsRmen6u3qu+JXros54e4juQ==
-----END CERTIFICATE-----
# PostgreSQL (https://github.com/bitnami/charts/tree/master/bitnami/postgresql)
postgresql:
enabled: false
image:
registry: docker.io
repository: bitnami/postgresql
tag: 11.13.0-debian-10-r0
postgresqlPostgresPassword: ""
postgresqlUsername: postgres
postgresqlPassword: ""
postgresqlDatabase: ""
persistence:
enabled: true
storageClass: ""
size: 8Gi
# MySQL (https://github.com/bitnami/charts/tree/master/bitnami/mysql)
mysql:
enabled: false
image:
registry: docker.io
repository: bitnami/mysql
tag: 8.0.26-debian-10-r10
auth:
rootPassword: ""
database: my_database
username: ""
password: ""
primary:
persistence:
enabled: true
storageClass: ""
size: 8Gi
# MariaDB (https://github.com/bitnami/charts/tree/master/bitnami/mariadb)
mariadb:
enabled: false
image:
registry: docker.io
repository: bitnami/mariadb
tag: 10.5.12-debian-10-r0
auth:
rootPassword: ""
database: my_database
username: ""
password: ""
primary:
persistence:
enabled: true
storageClass: ""
size: 8Gi

View File

@@ -180,6 +180,12 @@ components:
rxBytes:
type: integer
format: int64
associations_2G:
type: integer
format: int64
associations_5G:
type: integer
format: int64
devicePassword:
type: string
lastContact:
@@ -248,6 +254,12 @@ components:
format: int64
firmware:
type: string
associations_2G:
type: integer
format: int64
associations_5G:
type: integer
format: int64
verifiedCertificate:
type: string
enum:
@@ -584,6 +596,12 @@ components:
DeviceDashboard:
type: object
properties:
snapshot:
type: integer
format: int64
numberOfDevices:
type: integer
format: int64
commands:
$ref: '#/components/schemas/TagIntPairList'
upTimes:
@@ -610,6 +628,8 @@ components:
$ref: '#/components/schemas/TagIntPairList'
lastContact:
$ref: '#/components/schemas/TagIntPairList'
associations:
$ref: '#/components/schemas/TagIntPairList'
#########################################################################################
##
@@ -852,6 +872,7 @@ paths:
name: countOnly
schema:
type: boolean
example: countOnly=true
- in: query
description: Return extra information with the device information
name: deviceWithStatus
@@ -950,7 +971,7 @@ paths:
format: int64
responses:
200:
204:
description: Successfully deleted commands for the device.
content:
application/json:
@@ -1001,7 +1022,7 @@ paths:
format: uuid
required: true
responses:
200:
204:
description: Delete command success
content:
application/json:
@@ -1096,7 +1117,7 @@ paths:
type: string
required: true
responses:
200:
204:
$ref: '#/components/responses/Success'
403:
$ref: '#/components/responses/Unauthorized'
@@ -1224,7 +1245,7 @@ paths:
type: string
required: true
responses:
200:
204:
$ref: '#/components/responses/Success'
403:
$ref: '#/components/responses/Unauthorized'
@@ -1319,7 +1340,7 @@ paths:
format: int64
responses:
200:
204:
description: Successfully deleted logs for the device.
content:
application/json:
@@ -1416,7 +1437,7 @@ paths:
required: false
responses:
200:
204:
description: Successfully deleted health checks for the device.
content:
application/json:
@@ -1463,7 +1484,7 @@ paths:
type: string
required: true
responses:
200:
204:
description: List of logs for this device
content:
application/json:
@@ -1568,7 +1589,7 @@ paths:
required: false
responses:
200:
204:
description: Array of statistics for this device
content:
application/json:
@@ -1837,7 +1858,7 @@ paths:
404:
$ref: '#/components/responses/NotFound'
/device/{serialNumber}/eventrequest:
/device/{serialNumber}/eventqueue:
post:
tags:
- Commands
@@ -1956,7 +1977,7 @@ paths:
type: string
required: true
responses:
200:
204:
$ref: '#/components/responses/Success'
403:
$ref: '#/components/responses/Unauthorized'
@@ -2033,7 +2054,7 @@ paths:
type: string
required: true
responses:
200:
204:
$ref: '#/components/responses/Success'
403:
$ref: '#/components/responses/Unauthorized'

View File

@@ -20,7 +20,7 @@
#include "Daemon.h"
#include "SubSystemServer.h"
namespace uCentral {
namespace OpenWifi {
class ALBRequestHandler: public Poco::Net::HTTPRequestHandler
/// Return a HTML document with the current date and time.

View File

@@ -8,7 +8,7 @@
#include "Daemon.h"
#include "OpenAPIRequest.h"
namespace uCentral {
namespace OpenWifi {
class AuthClient * AuthClient::instance_ = nullptr;
int AuthClient::Start() {
@@ -38,7 +38,7 @@ namespace uCentral {
} else {
Types::StringPairVec QueryData;
QueryData.push_back(std::make_pair("token",SessionToken));
OpenAPIRequestGet Req(uSERVICE_SECURITY,
OpenAPIRequestGet Req( uSERVICE_SECURITY,
"/api/v1/validateToken",
QueryData,
5000);
@@ -56,4 +56,33 @@ namespace uCentral {
}
return false;
}
bool AuthClient::IsTokenAuthorized(const std::string &SessionToken, SecurityObjects::UserInfoAndPolicy & UInfo) {
SubMutexGuard G(Mutex_);
auto User = UserCache_.find(SessionToken);
if(User != UserCache_.end() && !IsTokenExpired(User->second.webtoken)) {
UInfo = User->second;
return true;
} else {
Types::StringPairVec QueryData;
QueryData.push_back(std::make_pair("token",SessionToken));
OpenAPIRequestGet Req(uSERVICE_SECURITY,
"/api/v1/validateToken",
QueryData,
5000);
Poco::JSON::Object::Ptr Response;
if(Req.Do(Response)==Poco::Net::HTTPResponse::HTTP_OK) {
if(Response->has("tokenInfo") && Response->has("userInfo")) {
SecurityObjects::UserInfoAndPolicy P;
P.from_json(Response);
UserCache_[SessionToken] = P;
UInfo = P;
}
return true;
}
}
return false;
}
}

View File

@@ -13,9 +13,9 @@
#include "RESTAPI_SecurityObjects.h"
#include "SubSystemServer.h"
namespace uCentral {
namespace OpenWifi {
class AuthClient : public SubSystemServer {
class AuthClient : public SubSystemServer {
public:
explicit AuthClient() noexcept:
SubSystemServer("Authentication", "AUTH-CLNT", "authentication")
@@ -31,12 +31,12 @@ namespace uCentral {
int Start() override;
void Stop() override;
bool IsAuthorized(Poco::Net::HTTPServerRequest & Request, std::string &SessionToken, SecurityObjects::UserInfoAndPolicy & UInfo );
bool IsAuthorized(Poco::Net::HTTPServerRequest & Request, std::string &SessionToken, OpenWifi::SecurityObjects::UserInfoAndPolicy & UInfo );
void RemovedCachedToken(const std::string &Token);
bool IsTokenAuthorized(const std::string &Token, SecurityObjects::UserInfoAndPolicy & UInfo);
private:
static AuthClient *instance_;
SecurityObjects::UserInfoCache UserCache_;
OpenWifi::SecurityObjects::UserInfoCache UserCache_;
};
inline AuthClient * AuthClient() { return AuthClient::instance(); }

View File

@@ -14,7 +14,7 @@
#include "Poco/JSON/Parser.h"
#include "Poco/File.h"
namespace uCentral::Config {
namespace OpenWifi::Config {
static std::string DefaultConfiguration;
@@ -232,7 +232,7 @@ namespace uCentral::Config {
}
catch ( const Poco::Exception & E )
{
uCentral::Daemon::instance()->logger().warning(Poco::format("%s: Failed with: %s", std::string(__func__) , E.displayText()));
Daemon::instance()->logger().warning(Poco::format("%s: Failed with: %s", std::string(__func__) , E.displayText()));
}
}

View File

@@ -12,7 +12,7 @@
#include <string>
#include "Poco/JSON/Object.h"
namespace uCentral::Config {
namespace OpenWifi::Config {
class Config {
public:

View File

@@ -1,164 +0,0 @@
//
// License type: BSD 3-Clause License
// License copy: https://github.com/Telecominfraproject/wlan-cloud-ucentralgw/blob/master/LICENSE
//
// Created by Stephane Bourque on 2021-03-04.
// Arilia Wireless Inc.
//
#include "CommandChannel.h"
#include "AuthClient.h"
#include "CommandManager.h"
#include "Daemon.h"
#include "FileUploader.h"
#include "RESTAPI_server.h"
#include "StorageService.h"
#include "WebSocketServer.h"
#include <boost/algorithm/string.hpp>
namespace uCentral {
class CommandChannel * CommandChannel::instance_ = nullptr;
std::string CommandChannel::ProcessCommand(const std::string &Command) {
std::vector<std::string> Tokens{};
std::string Result{"OK"};
try {
size_t pos, old_pos = 0 ;
Logger_.notice(Poco::format("COMMAND: %s",Command));
while((pos = Command.find(' ', old_pos)) != std::string::npos) {
Tokens.push_back(Command.substr(old_pos,pos-old_pos));
old_pos = pos + 1 ;
}
Tokens.push_back(Command.substr(old_pos));
boost::algorithm::to_lower(Tokens[0]);
boost::algorithm::to_lower(Tokens[1]);
if(Tokens[0]=="set") {
if(Tokens[1]=="loglevel") {
if(!Daemon()->SetSubsystemLogLevel(Tokens[3],Tokens[2]))
Result = "ERROR: Invalid: set logLevel subsystem name:" + Tokens[3];
}
} else if(Tokens[0]=="get") {
if(Tokens[1]=="loglevel") {
std::cout << "LogLevels:" << std::endl;
std::cout << " Auth: " << AuthClient()->Logger().getLevel() << std::endl;
std::cout << " uFileUploader: " << FileUploader()->Logger().getLevel() << std::endl;
std::cout << " WebSocket: " << WebSocketServer()->Logger().getLevel() << std::endl;
std::cout << " Storage: " << Storage()->Logger().getLevel() << std::endl;
std::cout << " RESTAPI: " << RESTAPI_server()->Logger().getLevel() << std::endl;
std::cout << " CommandManager: " << Logger_.getLevel() << std::endl;
std::cout << " DeviceRegistry: " << DeviceRegistry()->Logger().getLevel() << std::endl;
} else if (Tokens[1]=="stats") {
} else {
Result = "ERROR: Invalid: get command:" + Tokens[1];
}
} else if(Tokens[0]=="restart") {
Logger_.information("RESTART...");
} else if(Tokens[0]=="stop") {
Logger_.information("STOP...");
} else if(Tokens[0]=="stats") {
Logger_.information("STATS...");
} else {
Result = "ERROR: Invalid command: " + Tokens[0];
}
Logger_.notice(Poco::format("COMMAND-RESULT: %s",Result));
}
catch ( const Poco::Exception & E) {
Logger_.warning(Poco::format("COMMAND: Poco exception %s in performing command.",E.displayText()));
}
catch ( const std::exception & E) {
Logger_.warning(Poco::format("COMMAND: std::exception %s in performing command.",std::string(E.what())));
}
return Result;
}
/// This class handles all client connections.
class UnixSocketServerConnection: public Poco::Net::TCPServerConnection
{
public:
explicit UnixSocketServerConnection(const Poco::Net::StreamSocket & S, Poco::Logger & Logger):
TCPServerConnection(S),
Logger_(Logger)
{
}
void run() override
{
try
{
std::string Message;
std::vector<char> buffer(1024);
int n = 1;
while (n > 0)
{
n = socket().receiveBytes(&buffer[0], (int)buffer.size());
buffer[n] = '\0';
Message += &buffer[0];
Logger_.information(Poco::format("COMMAND-CHANNEL: %s",Message));
if(buffer.size() > n && !Message.empty())
{
CommandChannel()->ProcessCommand(Message);
Message.clear();
}
}
}
catch (const Poco::Exception & E)
{
Logger_.log(E);
}
}
private:
Poco::Logger & Logger_;
};
class UnixSocketServerConnectionFactory: public Poco::Net::TCPServerConnectionFactory
{
public:
explicit UnixSocketServerConnectionFactory() :
Logger_(CommandChannel()->Logger())
{
}
Poco::Net::TCPServerConnection* createConnection(const Poco::Net::StreamSocket& socket) override
{
return new UnixSocketServerConnection(socket,Logger_);
}
private:
Poco::Logger & Logger_;
};
CommandChannel::CommandChannel() noexcept:
SubSystemServer("CommandChannel", "COMMAND-CHANNEL", "commandchannel")
{
}
void CommandChannel::Stop() {
Logger_.notice("Stopping...");
Srv_->stop();
}
int CommandChannel::Start() {
Poco::File F(Daemon()->ConfigPath("ucentral.system.commandchannel","/tmp/app.ucentralgw"));
try {
if (F.exists())
F.remove();
} catch (const Poco::Exception &E ) {
}
SocketFile_ = std::make_unique<Poco::File>(F);
UnixSocket_ = std::make_unique<Poco::Net::SocketAddress>(Poco::Net::SocketAddress::UNIX_LOCAL, SocketFile_->path());
Svs_ = std::make_unique<Poco::Net::ServerSocket>(*UnixSocket_);
Srv_ = std::make_unique<Poco::Net::TCPServer>(new UnixSocketServerConnectionFactory, *Svs_);
Srv_->start();
Logger_.notice("Starting...");
return 0;
}
}

View File

@@ -1,51 +0,0 @@
//
// License type: BSD 3-Clause License
// License copy: https://github.com/Telecominfraproject/wlan-cloud-ucentralgw/blob/master/LICENSE
//
// Created by Stephane Bourque on 2021-03-04.
// Arilia Wireless Inc.
//
#ifndef UCENTRALGW_COMMANDCHANNEL_H
#define UCENTRALGW_COMMANDCHANNEL_H
#include "SubSystemServer.h"
#include "Poco/File.h"
#include "Poco/Net/Socket.h"
#include "Poco/Net/SocketAddress.h"
#include "Poco/Net/TCPServer.h"
#include "Poco/Net/TCPServerConnection.h"
#include "Poco/Net/TCPServerConnectionFactory.h"
#include "Poco/Net/StreamSocket.h"
#include "Poco/Net/ServerSocket.h"
namespace uCentral {
class CommandChannel : public SubSystemServer {
public:
static CommandChannel *instance() {
if (instance_ == nullptr) {
instance_ = new CommandChannel;
}
return instance_;
}
int Start() override;
void Stop() override;
std::string ProcessCommand(const std::string &Command);
private:
static CommandChannel * instance_;
std::unique_ptr<Poco::File> SocketFile_;
std::unique_ptr<Poco::Net::SocketAddress> UnixSocket_;
std::unique_ptr<Poco::Net::ServerSocket> Svs_;
std::unique_ptr<Poco::Net::TCPServer> Srv_;
CommandChannel() noexcept;
};
inline CommandChannel * CommandChannel() { return CommandChannel::instance(); }
} //namespace
#endif // UCENTRALGW_COMMANDCHANNEL_H

View File

@@ -18,7 +18,7 @@
#include "Poco/JSON/Parser.h"
namespace uCentral {
namespace OpenWifi {
class CommandManager * CommandManager::instance_ = nullptr;
@@ -31,15 +31,18 @@ namespace uCentral {
Running_ = true;
while(Running_)
{
Poco::Thread::trySleep(10000);
Poco::Thread::trySleep(30000);
if(!Running_)
break;
std::vector<GWObjects::CommandDetails> Commands;
if(Storage()->GetReadyToExecuteCommands(0,1000,Commands))
if(Storage()->GetReadyToExecuteCommands(1,200,Commands))
{
for(auto & Cmd: Commands)
{
if(!Running_)
break;
if(!SendCommand(Cmd)) {
Logger_.information(Poco::format("Failed to send command '%s' to %s",Cmd.Command,Cmd.SerialNumber));
}

View File

@@ -22,7 +22,7 @@
#include "RESTAPI_GWobjects.h"
#include "SubSystemServer.h"
namespace uCentral {
namespace OpenWifi {
class CommandManager : public SubSystemServer, Poco::Runnable {
public:

View File

@@ -14,7 +14,6 @@
#include "Daemon.h"
#include "CommandChannel.h"
#include "CommandManager.h"
#include "DeviceRegistry.h"
#include "FileUploader.h"
@@ -28,8 +27,9 @@
#include "RESTAPI_InternalServer.h"
#include "AuthClient.h"
#include "StorageArchiver.h"
#include "SerialNumberCache.h"
namespace uCentral {
namespace OpenWifi {
class Daemon *Daemon::instance_ = nullptr;
class Daemon *Daemon::instance() {
@@ -41,6 +41,7 @@ namespace uCentral {
vDAEMON_BUS_TIMER,
Types::SubSystemVec{
Storage(),
SerialNumberCache(),
AuthClient(),
DeviceRegistry(),
RESTAPI_server(),
@@ -49,7 +50,6 @@ namespace uCentral {
CommandManager(),
FileUploader(),
OUIServer(),
CommandChannel(),
StorageArchiver(),
});
}
@@ -71,7 +71,7 @@ namespace uCentral {
auto Type = Line.substr(0, P1);
auto List = Line.substr(P1+1);
Types::StringVec Tokens = uCentral::Utils::Split(List);
Types::StringVec Tokens = Utils::Split(List);
auto Entry = DeviceTypeIdentifications_.find(Type);
if(DeviceTypeIdentifications_.end() == Entry) {
@@ -96,7 +96,7 @@ namespace uCentral {
int main(int argc, char **argv) {
try {
auto App = uCentral::Daemon::instance();
auto App = OpenWifi::Daemon::instance();
auto ExitCode = App->run(argc, argv);
delete App;

View File

@@ -27,9 +27,9 @@
#include "Dashboard.h"
#include "MicroService.h"
#include "uCentralTypes.h"
#include "OpenWifiTypes.h"
namespace uCentral {
namespace OpenWifi {
static const char * vDAEMON_PROPERTIES_FILENAME = "ucentralgw.properties";
static const char * vDAEMON_ROOT_ENV_VAR = "UCENTRALGW_ROOT";

View File

@@ -6,14 +6,15 @@
#include "DeviceRegistry.h"
#include "StorageService.h"
namespace uCentral {
namespace OpenWifi {
void DeviceDashboard::Create() {
uint64_t Now = std::time(nullptr);
if(LastRun_==0 || (Now-LastRun_)>120) {
DB_.reset();
Storage()->AnalyzeCommands(DB_.commands);
DeviceRegistry()->AnalyzeRegistry(DB_);
// DeviceRegistry()->AnalyzeRegistry(DB_);
Storage()->AnalyzeDevices(DB_);
LastRun_ = Now;
}
}

View File

@@ -5,18 +5,18 @@
#ifndef UCENTRALGW_DASHBOARD_H
#define UCENTRALGW_DASHBOARD_H
#include "uCentralTypes.h"
#include "OpenWifiTypes.h"
#include "RESTAPI_GWobjects.h"
namespace uCentral {
namespace OpenWifi {
class DeviceDashboard {
public:
void Create();
const GWObjects::Dashboard & Report() const { return DB_;}
inline void Reset() { LastRun_=0; DB_.reset(); }
private:
GWObjects::Dashboard DB_;
uint64_t LastRun_=0;
inline void Reset() { DB_.reset(); }
};
}

View File

@@ -16,7 +16,7 @@
#include "Poco/JSON/Object.h"
#include "Poco/JSON/Parser.h"
namespace uCentral {
namespace OpenWifi {
class DeviceRegistry *DeviceRegistry::instance_ = nullptr;
DeviceRegistry::DeviceRegistry() noexcept:
@@ -207,7 +207,7 @@ namespace uCentral {
if( T==100) return "100%";
if( T>90) return ">90%";
if( T>60) return ">60%";
return "<60%%>";
return "<60%";
}
std::string ComputeUpTimeTag(uint64_t T) {

View File

@@ -16,7 +16,7 @@
// class uCentral::WebSocket::WSConnection;
namespace uCentral {
namespace OpenWifi {
class WSConnection;
class DeviceRegistry : public SubSystemServer {

View File

@@ -26,7 +26,7 @@
#include "Utils.h"
namespace uCentral {
namespace OpenWifi {
class FileUploader *FileUploader::instance_ = nullptr;
static const std::string URI_BASE{"/v1/upload/"};
@@ -42,7 +42,16 @@ namespace uCentral {
Logger_.information(l);
Path_ = Daemon()->ConfigPath("ucentral.fileuploader.path","/tmp");
Poco::File UploadsDir(Daemon()->ConfigPath("ucentral.fileuploader.path","/tmp"));
Path_ = UploadsDir.path();
if(!UploadsDir.exists()) {
try {
UploadsDir.createDirectory();
} catch (const Poco::Exception &E) {
Logger_.log(E);
Path_ = "/tmp";
}
}
auto Sock{Svr.CreateSecureSocket(Logger_)};
@@ -63,6 +72,8 @@ namespace uCentral {
Servers_.push_back(std::move(NewServer));
}
MaxSize_ = 1000 * Daemon()->ConfigGetInt("ucentral.fileuploader.maxsize", 10000);
return 0;
}
@@ -112,35 +123,49 @@ namespace uCentral {
void handlePart(const Poco::Net::MessageHeader& Header, std::istream& Stream) override
{
FileType_ = Header.get("Content-Type", "(unspecified)");
if (Header.has("Content-Disposition"))
{
std::string Disposition;
Poco::Net::NameValueCollection Parameters;
Poco::Net::MessageHeader::splitParameters(Header["Content-Disposition"], Disposition, Parameters);
Name_ = Parameters.get("name", "(unnamed)");
}
try {
Name_ = "(unnamed)";
if (Header.has("Content-Disposition")) {
std::string Disposition;
Poco::Net::NameValueCollection Parameters;
Poco::Net::MessageHeader::splitParameters(Header["Content-Disposition"],
Disposition, Parameters);
Name_ = Parameters.get("filename", "(unnamed)");
}
Poco::TemporaryFile TmpFile;
std::string FinalFileName = FileUploader()->Path() + "/" + UUID_ ;
Logger_.information(Poco::format("FILE-UPLOADER: uploading trace for %s",UUID_));
Poco::TemporaryFile TmpFile;
std::string FinalFileName = FileUploader()->Path() + "/" + UUID_;
Logger_.information(Poco::format("FILE-UPLOADER: uploading trace for %s", UUID_));
Poco::CountingInputStream InputStream(Stream);
std::ofstream OutputStream(TmpFile.path(), std::ofstream::out);
Poco::StreamCopier::copyStream(InputStream, OutputStream);
Length_ = InputStream.chars();
rename(TmpFile.path().c_str(),FinalFileName.c_str());
}
Poco::CountingInputStream InputStream(Stream);
std::ofstream OutputStream(TmpFile.path(), std::ofstream::out);
Poco::StreamCopier::copyStream(InputStream, OutputStream);
Length_ = TmpFile.getSize();
if (Length_ < FileUploader()->MaxSize()) {
rename(TmpFile.path().c_str(), FinalFileName.c_str());
Good_=true;
} else {
Error_ = "File is too large.";
}
return;
} catch (const Poco::Exception &E ) {
Logger_.log(E);
Error_ = std::string("Upload caused an internal error: ") + E.what() ;
}
}
[[nodiscard]] uint64_t Length() const { return Length_; }
[[nodiscard]] const std::string& Name() const { return Name_; }
[[nodiscard]] const std::string& ContentType() const { return FileType_; }
[[nodiscard]] bool Good() const { return Good_; }
std::string & Error() { return Error_; }
private:
uint64_t Length_=0;
std::string FileType_;
bool Good_=false;
std::string Name_;
std::string UUID_;
std::string Error_;
Poco::Logger & Logger_;
};
@@ -165,14 +190,15 @@ namespace uCentral {
Response.setContentType("application/json");
Poco::JSON::Object Answer;
if (!partHandler.Name().empty()) {
if (partHandler.Good()) {
Answer.set("filename", UUID_);
Answer.set("error", 0);
Storage()->AttachFileToCommand(UUID_);
} else {
Answer.set("filename", UUID_);
Answer.set("error", 13);
Answer.set("errorText", "File could not be uploaded");
Answer.set("errorText", partHandler.Error() );
Storage()->CancelWaitFile(UUID_, partHandler.Error() );
}
std::ostream &ResponseStream = Response.send();
Poco::JSON::Stringifier::stringify(Answer, ResponseStream);
@@ -193,7 +219,7 @@ namespace uCentral {
Poco::Net::HTTPRequestHandler *FileUpLoaderRequestHandlerFactory::createRequestHandler(const Poco::Net::HTTPServerRequest & Request) {
Logger_.debug(Poco::format("REQUEST(%s): %s %s", uCentral::Utils::FormatIPv6(Request.clientAddress().toString()), Request.getMethod(), Request.getURI()));
Logger_.debug(Poco::format("REQUEST(%s): %s %s", Utils::FormatIPv6(Request.clientAddress().toString()), Request.getMethod(), Request.getURI()));
// The UUID should be after the /v1/upload/ part...
auto UUIDLocation = Request.getURI().find_first_of(URI_BASE);

View File

@@ -17,7 +17,7 @@
#include "Poco/Net/HTTPServerRequest.h"
#include "RESTAPI_handler.h"
namespace uCentral {
namespace OpenWifi {
class FileUploader : public SubSystemServer {
public:
@@ -36,6 +36,8 @@ namespace uCentral {
return instance_;
}
[[nodiscard]] inline uint64_t MaxSize() const { return MaxSize_; }
private:
static FileUploader *instance_;
std::vector<std::unique_ptr<Poco::Net::HTTPServer>> Servers_;
@@ -43,6 +45,7 @@ namespace uCentral {
std::string FullName_;
std::map<std::string,uint64_t> OutStandingUploads_;
std::string Path_;
uint64_t MaxSize_=10000000;
explicit FileUploader() noexcept:
SubSystemServer("FileUploader", "FILE-UPLOAD", "ucentral.fileuploader")

View File

@@ -12,7 +12,7 @@
#include "Daemon.h"
#include "Utils.h"
namespace uCentral {
namespace OpenWifi {
class KafkaManager *KafkaManager::instance_ = nullptr;

View File

@@ -13,11 +13,11 @@
#include <thread>
#include "SubSystemServer.h"
#include "uCentralTypes.h"
#include "OpenWifiTypes.h"
#include "cppkafka/cppkafka.h"
namespace uCentral {
namespace OpenWifi {
class KafkaManager : public SubSystemServer {
public:

View File

@@ -5,7 +5,7 @@
#ifndef UCENTRALGW_KAFKA_TOPICS_H
#define UCENTRALGW_KAFKA_TOPICS_H
namespace uCentral::KafkaTopics {
namespace OpenWifi::KafkaTopics {
static const std::string HEALTHCHECK{"healthcheck"};
static const std::string STATE{"state"};
static const std::string CONNECTION{"connection"};
@@ -13,6 +13,7 @@ namespace uCentral::KafkaTopics {
static const std::string ALERTS{"alerts"};
static const std::string COMMAND{"command"};
static const std::string SERVICE_EVENTS{"service_events"};
static const std::string DEVICE_EVENT_QUEUE{"device_event_queue"};
namespace ServiceEvents {
static const std::string EVENT_JOIN{"join"};

View File

@@ -34,7 +34,7 @@
#include "AuthClient.h"
#endif
namespace uCentral {
namespace OpenWifi {
void MyErrorHandler::exception(const Poco::Exception & E) {
Poco::Thread * CurrentThread = Poco::Thread::current();
@@ -112,6 +112,16 @@ namespace uCentral {
} else {
logger().error("Bad bus message.");
}
auto i=Services_.begin();
auto Now = (uint64_t )std::time(nullptr);
for(;i!=Services_.end();) {
if((Now - i->second.LastUpdate)>60) {
i = Services_.erase(i);
} else
++i;
}
} catch (const Poco::Exception &E) {
logger().log(E);
}

View File

@@ -24,16 +24,16 @@
#include "Poco/Net/HTTPServerRequest.h"
#include "Poco/Process.h"
#include "uCentralTypes.h"
#include "OpenWifiTypes.h"
#include "SubSystemServer.h"
namespace uCentral {
namespace OpenWifi {
static const std::string uSERVICE_SECURITY{"ucentralsec"};
static const std::string uSERVICE_GATEWAY{"ucentralgw"};
static const std::string uSERVICE_FIRMWARE{ "ucentralfws"};
static const std::string uSERVICE_TOPOLOGY{ "ucentraltopo"};
static const std::string uSERVICE_PROVISIONING{ "ucentralprov"};
static const std::string uSERVICE_FIRMWARE{ "ucentralfms"};
static const std::string uSERVICE_TOPOLOGY{ "owtopo"};
static const std::string uSERVICE_PROVISIONING{ "owprov"};
class MyErrorHandler : public Poco::ErrorHandler {
public:

View File

@@ -17,7 +17,7 @@
#include "Utils.h"
namespace uCentral {
namespace OpenWifi {
class OUIServer * OUIServer::instance_;
int OUIServer::Start() {

View File

@@ -7,7 +7,7 @@
#include "SubSystemServer.h"
namespace uCentral {
namespace OpenWifi {
class OUIServer : public SubSystemServer {
public:

View File

@@ -17,7 +17,7 @@
#include "Utils.h"
#include "Daemon.h"
namespace uCentral {
namespace OpenWifi {
OpenAPIRequestGet::OpenAPIRequestGet( const std::string & ServiceType,
const std::string & EndPoint,
@@ -32,7 +32,7 @@ namespace uCentral {
int OpenAPIRequestGet::Do(Poco::JSON::Object::Ptr &ResponseObject) {
try {
auto Services = Daemon()->GetServices(Type_);
auto Services = Daemon()->GetServices(Type_);
for(auto const &Svc:Services) {
Poco::URI URI(Svc.PrivateEndPoint);
Poco::Net::HTTPSClientSession Session(URI.getHost(), URI.getPort());
@@ -42,7 +42,7 @@ namespace uCentral {
URI.addQueryParameter(qp.first, qp.second);
std::string Path(URI.getPathAndQuery());
Session.setTimeout(Poco::Timespan(5, 0));
Session.setTimeout(Poco::Timespan(msTimeout_/1000, msTimeout_ % 1000));
Poco::Net::HTTPRequest Request(Poco::Net::HTTPRequest::HTTP_GET,
Path,

View File

@@ -7,9 +7,9 @@
#include "Poco/JSON/Object.h"
#include "uCentralTypes.h"
#include "OpenWifiTypes.h"
namespace uCentral {
namespace OpenWifi {
class OpenAPIRequestGet {
public:

View File

@@ -15,7 +15,9 @@
#include <utility>
#include <queue>
namespace uCentral::Types {
#include "Poco/StringTokenizer.h"
namespace OpenWifi::Types {
typedef std::pair<std::string,std::string> StringPair;
typedef std::vector<StringPair> StringPairVec;
typedef std::queue<StringPair> StringPairQueue;
@@ -28,12 +30,38 @@ namespace uCentral::Types {
typedef std::map<std::string, TopicNotifyFunctionList> NotifyTable;
typedef std::map<std::string,uint64_t> CountedMap;
inline void UpdateCountedMap(CountedMap &M, const std::string &S ) {
typedef std::string UUID_t;
typedef std::vector<UUID_t> UUIDvec_t;
inline void UpdateCountedMap(CountedMap &M, const std::string &S, uint64_t Increment=1) {
auto it = M.find(S);
if(it==M.end())
M[S]=1;
M[S] = Increment;
else
it->second += 1;
it->second += Increment;
}
inline std::string to_string( const StringVec &V) {
std::string Result;
bool first=true;
for(const auto &i:V) {
if(first) {
Result += i;
first = false;
} else {
Result += ",";
Result += i;
}
}
return Result;
}
inline void from_string(const std::string &S, StringVec &V) {
Poco::StringTokenizer Tokens(S,",",Poco::StringTokenizer::TOK_TRIM | Poco::StringTokenizer::TOK_IGNORE_EMPTY);
for(auto const &i:Tokens)
V.emplace_back(i);
}
};

View File

@@ -14,7 +14,7 @@
#include "RESTAPI_protocol.h"
#include "StorageService.h"
namespace uCentral {
namespace OpenWifi {
void RESTAPI_BlackList::handleRequest(Poco::Net::HTTPServerRequest &Request,
Poco::Net::HTTPServerResponse &Response) {
@@ -44,7 +44,7 @@ namespace uCentral {
Poco::Net::HTTPServerResponse &Response) {
try {
auto SerialNumber = GetBinding(uCentral::RESTAPI::Protocol::SERIALNUMBER, "");
auto SerialNumber = GetBinding(RESTAPI::Protocol::SERIALNUMBER, "");
if (!SerialNumber.empty()) {
if (Storage()->DeleteBlackListDevice(SerialNumber)) {
@@ -63,7 +63,10 @@ namespace uCentral {
void RESTAPI_BlackList::DoGet(Poco::Net::HTTPServerRequest &Request,
Poco::Net::HTTPServerResponse &Response) {
try {
InitQueryBlock();
if(!InitQueryBlock()) {
BadRequest(Request, Response, "Illegal parameter value.");
return;
}
std::vector<GWObjects::BlackListedDevice> Devices;
Poco::JSON::Array Objects;
@@ -75,7 +78,7 @@ namespace uCentral {
}
}
Poco::JSON::Object RetObj;
RetObj.set(uCentral::RESTAPI::Protocol::DEVICES, Objects);
RetObj.set(RESTAPI::Protocol::DEVICES, Objects);
ReturnObject(Request, RetObj, Response);
return;
} catch (const Poco::Exception &E) {
@@ -91,18 +94,18 @@ namespace uCentral {
Poco::JSON::Object::Ptr Obj =
parser.parse(Request.stream()).extract<Poco::JSON::Object::Ptr>();
if (Obj->has(uCentral::RESTAPI::Protocol::DEVICES) &&
Obj->isArray(uCentral::RESTAPI::Protocol::DEVICES)) {
if (Obj->has(RESTAPI::Protocol::DEVICES) &&
Obj->isArray(RESTAPI::Protocol::DEVICES)) {
std::vector<GWObjects::BlackListedDevice> Devices;
auto DeviceArray = Obj->getArray(uCentral::RESTAPI::Protocol::DEVICES);
auto DeviceArray = Obj->getArray(RESTAPI::Protocol::DEVICES);
for (const auto &i : *DeviceArray) {
Poco::JSON::Parser pp;
auto InnerObj = pp.parse(i).extract<Poco::JSON::Object::Ptr>();
Poco::DynamicStruct Vars = *InnerObj;
if (Vars.contains(uCentral::RESTAPI::Protocol::SERIALNUMBER) &&
Vars.contains(uCentral::RESTAPI::Protocol::REASON)) {
auto SerialNumber = Vars[uCentral::RESTAPI::Protocol::SERIALNUMBER].toString();
auto Reason = Vars[uCentral::RESTAPI::Protocol::REASON].toString();
if (Vars.contains(RESTAPI::Protocol::SERIALNUMBER) &&
Vars.contains(RESTAPI::Protocol::REASON)) {
auto SerialNumber = Vars[RESTAPI::Protocol::SERIALNUMBER].toString();
auto Reason = Vars[RESTAPI::Protocol::REASON].toString();
GWObjects::BlackListedDevice D{.SerialNumber = SerialNumber,
.Reason = Reason,
.Author = UserInfo_.webtoken.username_,

View File

@@ -11,7 +11,7 @@
#include "RESTAPI_handler.h"
namespace uCentral {
namespace OpenWifi {
class RESTAPI_BlackList : public RESTAPIHandler {
public:
RESTAPI_BlackList(const RESTAPIHandler::BindingMap &bindings, Poco::Logger &L, bool Internal)

View File

@@ -19,16 +19,16 @@
#include "RESTAPI_utils.h"
#include "Utils.h"
using uCentral::RESTAPI_utils::field_to_json;
using uCentral::RESTAPI_utils::field_from_json;
using uCentral::RESTAPI_utils::EmbedDocument;
using OpenWifi::RESTAPI_utils::field_to_json;
using OpenWifi::RESTAPI_utils::field_from_json;
using OpenWifi::RESTAPI_utils::EmbedDocument;
namespace uCentral::GWObjects {
namespace OpenWifi::GWObjects {
void Device::to_json(Poco::JSON::Object &Obj) const {
field_to_json(Obj,"serialNumber", SerialNumber);
#ifdef TIP_GATEWAY_SERVICE
field_to_json(Obj,"deviceType", uCentral::Daemon::instance()->IdentifyDevice(Compatible));
field_to_json(Obj,"deviceType", Daemon::instance()->IdentifyDevice(Compatible));
#endif
field_to_json(Obj,"macAddress", MACAddress);
field_to_json(Obj,"manufacturer", Manufacturer);
@@ -57,13 +57,15 @@ namespace uCentral::GWObjects {
if (DeviceRegistry()->GetState(SerialNumber, ConState)) {
ConState.to_json(Obj);
} else {
field_to_json(Obj,"ipAddress", "N/A");
field_to_json(Obj,"ipAddress", "");
field_to_json(Obj,"txBytes", (uint64_t) 0);
field_to_json(Obj,"rxBytes", (uint64_t )0);
field_to_json(Obj,"messageCount", (uint64_t )0);
field_to_json(Obj,"connected", false);
field_to_json(Obj,"lastContact", "N/A");
field_to_json(Obj,"lastContact", "");
field_to_json(Obj,"verifiedCertificate", "NO_CERTIFICATE");
field_to_json(Obj,"associations_2G", (uint64_t) 0);
field_to_json(Obj,"associations_5G", (uint64_t) 0);
}
#endif
}
@@ -176,6 +178,9 @@ namespace uCentral::GWObjects {
field_to_json(Obj,"connected", Connected);
field_to_json(Obj,"firmware", Firmware);
field_to_json(Obj,"lastContact", LastContact);
field_to_json(Obj,"associations_2G", Associations_2G);
field_to_json(Obj,"associations_5G", Associations_5G);
switch(VerifiedCertificate) {
case NO_CERTIFICATE:
field_to_json(Obj,"verifiedCertificate", "NO_CERTIFICATE"); break;
@@ -216,6 +221,9 @@ namespace uCentral::GWObjects {
field_to_json(Obj,"healths",healths);
field_to_json(Obj,"certificates",certificates);
field_to_json(Obj,"lastContact",lastContact);
field_to_json(Obj,"associations",associations);
field_to_json(Obj,"snapshot",snapshot);
field_to_json(Obj,"numberOfDevices",numberOfDevices);
}
void Dashboard::reset() {
@@ -231,6 +239,9 @@ namespace uCentral::GWObjects {
healths.clear();
certificates.clear();
lastContact.clear();
associations.clear();
numberOfDevices = 0 ;
snapshot = std::time(nullptr);
}
}

View File

@@ -12,7 +12,7 @@
#include "Poco/JSON/Object.h"
#include "RESTAPI_SecurityObjects.h"
namespace uCentral::GWObjects {
namespace OpenWifi::GWObjects {
enum CertificateValidation {
NO_CERTIFICATE,
@@ -24,10 +24,12 @@ namespace uCentral::GWObjects {
struct ConnectionState {
uint64_t MessageCount = 0 ;
std::string SerialNumber;
std::string Address = "N/A";
std::string Address;
uint64_t UUID = 0 ;
uint64_t PendingUUID = 0 ;
uint64_t TX = 0, RX = 0;
uint64_t Associations_2G=0;
uint64_t Associations_5G=0;
bool Connected = false;
uint64_t LastContact=0;
std::string Firmware;
@@ -159,6 +161,8 @@ namespace uCentral::GWObjects {
};
struct Dashboard {
uint64_t snapshot;
uint64_t numberOfDevices;
Types::CountedMap commands;
Types::CountedMap upTimes;
Types::CountedMap memoryUsed;
@@ -171,6 +175,7 @@ namespace uCentral::GWObjects {
Types::CountedMap healths;
Types::CountedMap certificates;
Types::CountedMap lastContact;
Types::CountedMap associations;
void to_json(Poco::JSON::Object &Obj) const;
void reset();
};

View File

@@ -18,7 +18,7 @@
#include "RESTAPI_ouis.h"
#include "Utils.h"
namespace uCentral {
namespace OpenWifi {
class RESTAPI_InternalServer *RESTAPI_InternalServer::instance_ = nullptr;
@@ -59,7 +59,7 @@ namespace uCentral {
Poco::Net::HTTPRequestHandler *InternalRequestHandlerFactory::createRequestHandler(const Poco::Net::HTTPServerRequest & Request) {
Logger_.debug(Poco::format("REQUEST(%s): %s %s", uCentral::Utils::FormatIPv6(Request.clientAddress().toString()), Request.getMethod(), Request.getURI()));
Logger_.debug(Poco::format("REQUEST(%s): %s %s", Utils::FormatIPv6(Request.clientAddress().toString()), Request.getMethod(), Request.getURI()));
Poco::URI uri(Request.getURI());
const auto & Path = uri.getPath();

View File

@@ -12,7 +12,7 @@
#include "Poco/Net/HTTPServerRequest.h"
#include "Poco/Net/NetException.h"
namespace uCentral {
namespace OpenWifi {
class RESTAPI_InternalServer : public SubSystemServer {

View File

@@ -13,8 +13,9 @@
#include "StorageService.h"
#include "DeviceRegistry.h"
#include "CommandManager.h"
#include "uCentralProtocol.h"
namespace uCentral::RESTAPI_RPC {
namespace OpenWifi::RESTAPI_RPC {
void SetCommandAsPending(GWObjects::CommandDetails &Cmd,
Poco::Net::HTTPServerRequest &Request,
Poco::Net::HTTPServerResponse &Response, RESTAPIHandler *Handler) {
@@ -70,6 +71,12 @@ namespace uCentral::RESTAPI_RPC {
Cmd.Status = "completed";
Cmd.Completed = time(nullptr);
if(Cmd.ErrorCode && Cmd.Command==uCentralProtocol::TRACE) {
Cmd.WaitingForFile = 0;
Cmd.AttachDate = Cmd.AttachSize = 0 ;
Cmd.AttachType = "";
}
// Add the completed command to the database...
Storage()->AddCommand(Cmd.SerialNumber, Cmd,Storage::COMMAND_COMPLETED);

View File

@@ -18,7 +18,7 @@
#include "RESTAPI_GWobjects.h"
#include "RESTAPI_handler.h"
namespace uCentral::RESTAPI_RPC {
namespace OpenWifi::RESTAPI_RPC {
bool WaitForRPC(GWObjects::CommandDetails &Cmd,
Poco::Net::HTTPServerRequest &Request,

View File

@@ -12,10 +12,10 @@
#include "RESTAPI_SecurityObjects.h"
#include "RESTAPI_utils.h"
using uCentral::RESTAPI_utils::field_to_json;
using uCentral::RESTAPI_utils::field_from_json;
using OpenWifi::RESTAPI_utils::field_to_json;
using OpenWifi::RESTAPI_utils::field_from_json;
namespace uCentral::SecurityObjects {
namespace OpenWifi::SecurityObjects {
void AclTemplate::to_json(Poco::JSON::Object &Obj) const {
field_to_json(Obj,"Read",Read_);
@@ -303,6 +303,20 @@ namespace uCentral::SecurityObjects {
return false;
}
bool append_from_json(Poco::JSON::Object::Ptr Obj, const UserInfo &UInfo, NoteInfoVec & Notes) {
try {
SecurityObjects::NoteInfoVec NIV;
NIV = RESTAPI_utils::to_object_array<SecurityObjects::NoteInfo>(Obj->get("notes").toString());
for(auto const &i:NIV) {
SecurityObjects::NoteInfo ii{.created=(uint64_t)std::time(nullptr), .createdBy=UInfo.email, .note=i.note};
Notes.push_back(ii);
}
} catch(...) {
}
return false;
}
void ProfileAction::to_json(Poco::JSON::Object &Obj) const {
field_to_json(Obj,"resource", resource);
field_to_json<ResourceAccessType>(Obj,"access", access, ResourceAccessTypeToString);

View File

@@ -10,9 +10,9 @@
#define UCENTRAL_RESTAPI_SECURITYOBJECTS_H
#include "Poco/JSON/Object.h"
#include "uCentralTypes.h"
#include "OpenWifiTypes.h"
namespace uCentral::SecurityObjects {
namespace OpenWifi::SecurityObjects {
struct AclTemplate {
bool Read_ = true;
@@ -94,6 +94,8 @@ namespace uCentral::SecurityObjects {
};
typedef std::vector<UserInfo> UserInfoVec;
bool append_from_json(Poco::JSON::Object::Ptr Obj, const UserInfo &UInfo, NoteInfoVec & Notes);
struct InternalServiceInfo {
std::string privateURI;
std::string publicURI;
@@ -114,9 +116,9 @@ namespace uCentral::SecurityObjects {
struct SystemEndpoint {
std::string type;
uint64_t id = 0;
std::string vendor;
std::string vendor{"OpenWiFi"};
std::string uri;
std::string authenticationType;
std::string authenticationType{"internal_v1"};
void to_json(Poco::JSON::Object &Obj) const;
bool from_json(const Poco::JSON::Object::Ptr &Obj);
};

View File

@@ -11,7 +11,7 @@
#include "RESTAPI_protocol.h"
#include "StorageService.h"
namespace uCentral {
namespace OpenWifi {
void RESTAPI_command::handleRequest(Poco::Net::HTTPServerRequest &Request,
Poco::Net::HTTPServerResponse &Response) {
if (!ContinueProcessing(Request, Response))
@@ -24,7 +24,7 @@ void RESTAPI_command::handleRequest(Poco::Net::HTTPServerRequest &Request,
ParseParameters(Request);
if (Request.getMethod() == Poco::Net::HTTPRequest::HTTP_GET) {
auto CommandUUID = GetBinding(uCentral::RESTAPI::Protocol::COMMANDUUID, "");
auto CommandUUID = GetBinding(RESTAPI::Protocol::COMMANDUUID, "");
GWObjects::CommandDetails Command;
if (Storage()->GetCommand(CommandUUID, Command)) {
Poco::JSON::Object RetObj;
@@ -33,7 +33,7 @@ void RESTAPI_command::handleRequest(Poco::Net::HTTPServerRequest &Request,
} else
NotFound(Request, Response);
} else if (Request.getMethod() == Poco::Net::HTTPRequest::HTTP_DELETE) {
auto CommandUUID = GetBinding(uCentral::RESTAPI::Protocol::COMMANDUUID, "");
auto CommandUUID = GetBinding(RESTAPI::Protocol::COMMANDUUID, "");
if (Storage()->DeleteCommand(CommandUUID)) {
OK(Request, Response);
} else {

View File

@@ -11,7 +11,7 @@
#include "RESTAPI_handler.h"
namespace uCentral {
namespace OpenWifi {
class RESTAPI_command : public RESTAPIHandler {
public:
RESTAPI_command(const RESTAPIHandler::BindingMap &bindings, Poco::Logger &L, bool Internal)

View File

@@ -11,7 +11,7 @@
#include "StorageService.h"
#include "Utils.h"
namespace uCentral {
namespace OpenWifi {
void RESTAPI_commands::handleRequest(Poco::Net::HTTPServerRequest &Request,
Poco::Net::HTTPServerResponse &Response) {
if (!ContinueProcessing(Request, Response))
@@ -22,9 +22,12 @@ void RESTAPI_commands::handleRequest(Poco::Net::HTTPServerRequest &Request,
try {
ParseParameters(Request);
InitQueryBlock();
if(!InitQueryBlock()) {
BadRequest(Request, Response, "Illegal parameter value.");
return;
}
auto SerialNumber = GetParameter(uCentral::RESTAPI::Protocol::SERIALNUMBER, "");
auto SerialNumber = GetParameter(RESTAPI::Protocol::SERIALNUMBER, "");
if (Request.getMethod() == Poco::Net::HTTPRequest::HTTP_GET) {
std::vector<GWObjects::CommandDetails> Commands;
@@ -41,7 +44,7 @@ void RESTAPI_commands::handleRequest(Poco::Net::HTTPServerRequest &Request,
ArrayObj.add(Obj);
}
Poco::JSON::Object RetObj;
RetObj.set(uCentral::RESTAPI::Protocol::COMMANDS, ArrayObj);
RetObj.set(RESTAPI::Protocol::COMMANDS, ArrayObj);
ReturnObject(Request, RetObj, Response);
return;

View File

@@ -11,7 +11,7 @@
#include "RESTAPI_handler.h"
namespace uCentral {
namespace OpenWifi {
class RESTAPI_commands : public RESTAPIHandler {
public:
RESTAPI_commands(const RESTAPIHandler::BindingMap &bindings, Poco::Logger &L, bool Internal)

View File

@@ -14,7 +14,7 @@
#include "RESTAPI_protocol.h"
#include "StorageService.h"
namespace uCentral {
namespace OpenWifi {
void RESTAPI_default_configuration::handleRequest(Poco::Net::HTTPServerRequest &Request,
Poco::Net::HTTPServerResponse &Response) {
if (!ContinueProcessing(Request, Response))
@@ -23,7 +23,7 @@ void RESTAPI_default_configuration::handleRequest(Poco::Net::HTTPServerRequest &
if (!IsAuthorized(Request, Response))
return;
std::string Name = GetBinding(uCentral::RESTAPI::Protocol::NAME, "");
std::string Name = GetBinding(RESTAPI::Protocol::NAME, "");
ParseParameters(Request);
if (Request.getMethod() == Poco::Net::HTTPRequest::HTTP_GET) {

View File

@@ -11,7 +11,7 @@
#include "RESTAPI_handler.h"
namespace uCentral {
namespace OpenWifi {
class RESTAPI_default_configuration : public RESTAPIHandler {
public:
RESTAPI_default_configuration(const RESTAPIHandler::BindingMap &bindings, Poco::Logger &L, bool Internal)

View File

@@ -13,45 +13,49 @@
#include "RESTAPI_protocol.h"
#include "StorageService.h"
namespace uCentral {
void RESTAPI_default_configurations::handleRequest(Poco::Net::HTTPServerRequest &Request,
Poco::Net::HTTPServerResponse &Response) {
if (!ContinueProcessing(Request, Response))
return;
namespace OpenWifi {
void RESTAPI_default_configurations::handleRequest(Poco::Net::HTTPServerRequest &Request,
Poco::Net::HTTPServerResponse &Response) {
if (!ContinueProcessing(Request, Response))
return;
if (!IsAuthorized(Request, Response))
return;
if (!IsAuthorized(Request, Response))
return;
try {
if (Request.getMethod() == Poco::Net::HTTPRequest::HTTP_GET) {
ParseParameters(Request);
InitQueryBlock();
try {
if (Request.getMethod() == Poco::Net::HTTPRequest::HTTP_GET) {
ParseParameters(Request);
if(!InitQueryBlock()) {
BadRequest(Request, Response, "Illegal parameter value.");
return;
}
Logger_.information(
Poco::format("DEFAULT_CONFIGURATIONS: from %Lu, limit of %Lu, filter=%s.",
(int64_t)QB_.Offset, (int64_t)QB_.Limit, QB_.Filter));
RESTAPIHandler::PrintBindings();
Logger_.information(
Poco::format("DEFAULT_CONFIGURATIONS: from %Lu, limit of %Lu, filter=%s.",
(int64_t)QB_.Offset, (int64_t)QB_.Limit, QB_.Filter));
RESTAPIHandler::PrintBindings();
std::vector<GWObjects::DefaultConfiguration> DefConfigs;
std::vector<GWObjects::DefaultConfiguration> DefConfigs;
Storage()->GetDefaultConfigurations(QB_.Offset, QB_.Limit, DefConfigs);
Storage()->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::Array Objects;
for (const auto &i : DefConfigs) {
Poco::JSON::Object Obj;
i.to_json(Obj);
Objects.add(Obj);
}
Poco::JSON::Object RetObj;
RetObj.set(uCentral::RESTAPI::Protocol::CONFIGURATIONS, Objects);
ReturnObject(Request, RetObj, Response);
} else
BadRequest(Request, Response);
return;
} catch (const Poco::Exception &E) {
Logger_.warning(
Poco::format("%s: Failed with: %s", std::string(__func__), E.displayText()));
Poco::JSON::Object RetObj;
RetObj.set(RESTAPI::Protocol::CONFIGURATIONS, Objects);
ReturnObject(Request, RetObj, Response);
} else
BadRequest(Request, Response);
return;
} catch (const Poco::Exception &E) {
Logger_.warning(
Poco::format("%s: Failed with: %s", std::string(__func__), E.displayText()));
}
BadRequest(Request, Response);
}
}
}

View File

@@ -11,7 +11,7 @@
#include "RESTAPI_handler.h"
namespace uCentral {
namespace OpenWifi {
class RESTAPI_default_configurations : public RESTAPIHandler {
public:
RESTAPI_default_configurations(const RESTAPIHandler::BindingMap &bindings, Poco::Logger &L, bool Internal)

View File

@@ -6,7 +6,7 @@
#include "Daemon.h"
#include "Dashboard.h"
namespace uCentral {
namespace OpenWifi {
void RESTAPI_deviceDashboardHandler::handleRequest(Poco::Net::HTTPServerRequest &Request,
Poco::Net::HTTPServerResponse &Response) {
@@ -18,7 +18,8 @@ namespace uCentral {
if (Request.getMethod() == Poco::Net::HTTPRequest::HTTP_GET) {
DoGet(Request, Response);
BadRequest(Request, Response);
} else {
BadRequest(Request, Response, "Unsupported method.");
}
}

View File

@@ -7,7 +7,7 @@
#include "RESTAPI_handler.h"
namespace uCentral {
namespace OpenWifi {
class RESTAPI_deviceDashboardHandler : public RESTAPIHandler {
public:
RESTAPI_deviceDashboardHandler(const RESTAPIHandler::BindingMap &bindings, Poco::Logger &L, bool Internal)

View File

@@ -29,7 +29,7 @@
#include "KafkaManager.h"
#include "Kafka_topics.h"
namespace uCentral {
namespace OpenWifi {
void RESTAPI_device_commandHandler::handleRequest(Poco::Net::HTTPServerRequest &Request,
Poco::Net::HTTPServerResponse &Response) {
@@ -40,14 +40,14 @@ void RESTAPI_device_commandHandler::handleRequest(Poco::Net::HTTPServerRequest &
if (!IsAuthorized(Request, Response))
return;
std::string Command = GetBinding(uCentral::RESTAPI::Protocol::COMMAND, "");
std::string Command = GetBinding(RESTAPI::Protocol::COMMAND, "");
if (Command.empty()) {
Logger_.error(Poco::format("Unrecognized command '%s'", Command));
BadRequest(Request, Response);
return;
}
SerialNumber_ = GetBinding(uCentral::RESTAPI::Protocol::SERIALNUMBER, "");
SerialNumber_ = GetBinding(RESTAPI::Protocol::SERIALNUMBER, "");
if (SerialNumber_.empty()) {
Logger_.error(Poco::format("Missing serial number for command '%s'", Command));
BadRequest(Request, Response);
@@ -55,66 +55,69 @@ void RESTAPI_device_commandHandler::handleRequest(Poco::Net::HTTPServerRequest &
}
ParseParameters(Request);
InitQueryBlock();
if(!InitQueryBlock()) {
BadRequest(Request, Response, "Illegal parameter value.");
return;
}
if (Command == uCentral::RESTAPI::Protocol::CAPABILITIES &&
if (Command == RESTAPI::Protocol::CAPABILITIES &&
Request.getMethod() == Poco::Net::HTTPServerRequest::HTTP_GET) {
GetCapabilities(Request, Response);
} else if (Command == uCentral::RESTAPI::Protocol::CAPABILITIES &&
} else if (Command == RESTAPI::Protocol::CAPABILITIES &&
Request.getMethod() == Poco::Net::HTTPServerRequest::HTTP_DELETE) {
DeleteCapabilities(Request, Response);
} else if (Command == uCentral::RESTAPI::Protocol::LOGS &&
} else if (Command == RESTAPI::Protocol::LOGS &&
Request.getMethod() == Poco::Net::HTTPServerRequest::HTTP_GET) {
GetLogs(Request, Response);
} else if (Command == uCentral::RESTAPI::Protocol::LOGS &&
} else if (Command == RESTAPI::Protocol::LOGS &&
Request.getMethod() == Poco::Net::HTTPServerRequest::HTTP_DELETE) {
DeleteLogs(Request, Response);
} else if (Command == uCentral::RESTAPI::Protocol::HEALTHCHECKS &&
} else if (Command == RESTAPI::Protocol::HEALTHCHECKS &&
Request.getMethod() == Poco::Net::HTTPServerRequest::HTTP_GET) {
GetChecks(Request, Response);
} else if (Command == uCentral::RESTAPI::Protocol::HEALTHCHECKS &&
} else if (Command == RESTAPI::Protocol::HEALTHCHECKS &&
Request.getMethod() == Poco::Net::HTTPServerRequest::HTTP_DELETE) {
DeleteChecks(Request, Response);
} else if (Command == uCentral::RESTAPI::Protocol::STATISTICS &&
} else if (Command == RESTAPI::Protocol::STATISTICS &&
Request.getMethod() == Poco::Net::HTTPServerRequest::HTTP_GET) {
GetStatistics(Request, Response);
} else if (Command == uCentral::RESTAPI::Protocol::STATISTICS &&
} else if (Command == RESTAPI::Protocol::STATISTICS &&
Request.getMethod() == Poco::Net::HTTPServerRequest::HTTP_DELETE) {
DeleteStatistics(Request, Response);
} else if (Command == uCentral::RESTAPI::Protocol::STATUS &&
} else if (Command == RESTAPI::Protocol::STATUS &&
Request.getMethod() == Poco::Net::HTTPServerRequest::HTTP_GET) {
GetStatus(Request, Response);
} else if (Command == uCentral::RESTAPI::Protocol::PERFORM &&
} else if (Command == RESTAPI::Protocol::PERFORM &&
Request.getMethod() == Poco::Net::HTTPServerRequest::HTTP_POST) {
ExecuteCommand(Request, Response);
} else if (Command == uCentral::RESTAPI::Protocol::CONFIGURE &&
} else if (Command == RESTAPI::Protocol::CONFIGURE &&
Request.getMethod() == Poco::Net::HTTPServerRequest::HTTP_POST) {
Configure(Request, Response);
} else if (Command == uCentral::RESTAPI::Protocol::UPGRADE &&
} else if (Command == RESTAPI::Protocol::UPGRADE &&
Request.getMethod() == Poco::Net::HTTPServerRequest::HTTP_POST) {
Upgrade(Request, Response);
} else if (Command == uCentral::RESTAPI::Protocol::REBOOT &&
} else if (Command == RESTAPI::Protocol::REBOOT &&
Request.getMethod() == Poco::Net::HTTPServerRequest::HTTP_POST) {
Reboot(Request, Response);
} else if (Command == uCentral::RESTAPI::Protocol::FACTORY &&
} else if (Command == RESTAPI::Protocol::FACTORY &&
Request.getMethod() == Poco::Net::HTTPServerRequest::HTTP_POST) {
Factory(Request, Response);
} else if (Command == uCentral::RESTAPI::Protocol::LEDS &&
} else if (Command == RESTAPI::Protocol::LEDS &&
Request.getMethod() == Poco::Net::HTTPServerRequest::HTTP_POST) {
LEDs(Request, Response);
} else if (Command == uCentral::RESTAPI::Protocol::TRACE &&
} else if (Command == RESTAPI::Protocol::TRACE &&
Request.getMethod() == Poco::Net::HTTPServerRequest::HTTP_POST) {
Trace(Request, Response);
} else if (Command == uCentral::RESTAPI::Protocol::REQUEST &&
} else if (Command == RESTAPI::Protocol::REQUEST &&
Request.getMethod() == Poco::Net::HTTPServerRequest::HTTP_POST) {
MakeRequest(Request, Response);
} else if (Command == uCentral::RESTAPI::Protocol::WIFISCAN &&
} else if (Command == RESTAPI::Protocol::WIFISCAN &&
Request.getMethod() == Poco::Net::HTTPServerRequest::HTTP_POST) {
WifiScan(Request, Response);
} else if (Command == uCentral::RESTAPI::Protocol::EVENTQUEUE &&
} else if (Command == RESTAPI::Protocol::EVENTQUEUE &&
Request.getMethod() == Poco::Net::HTTPServerRequest::HTTP_POST) {
EventQueue(Request, Response);
} else if (Command == uCentral::RESTAPI::Protocol::RTTY &&
} else if (Command == RESTAPI::Protocol::RTTY &&
Request.getMethod() == Poco::Net::HTTPServerRequest::HTTP_GET) {
Rtty(Request, Response);
} else {
@@ -122,7 +125,7 @@ void RESTAPI_device_commandHandler::handleRequest(Poco::Net::HTTPServerRequest &
}
return;
} catch (const Poco::Exception &E) {
Logger_.error(Poco::format("%s: failed with %s", std::string(__func__), E.displayText()));
Logger_.log(E);
}
BadRequest(Request, Response);
}
@@ -134,14 +137,14 @@ void RESTAPI_device_commandHandler::GetCapabilities(Poco::Net::HTTPServerRequest
if (Storage()->GetDeviceCapabilities(SerialNumber_, Caps)) {
Poco::JSON::Object RetObj;
Caps.to_json(RetObj);
RetObj.set(uCentral::RESTAPI::Protocol::SERIALNUMBER, SerialNumber_);
RetObj.set(RESTAPI::Protocol::SERIALNUMBER, SerialNumber_);
ReturnObject(Request, RetObj, Response);
} else {
NotFound(Request, Response);
}
return;
} catch (const Poco::Exception &E) {
Logger_.error(Poco::format("%s: failed with %s", std::string(__func__), E.displayText()));
Logger_.log(E);
}
BadRequest(Request, Response);
}
@@ -155,7 +158,7 @@ void RESTAPI_device_commandHandler::DeleteCapabilities(Poco::Net::HTTPServerRequ
NotFound(Request, Response);
return;
} catch (const Poco::Exception &E) {
Logger_.error(Poco::format("%s: failed with %s", std::string(__func__), E.displayText()));
Logger_.log(E);
}
BadRequest(Request, Response);
}
@@ -168,7 +171,7 @@ void RESTAPI_device_commandHandler::GetStatistics(Poco::Net::HTTPServerRequest &
Storage()->GetLifetimeStats(SerialNumber_, Stats);
Poco::JSON::Parser P;
if (Stats.empty())
Stats = uCentral::uCentralProtocol::EMPTY_JSON_DOC;
Stats = uCentralProtocol::EMPTY_JSON_DOC;
auto Obj = P.parse(Stats).extract<Poco::JSON::Object::Ptr>();
ReturnObject(Request, *Obj, Response);
} else if (QB_.LastOnly) {
@@ -176,7 +179,7 @@ void RESTAPI_device_commandHandler::GetStatistics(Poco::Net::HTTPServerRequest &
if (DeviceRegistry()->GetStatistics(SerialNumber_, Stats)) {
Poco::JSON::Parser P;
if (Stats.empty())
Stats = uCentral::uCentralProtocol::EMPTY_JSON_DOC;
Stats = uCentralProtocol::EMPTY_JSON_DOC;
auto Obj = P.parse(Stats).extract<Poco::JSON::Object::Ptr>();
ReturnObject(Request, *Obj, Response);
} else {
@@ -197,13 +200,13 @@ void RESTAPI_device_commandHandler::GetStatistics(Poco::Net::HTTPServerRequest &
ArrayObj.add(Obj);
}
Poco::JSON::Object RetObj;
RetObj.set(uCentral::RESTAPI::Protocol::DATA, ArrayObj);
RetObj.set(uCentral::RESTAPI::Protocol::SERIALNUMBER, SerialNumber_);
RetObj.set(RESTAPI::Protocol::DATA, ArrayObj);
RetObj.set(RESTAPI::Protocol::SERIALNUMBER, SerialNumber_);
ReturnObject(Request, RetObj, Response);
}
return;
} catch (const Poco::Exception &E) {
Logger_.error(Poco::format("%s: failed with %s", std::string(__func__), E.displayText()));
Logger_.log(E);
}
BadRequest(Request, Response);
}
@@ -227,7 +230,7 @@ void RESTAPI_device_commandHandler::DeleteStatistics(Poco::Net::HTTPServerReques
}
return;
} catch (const Poco::Exception &E) {
Logger_.error(Poco::format("%s: failed with %s", std::string(__func__), E.displayText()));
Logger_.log(E);
}
BadRequest(Request, Response);
}
@@ -246,7 +249,7 @@ void RESTAPI_device_commandHandler::GetStatus(Poco::Net::HTTPServerRequest &Requ
}
return;
} catch (const Poco::Exception &E) {
Logger_.error(Poco::format("%s: failed with %s", std::string(__func__), E.displayText()));
Logger_.log(E);
}
BadRequest(Request, Response);
}
@@ -258,19 +261,19 @@ void RESTAPI_device_commandHandler::Configure(Poco::Net::HTTPServerRequest &Requ
Poco::JSON::Parser Parser;
auto Obj = Parser.parse(Request.stream()).extract<Poco::JSON::Object::Ptr>();
if (Obj->has(uCentral::RESTAPI::Protocol::SERIALNUMBER) &&
Obj->has(uCentral::RESTAPI::Protocol::UUID) &&
Obj->has(uCentral::RESTAPI::Protocol::CONFIGURATION)) {
if (Obj->has(RESTAPI::Protocol::SERIALNUMBER) &&
Obj->has(RESTAPI::Protocol::UUID) &&
Obj->has(RESTAPI::Protocol::CONFIGURATION)) {
auto SNum = Obj->get(uCentral::RESTAPI::Protocol::SERIALNUMBER).toString();
auto SNum = Obj->get(RESTAPI::Protocol::SERIALNUMBER).toString();
if (SerialNumber_ != SNum) {
BadRequest(Request, Response);
return;
}
auto UUID = Obj->get(uCentral::RESTAPI::Protocol::UUID);
auto Configuration = GetS(uCentral::RESTAPI::Protocol::CONFIGURATION, Obj,
uCentral::uCentralProtocol::EMPTY_JSON_DOC);
auto UUID = Obj->get(RESTAPI::Protocol::UUID);
auto Configuration = GetS(RESTAPI::Protocol::CONFIGURATION, Obj,
uCentralProtocol::EMPTY_JSON_DOC);
auto When = GetWhen(Obj);
uint64_t NewUUID;
@@ -283,17 +286,17 @@ void RESTAPI_device_commandHandler::Configure(Poco::Net::HTTPServerRequest &Requ
Cmd.SerialNumber = SerialNumber_;
Cmd.UUID = Daemon()->CreateUUID();
Cmd.SubmittedBy = UserInfo_.webtoken.username_;
Cmd.Command = uCentral::uCentralProtocol::CONFIGURE;
Cmd.Command = uCentralProtocol::CONFIGURE;
Cmd.RunAt = When;
uCentral::Config::Config Cfg(Configuration);
Config::Config Cfg(Configuration);
Poco::JSON::Object Params;
Poco::JSON::Object CfgObj;
Params.set(uCentral::uCentralProtocol::SERIAL, SerialNumber_);
Params.set(uCentral::uCentralProtocol::UUID, NewUUID);
Params.set(uCentral::uCentralProtocol::WHEN, When);
Params.set(uCentral::uCentralProtocol::CONFIG, Cfg.to_json());
Params.set(uCentralProtocol::SERIAL, SerialNumber_);
Params.set(uCentralProtocol::UUID, NewUUID);
Params.set(uCentralProtocol::WHEN, When);
Params.set(uCentralProtocol::CONFIG, Cfg.to_json());
std::stringstream ParamStream;
Params.stringify(ParamStream);
@@ -305,7 +308,7 @@ void RESTAPI_device_commandHandler::Configure(Poco::Net::HTTPServerRequest &Requ
}
}
} catch (const Poco::Exception &E) {
Logger_.error(Poco::format("%s: failed with %s", std::string(__func__), E.displayText()));
Logger_.log(E);
}
BadRequest(Request, Response);
}
@@ -316,16 +319,16 @@ void RESTAPI_device_commandHandler::Upgrade(Poco::Net::HTTPServerRequest &Reques
Poco::JSON::Parser parser;
auto Obj = parser.parse(Request.stream()).extract<Poco::JSON::Object::Ptr>();
if (Obj->has(uCentral::RESTAPI::Protocol::URI) &&
Obj->has(uCentral::RESTAPI::Protocol::SERIALNUMBER)) {
if (Obj->has(RESTAPI::Protocol::URI) &&
Obj->has(RESTAPI::Protocol::SERIALNUMBER)) {
auto SNum = Obj->get(uCentral::RESTAPI::Protocol::SERIALNUMBER).toString();
auto SNum = Obj->get(RESTAPI::Protocol::SERIALNUMBER).toString();
if (SerialNumber_ != SNum) {
BadRequest(Request, Response);
return;
}
auto URI = GetS(uCentral::RESTAPI::Protocol::URI, Obj);
auto URI = GetS(RESTAPI::Protocol::URI, Obj);
auto When = GetWhen(Obj);
GWObjects::CommandDetails Cmd;
@@ -333,14 +336,14 @@ void RESTAPI_device_commandHandler::Upgrade(Poco::Net::HTTPServerRequest &Reques
Cmd.SerialNumber = SerialNumber_;
Cmd.UUID = Daemon()->CreateUUID();
Cmd.SubmittedBy = UserInfo_.webtoken.username_;
Cmd.Command = uCentral::uCentralProtocol::UPGRADE;
Cmd.Command = uCentralProtocol::UPGRADE;
Cmd.RunAt = When;
Poco::JSON::Object Params;
Params.set(uCentral::uCentralProtocol::SERIAL, SerialNumber_);
Params.set(uCentral::uCentralProtocol::URI, URI);
Params.set(uCentral::uCentralProtocol::WHEN, When);
Params.set(uCentralProtocol::SERIAL, SerialNumber_);
Params.set(uCentralProtocol::URI, URI);
Params.set(uCentralProtocol::WHEN, When);
std::stringstream ParamStream;
Params.stringify(ParamStream);
@@ -350,7 +353,7 @@ void RESTAPI_device_commandHandler::Upgrade(Poco::Net::HTTPServerRequest &Reques
return;
}
} catch (const Poco::Exception &E) {
Logger_.error(Poco::format("%s: failed with %s", std::string(__func__), E.displayText()));
Logger_.log(E);
}
BadRequest(Request, Response);
}
@@ -374,13 +377,13 @@ void RESTAPI_device_commandHandler::GetLogs(Poco::Net::HTTPServerRequest &Reques
ArrayObj.add(Obj);
}
Poco::JSON::Object RetObj;
RetObj.set(uCentral::RESTAPI::Protocol::VALUES, ArrayObj);
RetObj.set(uCentral::RESTAPI::Protocol::SERIALNUMBER, SerialNumber_);
RetObj.set(RESTAPI::Protocol::VALUES, ArrayObj);
RetObj.set(RESTAPI::Protocol::SERIALNUMBER, SerialNumber_);
ReturnObject(Request, RetObj, Response);
return;
} catch (const Poco::Exception &E) {
Logger_.error(Poco::format("%s: failed with %s", std::string(__func__), E.displayText()));
Logger_.log(E);
}
BadRequest(Request, Response);
}
@@ -394,7 +397,7 @@ void RESTAPI_device_commandHandler::DeleteLogs(Poco::Net::HTTPServerRequest &Req
return;
}
} catch (const Poco::Exception &E) {
Logger_.error(Poco::format("%s: failed with %s", std::string(__func__), E.displayText()));
Logger_.log(E);
}
BadRequest(Request, Response);
}
@@ -429,13 +432,13 @@ void RESTAPI_device_commandHandler::GetChecks(Poco::Net::HTTPServerRequest &Requ
}
Poco::JSON::Object RetObj;
RetObj.set(uCentral::RESTAPI::Protocol::VALUES, ArrayObj);
RetObj.set(uCentral::RESTAPI::Protocol::SERIALNUMBER, SerialNumber_);
RetObj.set(RESTAPI::Protocol::VALUES, ArrayObj);
RetObj.set(RESTAPI::Protocol::SERIALNUMBER, SerialNumber_);
ReturnObject(Request, RetObj, Response);
}
return;
} catch (const Poco::Exception &E) {
Logger_.error(Poco::format("%s: failed with %s", std::string(__func__), E.displayText()));
Logger_.log(E);
}
BadRequest(Request, Response);
}
@@ -448,7 +451,7 @@ void RESTAPI_device_commandHandler::DeleteChecks(Poco::Net::HTTPServerRequest &R
return;
}
} catch (const Poco::Exception &E) {
Logger_.error(Poco::format("%s: failed with %s", std::string(__func__), E.displayText()));
Logger_.log(E);
}
BadRequest(Request, Response);
}
@@ -460,18 +463,18 @@ void RESTAPI_device_commandHandler::ExecuteCommand(Poco::Net::HTTPServerRequest
Poco::JSON::Parser parser;
auto Obj = parser.parse(Request.stream()).extract<Poco::JSON::Object::Ptr>();
if (Obj->has(uCentral::RESTAPI::Protocol::COMMAND) &&
Obj->has(uCentral::RESTAPI::Protocol::SERIALNUMBER) &&
Obj->has(uCentral::RESTAPI::Protocol::PAYLOAD)) {
if (Obj->has(RESTAPI::Protocol::COMMAND) &&
Obj->has(RESTAPI::Protocol::SERIALNUMBER) &&
Obj->has(RESTAPI::Protocol::PAYLOAD)) {
auto SNum = Obj->get(uCentral::RESTAPI::Protocol::SERIALNUMBER).toString();
auto SNum = Obj->get(RESTAPI::Protocol::SERIALNUMBER).toString();
if (SerialNumber_ != SNum) {
BadRequest(Request, Response);
return;
}
auto Command = GetS(uCentral::RESTAPI::Protocol::COMMAND, Obj);
auto Payload = GetS(uCentral::RESTAPI::Protocol::PAYLOAD, Obj);
auto Command = GetS(RESTAPI::Protocol::COMMAND, Obj);
auto Payload = GetS(RESTAPI::Protocol::PAYLOAD, Obj);
auto When = GetWhen(Obj);
GWObjects::CommandDetails Cmd;
@@ -490,10 +493,10 @@ void RESTAPI_device_commandHandler::ExecuteCommand(Poco::Net::HTTPServerRequest
Poco::JSON::Object Params;
Params.set(uCentral::uCentralProtocol::SERIAL, SerialNumber_);
Params.set(uCentral::uCentralProtocol::COMMAND, Command);
Params.set(uCentral::uCentralProtocol::WHEN, When);
Params.set(uCentral::uCentralProtocol::PAYLOAD, PayloadObject);
Params.set(uCentralProtocol::SERIAL, SerialNumber_);
Params.set(uCentralProtocol::COMMAND, Command);
Params.set(uCentralProtocol::WHEN, When);
Params.set(uCentralProtocol::PAYLOAD, PayloadObject);
std::stringstream ParamStream;
Params.stringify(ParamStream);
@@ -503,7 +506,7 @@ void RESTAPI_device_commandHandler::ExecuteCommand(Poco::Net::HTTPServerRequest
return;
}
} catch (const Poco::Exception &E) {
Logger_.error(Poco::format("%s: failed with %s", std::string(__func__), E.displayText()));
Logger_.log(E);
}
BadRequest(Request, Response);
}
@@ -515,8 +518,8 @@ void RESTAPI_device_commandHandler::Reboot(Poco::Net::HTTPServerRequest &Request
Poco::JSON::Parser IncomingParser;
auto Obj = IncomingParser.parse(Request.stream()).extract<Poco::JSON::Object::Ptr>();
if (Obj->has(uCentral::RESTAPI::Protocol::SERIALNUMBER)) {
auto SNum = Obj->get(uCentral::RESTAPI::Protocol::SERIALNUMBER).toString();
if (Obj->has(RESTAPI::Protocol::SERIALNUMBER)) {
auto SNum = Obj->get(RESTAPI::Protocol::SERIALNUMBER).toString();
if (SerialNumber_ != SNum) {
BadRequest(Request, Response);
return;
@@ -527,13 +530,13 @@ void RESTAPI_device_commandHandler::Reboot(Poco::Net::HTTPServerRequest &Request
Cmd.SerialNumber = SerialNumber_;
Cmd.UUID = Daemon()->CreateUUID();
Cmd.SubmittedBy = UserInfo_.webtoken.username_;
Cmd.Command = uCentral::uCentralProtocol::REBOOT;
Cmd.Command = uCentralProtocol::REBOOT;
Cmd.RunAt = When;
Poco::JSON::Object Params;
Params.set(uCentral::uCentralProtocol::SERIAL, SerialNumber_);
Params.set(uCentral::uCentralProtocol::WHEN, When);
Params.set(uCentralProtocol::SERIAL, SerialNumber_);
Params.set(uCentralProtocol::WHEN, When);
std::stringstream ParamStream;
Params.stringify(ParamStream);
@@ -543,7 +546,7 @@ void RESTAPI_device_commandHandler::Reboot(Poco::Net::HTTPServerRequest &Request
return;
}
} catch (const Poco::Exception &E) {
Logger_.error(Poco::format("%s: failed with %s", std::string(__func__), E.displayText()));
Logger_.log(E);
}
BadRequest(Request, Response);
}
@@ -556,17 +559,17 @@ void RESTAPI_device_commandHandler::Factory(Poco::Net::HTTPServerRequest &Reques
Poco::JSON::Object::Ptr Obj =
parser.parse(Request.stream()).extract<Poco::JSON::Object::Ptr>();
if (Obj->has(uCentral::RESTAPI::Protocol::KEEPREDIRECTOR) &&
Obj->has(uCentral::RESTAPI::Protocol::SERIALNUMBER)) {
if (Obj->has(RESTAPI::Protocol::KEEPREDIRECTOR) &&
Obj->has(RESTAPI::Protocol::SERIALNUMBER)) {
auto SNum = Obj->get(uCentral::RESTAPI::Protocol::SERIALNUMBER).toString();
auto SNum = Obj->get(RESTAPI::Protocol::SERIALNUMBER).toString();
if (SerialNumber_ != SNum) {
BadRequest(Request, Response);
return;
}
auto KeepRedirector = GetB(uCentral::RESTAPI::Protocol::KEEPREDIRECTOR, Obj, true);
auto KeepRedirector = GetB(RESTAPI::Protocol::KEEPREDIRECTOR, Obj, true);
uint64_t When = GetWhen(Obj);
GWObjects::CommandDetails Cmd;
@@ -574,14 +577,14 @@ void RESTAPI_device_commandHandler::Factory(Poco::Net::HTTPServerRequest &Reques
Cmd.SerialNumber = SerialNumber_;
Cmd.UUID = Daemon()->CreateUUID();
Cmd.SubmittedBy = UserInfo_.webtoken.username_;
Cmd.Command = uCentral::uCentralProtocol::FACTORY;
Cmd.Command = uCentralProtocol::FACTORY;
Cmd.RunAt = When;
Poco::JSON::Object Params;
Params.set(uCentral::uCentralProtocol::SERIAL, SerialNumber_);
Params.set(uCentral::uCentralProtocol::KEEP_REDIRECTOR, KeepRedirector ? 1 : 0);
Params.set(uCentral::uCentralProtocol::WHEN, When);
Params.set(uCentralProtocol::SERIAL, SerialNumber_);
Params.set(uCentralProtocol::KEEP_REDIRECTOR, KeepRedirector ? 1 : 0);
Params.set(uCentralProtocol::WHEN, When);
std::stringstream ParamStream;
Params.stringify(ParamStream);
@@ -591,7 +594,7 @@ void RESTAPI_device_commandHandler::Factory(Poco::Net::HTTPServerRequest &Reques
return;
}
} catch (const Poco::Exception &E) {
Logger_.error(Poco::format("%s: failed with %s", std::string(__func__), E.displayText()));
Logger_.log(E);
}
BadRequest(Request, Response);
}
@@ -603,26 +606,26 @@ void RESTAPI_device_commandHandler::LEDs(Poco::Net::HTTPServerRequest &Request,
Poco::JSON::Object::Ptr Obj =
parser.parse(Request.stream()).extract<Poco::JSON::Object::Ptr>();
if (Obj->has(uCentral::uCentralProtocol::PATTERN) &&
Obj->has(uCentral::RESTAPI::Protocol::SERIALNUMBER)) {
if (Obj->has(uCentralProtocol::PATTERN) &&
Obj->has(RESTAPI::Protocol::SERIALNUMBER)) {
auto SNum = Obj->get(uCentral::RESTAPI::Protocol::SERIALNUMBER).toString();
auto SNum = Obj->get(RESTAPI::Protocol::SERIALNUMBER).toString();
if (SerialNumber_ != SNum) {
BadRequest(Request, Response);
return;
}
auto Pattern =
GetS(uCentral::uCentralProtocol::PATTERN, Obj, uCentral::uCentralProtocol::BLINK);
if (Pattern != uCentral::uCentralProtocol::ON &&
Pattern != uCentral::uCentralProtocol::OFF &&
Pattern != uCentral::uCentralProtocol::BLINK) {
GetS(uCentralProtocol::PATTERN, Obj, uCentralProtocol::BLINK);
if (Pattern != uCentralProtocol::ON &&
Pattern != uCentralProtocol::OFF &&
Pattern != uCentralProtocol::BLINK) {
Logger_.warning(Poco::format("LEDs(%s): Bad pattern", SerialNumber_));
BadRequest(Request, Response);
return;
}
auto Duration = Get(uCentral::uCentralProtocol::DURATION, Obj, 30);
auto Duration = Get(uCentralProtocol::DURATION, Obj, 30);
auto When = GetWhen(Obj);
Logger_.information(Poco::format("LEDS(%s): Pattern:%s Duration: %Lu", SerialNumber_,
Pattern, Duration));
@@ -632,14 +635,14 @@ void RESTAPI_device_commandHandler::LEDs(Poco::Net::HTTPServerRequest &Request,
Cmd.SerialNumber = SerialNumber_;
Cmd.UUID = Daemon()->CreateUUID();
Cmd.SubmittedBy = UserInfo_.webtoken.username_;
Cmd.Command = uCentral::uCentralProtocol::LEDS;
Cmd.Command = uCentralProtocol::LEDS;
Cmd.RunAt = When;
Poco::JSON::Object Params;
Params.set(uCentral::uCentralProtocol::SERIAL, SerialNumber_);
Params.set(uCentral::uCentralProtocol::DURATION, Duration);
Params.set(uCentral::uCentralProtocol::WHEN, When);
Params.set(uCentral::uCentralProtocol::PATTERN, Pattern);
Params.set(uCentralProtocol::SERIAL, SerialNumber_);
Params.set(uCentralProtocol::DURATION, Duration);
Params.set(uCentralProtocol::WHEN, When);
Params.set(uCentralProtocol::PATTERN, Pattern);
std::stringstream ParamStream;
Params.stringify(ParamStream);
@@ -649,7 +652,7 @@ void RESTAPI_device_commandHandler::LEDs(Poco::Net::HTTPServerRequest &Request,
return;
}
} catch (const Poco::Exception &E) {
Logger_.error(Poco::format("%s: failed with %s", std::string(__func__), E.displayText()));
Logger_.log(E);
}
BadRequest(Request, Response);
}
@@ -661,22 +664,22 @@ void RESTAPI_device_commandHandler::Trace(Poco::Net::HTTPServerRequest &Request,
Poco::JSON::Object::Ptr Obj =
parser.parse(Request.stream()).extract<Poco::JSON::Object::Ptr>();
if (Obj->has(uCentral::RESTAPI::Protocol::SERIALNUMBER) &&
(Obj->has(uCentral::RESTAPI::Protocol::NETWORK) ||
Obj->has(uCentral::RESTAPI::Protocol::INTERFACE))) {
if (Obj->has(RESTAPI::Protocol::SERIALNUMBER) &&
(Obj->has(RESTAPI::Protocol::NETWORK) ||
Obj->has(RESTAPI::Protocol::INTERFACE))) {
auto SNum = Obj->get(uCentral::RESTAPI::Protocol::SERIALNUMBER).toString();
auto SNum = Obj->get(RESTAPI::Protocol::SERIALNUMBER).toString();
if (SerialNumber_ != SNum) {
BadRequest(Request, Response);
BadRequest(Request, Response, "Missing serial number.");
return;
}
auto Duration = Get(uCentral::RESTAPI::Protocol::DURATION, Obj);
auto Duration = Get(RESTAPI::Protocol::DURATION, Obj, 30);
auto When = GetWhen(Obj);
auto NumberOfPackets = Get(uCentral::RESTAPI::Protocol::NUMBEROFPACKETS, Obj);
auto NumberOfPackets = Get(RESTAPI::Protocol::NUMBEROFPACKETS, Obj, 100);
auto Network = GetS(uCentral::RESTAPI::Protocol::NETWORK, Obj);
auto Interface = GetS(uCentral::RESTAPI::Protocol::INTERFACE, Obj);
auto Network = GetS(RESTAPI::Protocol::NETWORK, Obj);
auto Interface = GetS(RESTAPI::Protocol::INTERFACE, Obj);
auto UUID = Daemon()->CreateUUID();
auto URI = FileUploader()->FullName() + UUID;
@@ -684,31 +687,33 @@ void RESTAPI_device_commandHandler::Trace(Poco::Net::HTTPServerRequest &Request,
Cmd.SerialNumber = SerialNumber_;
Cmd.UUID = UUID;
Cmd.SubmittedBy = UserInfo_.webtoken.username_;
Cmd.Command = uCentral::uCentralProtocol::TRACE;
Cmd.Command = uCentralProtocol::TRACE;
Cmd.RunAt = When;
Cmd.WaitingForFile = 1;
Cmd.AttachType = uCentral::RESTAPI::Protocol::PCAP_FILE_TYPE;
Cmd.AttachType = RESTAPI::Protocol::PCAP_FILE_TYPE;
Poco::JSON::Object Params;
Params.set(uCentral::uCentralProtocol::SERIAL, SerialNumber_);
Params.set(uCentral::uCentralProtocol::DURATION, Duration);
Params.set(uCentral::uCentralProtocol::WHEN, When);
Params.set(uCentral::uCentralProtocol::PACKETS, NumberOfPackets);
Params.set(uCentral::uCentralProtocol::NETWORK, Network);
Params.set(uCentral::uCentralProtocol::INTERFACE, Interface);
Params.set(uCentral::uCentralProtocol::URI, URI);
Params.set(uCentralProtocol::SERIAL, SerialNumber_);
Params.set(uCentralProtocol::DURATION, Duration);
Params.set(uCentralProtocol::WHEN, When);
Params.set(uCentralProtocol::PACKETS, NumberOfPackets);
Params.set(uCentralProtocol::NETWORK, Network);
Params.set(uCentralProtocol::INTERFACE, Interface);
Params.set(uCentralProtocol::URI, URI);
std::stringstream ParamStream;
Params.stringify(ParamStream);
Cmd.Details = ParamStream.str();
FileUploader()->AddUUID(UUID);
RESTAPI_RPC::WaitForCommand(Cmd, Params, Request, Response, std::chrono::milliseconds(3000), nullptr, this);
return;
RESTAPI_RPC::WaitForCommand(Cmd, Params, Request, Response, std::chrono::milliseconds(5000), nullptr, this);
} else {
BadRequest(Request, Response, "Missing SerialNumber, Network, or Interface.");
}
return;
} catch (const Poco::Exception &E) {
Logger_.error(Poco::format("%s: failed with %s", std::string(__func__), E.displayText()));
Logger_.log(E);
}
BadRequest(Request, Response);
}
@@ -721,62 +726,64 @@ void RESTAPI_device_commandHandler::WifiScan(Poco::Net::HTTPServerRequest &Reque
Poco::JSON::Object::Ptr Obj =
parser.parse(Request.stream()).extract<Poco::JSON::Object::Ptr>();
auto SNum = Obj->get(uCentral::RESTAPI::Protocol::SERIALNUMBER).toString();
auto SNum = Obj->get(RESTAPI::Protocol::SERIALNUMBER).toString();
if (SerialNumber_ != SNum) {
BadRequest(Request, Response);
return;
}
if ((Obj->has(uCentral::RESTAPI::Protocol::BANDS) &&
Obj->isArray(uCentral::RESTAPI::Protocol::BANDS) ||
(Obj->has(uCentral::RESTAPI::Protocol::CHANNELS) &&
Obj->isArray(uCentral::RESTAPI::Protocol::CHANNELS)) ||
(!Obj->has(uCentral::RESTAPI::Protocol::BANDS) &&
!Obj->has(uCentral::RESTAPI::Protocol::CHANNELS)))) {
bool Verbose = GetB(uCentral::RESTAPI::Protocol::VERBOSE, Obj);
if ((Obj->has(RESTAPI::Protocol::BANDS) &&
Obj->isArray(RESTAPI::Protocol::BANDS) ||
(Obj->has(RESTAPI::Protocol::CHANNELS) &&
Obj->isArray(RESTAPI::Protocol::CHANNELS)) ||
(!Obj->has(RESTAPI::Protocol::BANDS) &&
!Obj->has(RESTAPI::Protocol::CHANNELS)))) {
bool Verbose = GetB(RESTAPI::Protocol::VERBOSE, Obj);
auto UUID = Daemon()->CreateUUID();
GWObjects::CommandDetails Cmd;
Cmd.SerialNumber = SerialNumber_;
Cmd.UUID = UUID;
Cmd.SubmittedBy = UserInfo_.webtoken.username_;
Cmd.Command = uCentral::uCentralProtocol::WIFISCAN;
Cmd.Command = uCentralProtocol::WIFISCAN;
Poco::JSON::Object Params;
Params.set(uCentral::uCentralProtocol::SERIAL, SerialNumber_);
Params.set(uCentral::uCentralProtocol::VERBOSE, Verbose);
Params.set(uCentralProtocol::SERIAL, SerialNumber_);
Params.set(uCentralProtocol::VERBOSE, Verbose);
if (Obj->has(uCentral::uCentralProtocol::BANDS)) {
Params.set(uCentral::uCentralProtocol::BANDS,
Obj->get(uCentral::RESTAPI::Protocol::BANDS));
} else if (Obj->has(uCentral::uCentralProtocol::CHANNELS)) {
Params.set(uCentral::uCentralProtocol::CHANNELS,
Obj->get(uCentral::RESTAPI::Protocol::CHANNELS));
if (Obj->has(uCentralProtocol::BANDS)) {
Params.set(uCentralProtocol::BANDS,
Obj->get(RESTAPI::Protocol::BANDS));
} else if (Obj->has(uCentralProtocol::CHANNELS)) {
Params.set(uCentralProtocol::CHANNELS,
Obj->get(RESTAPI::Protocol::CHANNELS));
}
if (Obj->has(uCentral::RESTAPI::Protocol::ACTIVESCAN)) {
if (Obj->has(RESTAPI::Protocol::ACTIVESCAN)) {
Params.set(
uCentral::uCentralProtocol::ACTIVE,
(int)(Obj->get(uCentral::RESTAPI::Protocol::ACTIVESCAN).toString() == "true")
uCentralProtocol::ACTIVE,
(int)(Obj->get(RESTAPI::Protocol::ACTIVESCAN).toString() == "true")
? 1
: 0);
} else {
Params.set(uCentral::uCentralProtocol::ACTIVE, 0);
Params.set(uCentralProtocol::ACTIVE, 0);
}
std::stringstream ParamStream;
Params.stringify(ParamStream);
Cmd.Details = ParamStream.str();
RESTAPI_RPC::WaitForCommand(Cmd, Params, Request, Response, std::chrono::milliseconds(20000), nullptr, this);
KafkaManager()->PostMessage(uCentral::KafkaTopics::WIFISCAN, SerialNumber_,
Cmd.Results);
if(Cmd.ErrorCode==0) {
KafkaManager()->PostMessage(KafkaTopics::WIFISCAN, SerialNumber_,
Cmd.Results);
}
return;
}
} catch (const Poco::Exception &E) {
Logger_.error(Poco::format("%s: failed with %s", std::string(__func__), E.displayText()));
Logger_.log(E);
}
BadRequest(Request, Response);
}
@@ -789,11 +796,11 @@ void RESTAPI_device_commandHandler::EventQueue(Poco::Net::HTTPServerRequest &Req
Poco::JSON::Object::Ptr Obj =
parser.parse(Request.stream()).extract<Poco::JSON::Object::Ptr>();
if (Obj->has(uCentral::RESTAPI::Protocol::SERIALNUMBER) &&
Obj->has(uCentral::RESTAPI::Protocol::TYPES) &&
Obj->isArray(uCentral::RESTAPI::Protocol::TYPES)) {
auto SNum = Obj->get(uCentral::RESTAPI::Protocol::SERIALNUMBER).toString();
auto Types = Obj->getArray(uCentral::RESTAPI::Protocol::TYPES);
if (Obj->has(RESTAPI::Protocol::SERIALNUMBER) &&
Obj->isArray(RESTAPI::Protocol::TYPES)) {
auto SNum = Obj->get(RESTAPI::Protocol::SERIALNUMBER).toString();
auto Types = Obj->getArray(RESTAPI::Protocol::TYPES);
if (SerialNumber_ == SNum) {
auto UUID = Daemon()->CreateUUID();
@@ -802,23 +809,26 @@ void RESTAPI_device_commandHandler::EventQueue(Poco::Net::HTTPServerRequest &Req
Cmd.SerialNumber = SerialNumber_;
Cmd.UUID = UUID;
Cmd.SubmittedBy = UserInfo_.webtoken.username_;
Cmd.Command = uCentral::uCentralProtocol::EVENT;
Cmd.Command = uCentralProtocol::EVENT;
Poco::JSON::Object Params;
Params.set(uCentral::uCentralProtocol::SERIAL, SerialNumber_);
Params.set(uCentral::uCentralProtocol::TYPES, Types);
Params.set(uCentralProtocol::SERIAL, SerialNumber_);
Params.set(uCentralProtocol::TYPES, Types);
std::stringstream ParamStream;
Params.stringify(ParamStream);
Cmd.Details = ParamStream.str();
RESTAPI_RPC::WaitForCommand(Cmd, Params, Request, Response, std::chrono::milliseconds(20000), nullptr, this);
if(Cmd.ErrorCode==0) {
KafkaManager()->PostMessage(KafkaTopics::DEVICE_EVENT_QUEUE, SerialNumber_,
Cmd.Results);
}
return;
}
}
} catch (const Poco::Exception &E) {
Logger_.error(Poco::format("%s: failed with %s", std::string(__func__), E.displayText()));
Logger_.log(E);
}
BadRequest(Request, Response);
}
@@ -831,15 +841,15 @@ void RESTAPI_device_commandHandler::MakeRequest(Poco::Net::HTTPServerRequest &Re
Poco::JSON::Object::Ptr Obj =
parser.parse(Request.stream()).extract<Poco::JSON::Object::Ptr>();
if (Obj->has(uCentral::RESTAPI::Protocol::SERIALNUMBER) &&
Obj->has(uCentral::uCentralProtocol::MESSAGE)) {
if (Obj->has(RESTAPI::Protocol::SERIALNUMBER) &&
Obj->has(uCentralProtocol::MESSAGE)) {
auto SNum = GetS(uCentral::RESTAPI::Protocol::SERIALNUMBER, Obj);
auto MessageType = GetS(uCentral::uCentralProtocol::MESSAGE, Obj);
auto SNum = GetS(RESTAPI::Protocol::SERIALNUMBER, Obj);
auto MessageType = GetS(uCentralProtocol::MESSAGE, Obj);
if ((SerialNumber_ != SNum) ||
(MessageType != uCentral::uCentralProtocol::STATE &&
MessageType != uCentral::uCentralProtocol::HEALTHCHECK)) {
(MessageType != uCentralProtocol::STATE &&
MessageType != uCentralProtocol::HEALTHCHECK)) {
BadRequest(Request, Response);
return;
}
@@ -850,15 +860,15 @@ void RESTAPI_device_commandHandler::MakeRequest(Poco::Net::HTTPServerRequest &Re
Cmd.SerialNumber = SerialNumber_;
Cmd.SubmittedBy = UserInfo_.webtoken.username_;
Cmd.UUID = Daemon()->CreateUUID();
Cmd.Command = uCentral::uCentralProtocol::REQUEST;
Cmd.Command = uCentralProtocol::REQUEST;
Cmd.RunAt = When;
Poco::JSON::Object Params;
Params.set(uCentral::uCentralProtocol::SERIAL, SerialNumber_);
Params.set(uCentral::uCentralProtocol::WHEN, When);
Params.set(uCentral::uCentralProtocol::MESSAGE, MessageType);
Params.set(uCentral::uCentralProtocol::REQUEST_UUID, Cmd.UUID);
Params.set(uCentralProtocol::SERIAL, SerialNumber_);
Params.set(uCentralProtocol::WHEN, When);
Params.set(uCentralProtocol::MESSAGE, MessageType);
Params.set(uCentralProtocol::REQUEST_UUID, Cmd.UUID);
std::stringstream ParamStream;
Params.stringify(ParamStream);
@@ -868,7 +878,7 @@ void RESTAPI_device_commandHandler::MakeRequest(Poco::Net::HTTPServerRequest &Re
return;
}
} catch (const Poco::Exception &E) {
Logger_.error(Poco::format("%s: failed with %s", std::string(__func__), E.displayText()));
Logger_.log(E);
}
BadRequest(Request, Response);
}
@@ -879,7 +889,7 @@ void RESTAPI_device_commandHandler::Rtty(Poco::Net::HTTPServerRequest &Request,
if (Daemon()->ConfigGetString("rtty.enabled", "false") == "true") {
GWObjects::Device Device;
if (Storage()->GetDevice(SerialNumber_, Device)) {
auto CommandUUID = uCentral::Daemon::instance()->CreateUUID();
auto CommandUUID = Daemon::instance()->CreateUUID();
GWObjects::RttySessionDetails Rtty{
.SerialNumber = SerialNumber_,
@@ -902,19 +912,19 @@ void RESTAPI_device_commandHandler::Rtty(Poco::Net::HTTPServerRequest &Request,
Cmd.SerialNumber = SerialNumber_;
Cmd.SubmittedBy = UserInfo_.webtoken.username_;
Cmd.UUID = CommandUUID;
Cmd.Command = uCentral::uCentralProtocol::RTTY;
Cmd.Command = uCentralProtocol::RTTY;
Poco::JSON::Object Params;
Params.set(uCentral::uCentralProtocol::METHOD, uCentral::uCentralProtocol::RTTY);
Params.set(uCentral::uCentralProtocol::SERIAL, SerialNumber_);
Params.set(uCentral::uCentralProtocol::ID, Rtty.ConnectionId);
Params.set(uCentral::uCentralProtocol::TOKEN, Rtty.Token);
Params.set(uCentral::uCentralProtocol::SERVER, Rtty.Server);
Params.set(uCentral::uCentralProtocol::PORT, Rtty.Port);
Params.set(uCentral::uCentralProtocol::USER, UserInfo_.webtoken.username_);
Params.set(uCentral::uCentralProtocol::TIMEOUT, Rtty.TimeOut);
Params.set(uCentral::uCentralProtocol::PASSWORD, Device.DevicePassword);
Params.set(uCentralProtocol::METHOD, uCentralProtocol::RTTY);
Params.set(uCentralProtocol::SERIAL, SerialNumber_);
Params.set(uCentralProtocol::ID, Rtty.ConnectionId);
Params.set(uCentralProtocol::TOKEN, Rtty.Token);
Params.set(uCentralProtocol::SERVER, Rtty.Server);
Params.set(uCentralProtocol::PORT, Rtty.Port);
Params.set(uCentralProtocol::USER, UserInfo_.webtoken.username_);
Params.set(uCentralProtocol::TIMEOUT, Rtty.TimeOut);
Params.set(uCentralProtocol::PASSWORD, Device.DevicePassword);
std::stringstream ParamStream;
Params.stringify(ParamStream);
@@ -930,7 +940,7 @@ void RESTAPI_device_commandHandler::Rtty(Poco::Net::HTTPServerRequest &Request,
return;
}
} catch (const Poco::Exception &E) {
Logger_.error(Poco::format("%s: failed with %s", std::string(__func__), E.displayText()));
Logger_.log(E);
}
BadRequest(Request, Response);
}

View File

@@ -11,7 +11,7 @@
#include "RESTAPI_handler.h"
namespace uCentral {
namespace OpenWifi {
class RESTAPI_device_commandHandler : public RESTAPIHandler {
public:
RESTAPI_device_commandHandler(const RESTAPIHandler::BindingMap &bindings, Poco::Logger &L, bool Internal)

View File

@@ -12,7 +12,7 @@
#include "StorageService.h"
#include "Utils.h"
namespace uCentral {
namespace OpenWifi {
void RESTAPI_device_handler::handleRequest(Poco::Net::HTTPServerRequest &Request,
Poco::Net::HTTPServerResponse &Response) {
if (!ContinueProcessing(Request, Response))
@@ -23,7 +23,7 @@ void RESTAPI_device_handler::handleRequest(Poco::Net::HTTPServerRequest &Request
ParseParameters(Request);
if (Request.getMethod() == Poco::Net::HTTPRequest::HTTP_GET) {
std::string SerialNumber = GetBinding(uCentral::RESTAPI::Protocol::SERIALNUMBER, "");
std::string SerialNumber = GetBinding(RESTAPI::Protocol::SERIALNUMBER, "");
GWObjects::Device Device;
if (Storage()->GetDevice(SerialNumber, Device)) {
@@ -34,7 +34,7 @@ void RESTAPI_device_handler::handleRequest(Poco::Net::HTTPServerRequest &Request
NotFound(Request, Response);
}
} else if (Request.getMethod() == Poco::Net::HTTPRequest::HTTP_DELETE) {
std::string SerialNumber = GetBinding(uCentral::RESTAPI::Protocol::SERIALNUMBER, "");
std::string SerialNumber = GetBinding(RESTAPI::Protocol::SERIALNUMBER, "");
if (Storage()->DeleteDevice(SerialNumber)) {
OK(Request, Response);
@@ -42,7 +42,7 @@ void RESTAPI_device_handler::handleRequest(Poco::Net::HTTPServerRequest &Request
NotFound(Request, Response);
}
} else if (Request.getMethod() == Poco::Net::HTTPRequest::HTTP_POST) {
std::string SerialNumber = GetBinding(uCentral::RESTAPI::Protocol::SERIALNUMBER, "");
std::string SerialNumber = GetBinding(RESTAPI::Protocol::SERIALNUMBER, "");
Poco::JSON::Parser IncomingParser;
Poco::JSON::Object::Ptr Obj =
@@ -57,7 +57,7 @@ void RESTAPI_device_handler::handleRequest(Poco::Net::HTTPServerRequest &Request
for(auto &i:Device.Notes)
i.createdBy = UserInfo_.userinfo.email;
if (!uCentral::Utils::ValidSerialNumber(Device.SerialNumber)) {
if (!Utils::ValidSerialNumber(Device.SerialNumber)) {
Logger_.warning(Poco::format("CREATE-DEVICE(%s): Illegal name.", Device.SerialNumber));
BadRequest(Request, Response);
return;
@@ -74,7 +74,7 @@ void RESTAPI_device_handler::handleRequest(Poco::Net::HTTPServerRequest &Request
BadRequest(Request, Response);
}
} else if (Request.getMethod() == Poco::Net::HTTPRequest::HTTP_PUT) {
std::string SerialNumber = GetBinding(uCentral::RESTAPI::Protocol::SERIALNUMBER, "");
std::string SerialNumber = GetBinding(RESTAPI::Protocol::SERIALNUMBER, "");
Poco::JSON::Parser IncomingParser;
Poco::JSON::Object::Ptr Obj =

View File

@@ -10,11 +10,10 @@
#define UCENTRAL_RESTAPI_DEVICEHANDLER_H
#include "RESTAPI_handler.h"
#include "Poco/Net/HTTPServerRequest.h"
#include "Poco/Net/HTTPServerResponse.h"
namespace uCentral {
namespace OpenWifi {
class RESTAPI_device_handler : public RESTAPIHandler {
public:
RESTAPI_device_handler(const RESTAPIHandler::BindingMap &bindings, Poco::Logger &L, bool Internal)

View File

@@ -16,7 +16,7 @@
#include "Utils.h"
namespace uCentral {
namespace OpenWifi {
void RESTAPI_devices_handler::handleRequest(Poco::Net::HTTPServerRequest &Request,
Poco::Net::HTTPServerResponse &Response) {
@@ -29,11 +29,14 @@ namespace uCentral {
try {
if (Request.getMethod() == Poco::Net::HTTPRequest::HTTP_GET) {
ParseParameters(Request);
InitQueryBlock();
auto serialOnly = GetBoolParameter(uCentral::RESTAPI::Protocol::SERIALONLY, false);
auto countOnly = GetBoolParameter(uCentral::RESTAPI::Protocol::COUNTONLY, false);
if(!InitQueryBlock()) {
BadRequest(Request, Response, "Illegal parameter value.");
return;
}
auto serialOnly = GetBoolParameter(RESTAPI::Protocol::SERIALONLY, false);
auto countOnly = GetBoolParameter(RESTAPI::Protocol::COUNTONLY, false);
auto deviceWithStatus =
GetBoolParameter(uCentral::RESTAPI::Protocol::DEVICEWITHSTATUS, false);
GetBoolParameter(RESTAPI::Protocol::DEVICEWITHSTATUS, false);
Logger_.debug(Poco::format("DEVICES: from %Lu, limit of %Lu, filter='%s'.",
(uint64_t)QB_.Offset, (uint64_t)QB_.Limit, QB_.Filter));
@@ -45,7 +48,7 @@ namespace uCentral {
if (!QB_.Select.empty()) {
Poco::JSON::Array Objects;
std::vector<std::string> Numbers = uCentral::Utils::Split(QB_.Select);
std::vector<std::string> Numbers = Utils::Split(QB_.Select);
for (auto &i : Numbers) {
GWObjects::Device D;
if (Storage()->GetDevice(i, D)) {
@@ -62,14 +65,14 @@ namespace uCentral {
}
if (deviceWithStatus)
RetObj.set(uCentral::RESTAPI::Protocol::DEVICESWITHSTATUS, Objects);
RetObj.set(RESTAPI::Protocol::DEVICESWITHSTATUS, Objects);
else
RetObj.set(uCentral::RESTAPI::Protocol::DEVICES, Objects);
RetObj.set(RESTAPI::Protocol::DEVICES, Objects);
} else if (countOnly == true) {
uint64_t Count = 0;
if (Storage()->GetDeviceCount(Count)) {
RetObj.set(uCentral::RESTAPI::Protocol::COUNT, Count);
RetObj.set(RESTAPI::Protocol::COUNT, Count);
}
} else if (serialOnly) {
std::vector<std::string> SerialNumbers;
@@ -78,7 +81,7 @@ namespace uCentral {
for (const auto &i : SerialNumbers) {
Objects.add(i);
}
RetObj.set(uCentral::RESTAPI::Protocol::SERIALNUMBERS, Objects);
RetObj.set(RESTAPI::Protocol::SERIALNUMBERS, Objects);
} else {
std::vector<GWObjects::Device> Devices;
Storage()->GetDevices(QB_.Offset, QB_.Limit, Devices);
@@ -92,9 +95,9 @@ namespace uCentral {
Objects.add(Obj);
}
if (deviceWithStatus)
RetObj.set(uCentral::RESTAPI::Protocol::DEVICESWITHSTATUS, Objects);
RetObj.set(RESTAPI::Protocol::DEVICESWITHSTATUS, Objects);
else
RetObj.set(uCentral::RESTAPI::Protocol::DEVICES, Objects);
RetObj.set(RESTAPI::Protocol::DEVICES, Objects);
}
ReturnObject(Request, RetObj, Response);
return;

View File

@@ -11,7 +11,7 @@
#include "RESTAPI_handler.h"
namespace uCentral {
namespace OpenWifi {
class RESTAPI_devices_handler : public RESTAPIHandler {
public:
RESTAPI_devices_handler(const RESTAPIHandler::BindingMap &bindings, Poco::Logger &L, bool Internal)

View File

@@ -15,7 +15,7 @@
#include <fstream>
#include "RESTAPI_protocol.h"
namespace uCentral {
namespace OpenWifi {
void RESTAPI_file::handleRequest(Poco::Net::HTTPServerRequest &Request,
Poco::Net::HTTPServerResponse &Response) {
if (!ContinueProcessing(Request, Response))
@@ -28,8 +28,8 @@ namespace uCentral {
ParseParameters(Request);
if (Request.getMethod() == Poco::Net::HTTPRequest::HTTP_GET) {
auto UUID = GetBinding(uCentral::RESTAPI::Protocol::FILEUUID, "");
auto SerialNumber = GetParameter(uCentral::RESTAPI::Protocol::SERIALNUMBER, "");
auto UUID = GetBinding(RESTAPI::Protocol::FILEUUID, "");
auto SerialNumber = GetParameter(RESTAPI::Protocol::SERIALNUMBER, "");
// does the file exist
Poco::File DownloadFile(FileUploader()->Path() + "/" + UUID);
@@ -45,7 +45,7 @@ namespace uCentral {
return;
} else if (Request.getMethod() == Poco::Net::HTTPRequest::HTTP_DELETE) {
auto UUID = GetBinding(uCentral::RESTAPI::Protocol::FILEUUID, "");
auto UUID = GetBinding(RESTAPI::Protocol::FILEUUID, "");
if (UUID.empty()) {
BadRequest(Request, Response);

View File

@@ -11,7 +11,7 @@
#include "RESTAPI_handler.h"
namespace uCentral {
namespace OpenWifi {
class RESTAPI_file : public RESTAPIHandler {
public:
RESTAPI_file(const RESTAPIHandler::BindingMap &bindings, Poco::Logger &L, bool Internal)

View File

@@ -27,16 +27,16 @@
#include "Utils.h"
#include "Daemon.h"
namespace uCentral {
namespace OpenWifi {
bool RESTAPIHandler::ParseBindings(const std::string & Request, const std::list<const char *> & EndPoints, BindingMap &bindings) {
std::string Param, Value;
bindings.clear();
std::vector<std::string> PathItems = uCentral::Utils::Split(Request, '/');
std::vector<std::string> PathItems = Utils::Split(Request, '/');
for(const auto &EndPoint:EndPoints) {
std::vector<std::string> ParamItems = uCentral::Utils::Split(EndPoint, '/');
std::vector<std::string> ParamItems = Utils::Split(EndPoint, '/');
if (PathItems.size() != ParamItems.size())
continue;
@@ -64,9 +64,9 @@ namespace uCentral {
}
void RESTAPIHandler::ParseParameters(Poco::Net::HTTPServerRequest &request) {
Poco::URI uri(request.getURI());
Parameters_ = uri.getQueryParameters();
InitQueryBlock();
}
static bool is_number(const std::string &s) {
@@ -111,6 +111,26 @@ namespace uCentral {
return Default;
}
bool RESTAPIHandler::HasParameter(const std::string &Name, std::string &Value) {
for (const auto &i : Parameters_) {
if (i.first == Name) {
Value = i.second;
return true;
}
}
return false;
}
bool RESTAPIHandler::HasParameter(const std::string &Name, uint64_t & Value) {
for (const auto &i : Parameters_) {
if (i.first == Name) {
Value = std::stoi(i.second);
return true;
}
}
return false;
}
const std::string &RESTAPIHandler::GetBinding(const std::string &Name, const std::string &Default) {
auto E = Bindings_.find(Poco::toLower(Name));
if (E == Bindings_.end())
@@ -364,18 +384,25 @@ namespace uCentral {
Poco::JSON::Stringifier::stringify(Object, Answer);
}
void RESTAPIHandler::InitQueryBlock() {
QB_.SerialNumber = GetParameter(uCentral::RESTAPI::Protocol::SERIALNUMBER, "");
QB_.StartDate = GetParameter(uCentral::RESTAPI::Protocol::STARTDATE, 0);
QB_.EndDate = GetParameter(uCentral::RESTAPI::Protocol::ENDDATE, 0);
QB_.Offset = GetParameter(uCentral::RESTAPI::Protocol::OFFSET, 0);
QB_.Limit = GetParameter(uCentral::RESTAPI::Protocol::LIMIT, 100);
QB_.Filter = GetParameter(uCentral::RESTAPI::Protocol::FILTER, "");
QB_.Select = GetParameter(uCentral::RESTAPI::Protocol::SELECT, "");
QB_.Lifetime = GetBoolParameter(uCentral::RESTAPI::Protocol::LIFETIME,false);
QB_.LogType = GetParameter(uCentral::RESTAPI::Protocol::LOGTYPE,0);
QB_.LastOnly = GetBoolParameter(uCentral::RESTAPI::Protocol::LASTONLY,false);
QB_.Newest = GetBoolParameter(uCentral::RESTAPI::Protocol::NEWEST,false);
bool RESTAPIHandler::InitQueryBlock() {
if(QueryBlockInitialized_)
return true;
QueryBlockInitialized_=true;
QB_.SerialNumber = GetParameter(RESTAPI::Protocol::SERIALNUMBER, "");
QB_.StartDate = GetParameter(RESTAPI::Protocol::STARTDATE, 0);
QB_.EndDate = GetParameter(RESTAPI::Protocol::ENDDATE, 0);
QB_.Offset = GetParameter(RESTAPI::Protocol::OFFSET, 1);
QB_.Limit = GetParameter(RESTAPI::Protocol::LIMIT, 100);
QB_.Filter = GetParameter(RESTAPI::Protocol::FILTER, "");
QB_.Select = GetParameter(RESTAPI::Protocol::SELECT, "");
QB_.Lifetime = GetBoolParameter(RESTAPI::Protocol::LIFETIME,false);
QB_.LogType = GetParameter(RESTAPI::Protocol::LOGTYPE,0);
QB_.LastOnly = GetBoolParameter(RESTAPI::Protocol::LASTONLY,false);
QB_.Newest = GetBoolParameter(RESTAPI::Protocol::NEWEST,false);
if(QB_.Offset<1)
QB_.Offset=1;
return true;
}
[[nodiscard]] uint64_t RESTAPIHandler::Get(const char *Parameter,const Poco::JSON::Object::Ptr &Obj, uint64_t Default){
@@ -397,7 +424,7 @@ namespace uCentral {
}
[[nodiscard]] uint64_t RESTAPIHandler::GetWhen(const Poco::JSON::Object::Ptr &Obj) {
return RESTAPIHandler::Get(uCentral::RESTAPI::Protocol::WHEN, Obj);
return RESTAPIHandler::Get(RESTAPI::Protocol::WHEN, Obj);
}

View File

@@ -26,7 +26,7 @@
#include "RESTAPI_SecurityObjects.h"
namespace uCentral {
namespace OpenWifi {
class RESTAPI_PartHandler: public Poco::Net::PartHandler
{
@@ -140,12 +140,14 @@ namespace uCentral {
void SendFile(Poco::File & File, Poco::Net::HTTPServerRequest &Request, Poco::Net::HTTPServerResponse &Response);
const std::string &GetBinding(const std::string &Name, const std::string &Default);
void InitQueryBlock();
bool InitQueryBlock();
[[nodiscard]] static uint64_t Get(const char *Parameter,const Poco::JSON::Object::Ptr &Obj, uint64_t Default=0);
[[nodiscard]] static std::string GetS(const char *Parameter,const Poco::JSON::Object::Ptr &Obj, const std::string & Default="");
[[nodiscard]] static bool GetB(const char *Parameter,const Poco::JSON::Object::Ptr &Obj, bool Default=false);
[[nodiscard]] static uint64_t GetWhen(const Poco::JSON::Object::Ptr &Obj);
bool HasParameter(const std::string &QueryParameter, std::string &Value);
bool HasParameter(const std::string &QueryParameter, uint64_t & Value);
protected:
BindingMap Bindings_;
@@ -156,6 +158,7 @@ namespace uCentral {
std::vector<std::string> Methods_;
QueryBlock QB_;
bool Internal_=false;
bool QueryBlockInitialized_=false;
};
class RESTAPI_UnknownRequestHandler : public RESTAPIHandler {
@@ -166,7 +169,7 @@ namespace uCentral {
Poco::Net::HTTPServerResponse &Response) override {
if (!IsAuthorized(Request, Response))
return;
BadRequest(Request, Response);
BadRequest(Request, Response, "Unknown API endpoint");
}
};

View File

@@ -7,7 +7,7 @@
#include "Utils.h"
#include "OUIServer.h"
namespace uCentral {
namespace OpenWifi {
void RESTAPI_ouis::handleRequest(Poco::Net::HTTPServerRequest &Request, Poco::Net::HTTPServerResponse &Response) {
if (!ContinueProcessing(Request, Response))
@@ -21,7 +21,7 @@ namespace uCentral {
if (Request.getMethod() == Poco::Net::HTTPRequest::HTTP_GET) {
Poco::JSON::Array Objects;
auto Select = GetParameter("macList","");
std::vector<std::string> Macs = uCentral::Utils::Split(Select);
std::vector<std::string> Macs = Utils::Split(Select);
for (auto &i : Macs) {
Poco::JSON::Object O;
auto Manufacturer = OUIServer()->GetManufacturer(i);

View File

@@ -7,7 +7,7 @@
#include "RESTAPI_handler.h"
namespace uCentral {
namespace OpenWifi {
class RESTAPI_ouis : public RESTAPIHandler {
public:
RESTAPI_ouis(const RESTAPIHandler::BindingMap &bindings, Poco::Logger &L, bool Internal)

View File

@@ -9,7 +9,7 @@
#ifndef UCENTRALGW_RESTAPI_PROTOCOL_H
#define UCENTRALGW_RESTAPI_PROTOCOL_H
namespace uCentral::RESTAPI::Protocol {
namespace OpenWifi::RESTAPI::Protocol {
static const char * CAPABILITIES = "capabilities";
static const char * LOGS = "logs";
static const char * HEALTHCHECKS = "healthchecks";

View File

@@ -24,8 +24,9 @@
#include "RESTAPI_deviceDashboardHandler.h"
#include "Utils.h"
#include "RESTAPI_webSocketServer.h"
namespace uCentral {
namespace OpenWifi {
class RESTAPI_server *RESTAPI_server::instance_ = nullptr;
@@ -67,7 +68,7 @@ namespace uCentral {
Poco::Net::HTTPRequestHandler *RESTAPIServerRequestHandlerFactory::createRequestHandler(const Poco::Net::HTTPServerRequest & Request) {
Logger_.debug(Poco::format("REQUEST(%s): %s %s", uCentral::Utils::FormatIPv6(Request.clientAddress().toString()), Request.getMethod(), Request.getURI()));
Logger_.debug(Poco::format("REQUEST(%s): %s %s", Utils::FormatIPv6(Request.clientAddress().toString()), Request.getMethod(), Request.getURI()));
Poco::URI uri(Request.getURI());
const auto & Path = uri.getPath();
@@ -85,6 +86,7 @@ namespace uCentral {
RESTAPI_file,
RESTAPI_system_command,
RESTAPI_deviceDashboardHandler,
RESTAPI_webSocketServer,
RESTAPI_BlackList>(Path,Bindings,Logger_);
}

View File

@@ -17,7 +17,7 @@
#include "Poco/Net/HTTPServerRequest.h"
#include "Poco/Net/NetException.h"
namespace uCentral {
namespace OpenWifi {
class RESTAPI_server : public SubSystemServer {

View File

@@ -13,7 +13,7 @@
#include "Daemon.h"
#include "RESTAPI_protocol.h"
namespace uCentral {
namespace OpenWifi {
void RESTAPI_system_command::handleRequest(Poco::Net::HTTPServerRequest &Request,
Poco::Net::HTTPServerResponse &Response) {
@@ -27,8 +27,8 @@ namespace uCentral {
DoPost(Request, Response);
else if(Request.getMethod()==Poco::Net::HTTPRequest::HTTP_GET)
DoGet(Request, Response);
BadRequest(Request, Response);
else
BadRequest(Request, Response, "Unsupported method.");
}
void RESTAPI_system_command::DoPost(Poco::Net::HTTPServerRequest &Request, Poco::Net::HTTPServerResponse &Response) {
@@ -36,19 +36,19 @@ namespace uCentral {
Poco::JSON::Parser parser;
auto Obj = parser.parse(Request.stream()).extract<Poco::JSON::Object::Ptr>();
if (Obj->has(uCentral::RESTAPI::Protocol::COMMAND)) {
auto Command = Poco::toLower(Obj->get(uCentral::RESTAPI::Protocol::COMMAND).toString());
if (Command == uCentral::RESTAPI::Protocol::SETLOGLEVEL) {
if (Obj->has(uCentral::RESTAPI::Protocol::PARAMETERS) &&
Obj->isArray(uCentral::RESTAPI::Protocol::PARAMETERS)) {
auto ParametersBlock = Obj->getArray(uCentral::RESTAPI::Protocol::PARAMETERS);
if (Obj->has(RESTAPI::Protocol::COMMAND)) {
auto Command = Poco::toLower(Obj->get(RESTAPI::Protocol::COMMAND).toString());
if (Command == RESTAPI::Protocol::SETLOGLEVEL) {
if (Obj->has(RESTAPI::Protocol::PARAMETERS) &&
Obj->isArray(RESTAPI::Protocol::PARAMETERS)) {
auto ParametersBlock = Obj->getArray(RESTAPI::Protocol::PARAMETERS);
for (const auto &i:*ParametersBlock) {
Poco::JSON::Parser pp;
auto InnerObj = pp.parse(i).extract<Poco::JSON::Object::Ptr>();
if (InnerObj->has(uCentral::RESTAPI::Protocol::TAG) &&
InnerObj->has(uCentral::RESTAPI::Protocol::VALUE)) {
auto Name = GetS(uCentral::RESTAPI::Protocol::TAG, InnerObj);
auto Value = GetS(uCentral::RESTAPI::Protocol::VALUE, InnerObj);
if (InnerObj->has(RESTAPI::Protocol::TAG) &&
InnerObj->has(RESTAPI::Protocol::VALUE)) {
auto Name = GetS(RESTAPI::Protocol::TAG, InnerObj);
auto Value = GetS(RESTAPI::Protocol::VALUE, InnerObj);
Daemon()->SetSubsystemLogLevel(Name, Value);
Logger_.information(Poco::format("Setting log level for %s at %s", Name, Value));
}
@@ -56,45 +56,45 @@ namespace uCentral {
OK(Request, Response);
return;
}
} else if (Command == uCentral::RESTAPI::Protocol::GETLOGLEVELS) {
} else if (Command == RESTAPI::Protocol::GETLOGLEVELS) {
auto CurrentLogLevels = Daemon()->GetLogLevels();
Poco::JSON::Object Result;
Poco::JSON::Array Array;
for(auto &[Name,Level]:CurrentLogLevels) {
Poco::JSON::Object Pair;
Pair.set( uCentral::RESTAPI::Protocol::TAG,Name);
Pair.set(uCentral::RESTAPI::Protocol::VALUE,Level);
Pair.set( RESTAPI::Protocol::TAG,Name);
Pair.set(RESTAPI::Protocol::VALUE,Level);
Array.add(Pair);
}
Result.set(uCentral::RESTAPI::Protocol::TAGLIST,Array);
Result.set(RESTAPI::Protocol::TAGLIST,Array);
ReturnObject(Request,Result,Response);
return;
} else if (Command == uCentral::RESTAPI::Protocol::GETLOGLEVELNAMES) {
} else if (Command == RESTAPI::Protocol::GETLOGLEVELNAMES) {
Poco::JSON::Object Result;
Poco::JSON::Array LevelNamesArray;
const Types::StringVec & LevelNames = Daemon()->GetLogLevelNames();
for(const auto &i:LevelNames)
LevelNamesArray.add(i);
Result.set(uCentral::RESTAPI::Protocol::LIST,LevelNamesArray);
Result.set(RESTAPI::Protocol::LIST,LevelNamesArray);
ReturnObject(Request,Result,Response);
return;
} else if (Command == uCentral::RESTAPI::Protocol::GETSUBSYSTEMNAMES) {
} else if (Command == RESTAPI::Protocol::GETSUBSYSTEMNAMES) {
Poco::JSON::Object Result;
Poco::JSON::Array LevelNamesArray;
const Types::StringVec & SubSystemNames = Daemon()->GetSubSystems();
for(const auto &i:SubSystemNames)
LevelNamesArray.add(i);
Result.set(uCentral::RESTAPI::Protocol::LIST,LevelNamesArray);
Result.set(RESTAPI::Protocol::LIST,LevelNamesArray);
ReturnObject(Request,Result,Response);
return;
} else if (Command == uCentral::RESTAPI::Protocol::STATS) {
} else if (Command == RESTAPI::Protocol::STATS) {
}
}
} catch(const Poco::Exception &E) {
Logger_.log(E);
}
BadRequest(Request, Response);
BadRequest(Request, Response, "Unsupported or missing parameters.");
}
void RESTAPI_system_command::DoGet(Poco::Net::HTTPServerRequest &Request, Poco::Net::HTTPServerResponse &Response) {
@@ -126,7 +126,7 @@ namespace uCentral {
} catch (const Poco::Exception &E) {
Logger_.log(E);
}
BadRequest(Request, Response);
BadRequest(Request, Response, "Unsupported or missing parameters.");
}
}

View File

@@ -11,7 +11,7 @@
#include "RESTAPI_handler.h"
namespace uCentral {
namespace OpenWifi {
class RESTAPI_system_command : public RESTAPIHandler {
public:
RESTAPI_system_command(const RESTAPIHandler::BindingMap &bindings, Poco::Logger &L, bool Internal)

View File

@@ -4,7 +4,7 @@
#include "RESTAPI_utils.h"
namespace uCentral::RESTAPI_utils {
namespace OpenWifi::RESTAPI_utils {
void EmbedDocument(const std::string & ObjName, Poco::JSON::Object & Obj, const std::string &ObjStr) {
std::string D = ObjStr.empty() ? "{}" : ObjStr;

View File

@@ -9,10 +9,10 @@
#include "Poco/JSON/Object.h"
#include "Poco/JSON/Parser.h"
#include "Poco/Net/HTTPServerRequest.h"
#include "uCentralTypes.h"
#include "OpenWifiTypes.h"
#include "Utils.h"
namespace uCentral::RESTAPI_utils {
namespace OpenWifi::RESTAPI_utils {
void EmbedDocument(const std::string & ObjName, Poco::JSON::Object & Obj, const std::string &ObjStr);

View File

@@ -0,0 +1,151 @@
//
// Created by stephane bourque on 2021-08-12.
//
#include "RESTAPI_webSocketServer.h"
#include "Poco/Net/WebSocket.h"
#include "Poco/Net/HTTPResponse.h"
#include "Poco/JSON/Object.h"
#include "Poco/JSON/Parser.h"
#include "Poco/JSON/Stringifier.h"
#include "SerialNumberCache.h"
#include "Utils.h"
#include "AuthClient.h"
namespace OpenWifi {
void RESTAPI_webSocketServer::handleRequest(Poco::Net::HTTPServerRequest &Request, Poco::Net::HTTPServerResponse &Response) {
if (!ContinueProcessing(Request, Response))
return;
if(Request.getMethod()==Poco::Net::HTTPRequest::HTTP_GET)
DoGet(Request,Response);
else
BadRequest(Request, Response, "Can only do get for WebSocket.");
}
void RESTAPI_webSocketServer::DoGet(Poco::Net::HTTPServerRequest &Request, Poco::Net::HTTPServerResponse &Response) {
// try and upgrade this session to websocket...
if(Request.find("Upgrade") != Request.end() && Poco::icompare(Request["Upgrade"], "websocket") == 0) {
try
{
Poco::Net::WebSocket WS(Request, Response);
Logger_.information("WebSocket connection established.");
int flags;
int n;
bool Authenticated=false;
bool Done=false;
do
{
Poco::Buffer<char> IncomingFrame(0);
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: {
IncomingFrame.append(0);
if(!Authenticated) {
std::string Frame{IncomingFrame.begin()};
auto Tokens = Utils::Split(Frame,':');
if(Tokens.size()==2 && AuthClient()->IsTokenAuthorized(Tokens[1], UserInfo_)) {
Authenticated=true;
std::string S{"Welcome! Bienvenue! Bienvenidos!"};
WS.sendFrame(S.c_str(),S.size());
} else {
std::string S{"Invalid token. Closing connection."};
WS.sendFrame(S.c_str(),S.size());
Done=true;
}
} else {
try {
Poco::JSON::Parser P;
auto Obj = P.parse(IncomingFrame.begin())
.extract<Poco::JSON::Object::Ptr>();
std::string Answer;
Process(Obj, Answer);
if (!Answer.empty())
WS.sendFrame(Answer.c_str(), Answer.size());
else {
WS.sendFrame("{}", 2);
}
} catch (const Poco::JSON::JSONException & E) {
Logger_.log(E);
}
}
}
break;
default:
{
}
}
}
while (!Done && (n > 0 && (flags & Poco::Net::WebSocket::FRAME_OP_BITMASK) != Poco::Net::WebSocket::FRAME_OP_CLOSE));
Logger_.information("WebSocket connection closed.");
}
catch (const Poco::Net::WebSocketException & E)
{
Logger_.log(E);
switch (E.code())
{
case Poco::Net::WebSocket::WS_ERR_HANDSHAKE_UNSUPPORTED_VERSION:
Response.set("Sec-WebSocket-Version", Poco::Net::WebSocket::WEBSOCKET_VERSION);
// fallthrough
case Poco::Net::WebSocket::WS_ERR_NO_HANDSHAKE:
case Poco::Net::WebSocket::WS_ERR_HANDSHAKE_NO_VERSION:
case Poco::Net::WebSocket::WS_ERR_HANDSHAKE_NO_KEY:
Response.setStatusAndReason(Poco::Net::HTTPResponse::HTTP_BAD_REQUEST);
Response.setContentLength(0);
Response.send();
break;
}
}
catch (const Poco::Exception &E) {
Logger_.log(E);
}
}
}
void RESTAPI_webSocketServer::Process(const Poco::JSON::Object::Ptr &O, std::string &Answer ) {
try {
if (O->has("command")) {
auto Command = O->get("command").toString();
if (Command == "serial_number_search" && O->has("serial_prefix")) {
auto Prefix = O->get("serial_prefix").toString();
uint64_t HowMany = 32;
if (O->has("howMany"))
HowMany = O->get("howMany");
Logger_.information(Poco::format("serial_number_search: %s", Prefix));
if (!Prefix.empty() && Prefix.length() < 13) {
std::vector<uint64_t> Numbers;
SerialNumberCache()->FindNumbers(Prefix, 50, Numbers);
Poco::JSON::Array A;
for (const auto &i : Numbers)
A.add(Utils::int_to_hex(i));
Poco::JSON::Object AO;
AO.set("serialNumbers", A);
AO.set("command","serial_number_search");
std::ostringstream SS;
Poco::JSON::Stringifier::stringify(AO, SS);
Answer = SS.str();
}
}
}
} catch (const Poco::Exception &E) {
Logger_.log(E);
}
}
}

View File

@@ -0,0 +1,30 @@
//
// Created by stephane bourque on 2021-08-12.
//
#ifndef UCENTRALGW_RESTAPI_WEBSOCKETSERVER_H
#define UCENTRALGW_RESTAPI_WEBSOCKETSERVER_H
class RESTAPI_webSocketServer {};
#include "RESTAPI_handler.h"
namespace OpenWifi {
class RESTAPI_webSocketServer : public RESTAPIHandler {
public:
RESTAPI_webSocketServer(const RESTAPIHandler::BindingMap &bindings, Poco::Logger &L, bool Internal)
: RESTAPIHandler(bindings, L,
std::vector<std::string>{Poco::Net::HTTPRequest::HTTP_GET,
Poco::Net::HTTPRequest::HTTP_OPTIONS},
Internal) {}
void handleRequest(Poco::Net::HTTPServerRequest &Request,
Poco::Net::HTTPServerResponse &Response) override final;
static const std::list<const char *> PathName() { return std::list<const char *>{"/api/v1/ws"};}
void DoGet(Poco::Net::HTTPServerRequest &Request,
Poco::Net::HTTPServerResponse &Response);
private:
void Process(const Poco::JSON::Object::Ptr &O, std::string &Answer);
};
}
#endif // UCENTRALGW_RESTAPI_WEBSOCKETSERVER_H

73
src/SerialNumberCache.cpp Normal file
View File

@@ -0,0 +1,73 @@
//
// Created by stephane bourque on 2021-08-11.
//
#include "SerialNumberCache.h"
#include <mutex>
#include "Utils.h"
#include "StorageService.h"
namespace OpenWifi {
class SerialNumberCache * SerialNumberCache::instance_ = nullptr;
int SerialNumberCache::Start() {
Storage()->UpdateSerialNumberCache();
return 0;
}
void SerialNumberCache::Stop() {
}
void SerialNumberCache::AddSerialNumber(const std::string &S) {
std::lock_guard G(M_);
uint64_t SN = std::stoull(S,0,16);
if(std::find(SNs_.begin(),SNs_.end(),SN) == SNs_.end()) {
if(SNs_.size()+1 == SNs_.capacity())
SNs_.resize(SNs_.capacity()+2000);
SNs_.push_back(SN);
std::sort(SNs_.begin(),SNs_.end());
}
}
void SerialNumberCache::DeleteSerialNumber(const std::string &S) {
std::lock_guard G(M_);
uint64_t SN = std::stoull(S,0,16);
auto It = std::find(SNs_.begin(),SNs_.end(),SN);
if(It != SNs_.end()) {
SNs_.erase(It);
}
}
void SerialNumberCache::FindNumbers(const std::string &S, uint HowMany, std::vector<uint64_t> &A) {
std::lock_guard G(M_);
if(S.length()==12) {
uint64_t SN = std::stoull(S,0,16);
auto It = std::find(SNs_.begin(),SNs_.end(),SN);
if(It != SNs_.end()) {
A.push_back(*It);
}
} else if (S.length()<12){
std::string SS{S};
SS.insert(SS.end(), 12 - SS.size(), '0');
uint64_t SN = std::stoull(SS,0,16);
auto LB = std::lower_bound(SNs_.begin(),SNs_.end(),SN);
if(LB!=SNs_.end()) {
for(;LB!=SNs_.end() && HowMany;++LB,--HowMany) {
std::string TSN = Utils::int_to_hex(*LB);
if(S == TSN.substr(0,S.size())) {
A.emplace_back(*LB);
} else {
break;
}
}
}
}
}
}

44
src/SerialNumberCache.h Normal file
View File

@@ -0,0 +1,44 @@
//
// Created by stephane bourque on 2021-08-11.
//
#ifndef UCENTRALGW_SERIALNUMBERCACHE_H
#define UCENTRALGW_SERIALNUMBERCACHE_H
#include "SubSystemServer.h"
namespace OpenWifi {
class SerialNumberCache : public SubSystemServer {
public:
static SerialNumberCache *instance() {
if (instance_ == nullptr) {
instance_ = new SerialNumberCache;
}
return instance_;
}
int Start() override;
void Stop() override;
void AddSerialNumber(const std::string &S);
void DeleteSerialNumber(const std::string &S);
void FindNumbers(const std::string &S, uint HowMany, std::vector<uint64_t> &A);
private:
static SerialNumberCache * instance_;
uint64_t LastUpdate_ = 0 ;
std::vector<uint64_t> SNs_;
std::mutex M_;
SerialNumberCache() noexcept:
SubSystemServer("SerialNumberCache", "SNCACHE-SVR", "serialcache")
{
SNs_.reserve(2000);
}
};
inline SerialNumberCache * SerialNumberCache() { return SerialNumberCache::instance(); }
} // namespace OpenWiFi
#endif // UCENTRALGW_SERIALNUMBERCACHE_H

View File

@@ -7,7 +7,7 @@
#include "Poco/JSON/Parser.h"
namespace uCentral {
namespace OpenWifi {
bool StateProcessor::Add(const Poco::JSON::Object::Ptr & O) {
try {
@@ -43,6 +43,10 @@ namespace uCentral {
return false;
}
}
if(Conn_)
GetAssociations(O,Conn_->Associations_2G,Conn_->Associations_5G);
if(UpdatesSinceLastWrite_>10)
Save();
return true;
@@ -129,4 +133,52 @@ namespace uCentral {
std::string StatsToSave = toString();
return Storage()->SetLifetimeStats(SerialNumber_, StatsToSave);
}
static int ChannelToBand(uint64_t C) {
if(C>=1 && C<=16) return 2;
return 5;
}
bool StateProcessor::GetAssociations(const Poco::JSON::Object::Ptr &RawObject, uint64_t &Radios_2G, uint64_t &Radios_5G) {
Radios_2G = 0 ;
Radios_5G = 0;
if(RawObject->isArray("radios") && RawObject->isArray("interfaces")) {
auto RA = RawObject->getArray("radios");
// map of phy to 2g/5g
std::map<std::string,int> RadioPHYs;
// parse radios and get the phy out with the band
for(auto const &i:*RA) {
Poco::JSON::Parser p2;
auto RadioObj = i.extract<Poco::JSON::Object::Ptr>();
if(RadioObj->has("phy") && RadioObj->has("channel")) {
RadioPHYs[RadioObj->get("phy").toString()]= ChannelToBand(RadioObj->get("channel"));
}
}
auto IA = RawObject->getArray("interfaces");
for(auto const &i:*IA) {
auto InterfaceObj = i.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();
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();
else
Radios_5G+=AssocA->size();
}
}
}
}
return true;
}
return false;
}
}

View File

@@ -7,10 +7,13 @@
#include <map>
#include "Poco/JSON/Object.h"
#include "RESTAPI_GWobjects.h"
namespace uCentral {
namespace OpenWifi {
class StateProcessor {
public:
StateProcessor(GWObjects::ConnectionState * Conn):
Conn_(Conn) {}
~StateProcessor() {
Save();
@@ -24,13 +27,15 @@ namespace uCentral {
[[nodiscard]] std::string toString() const;
bool Initialize(std::string & SerialNumber);
bool Save();
static bool GetAssociations(const Poco::JSON::Object::Ptr &Ptr, uint64_t &Radios_2G, uint64_t &Radios_5G);
private:
std::string SerialNumber_;
std::string SerialNumber_;
Poco::JSON::Object State_;
// interface name is the key, each entry is a map with the stats name as key and then the value
std::map<std::string,std::map<std::string,uint64_t>> Stats_;
uint64_t UpdatesSinceLastWrite_ = 0 ;
uint64_t UpdatesSinceLastWrite_ = 0 ;
GWObjects::ConnectionState * Conn_ = nullptr;
};
}

View File

@@ -10,7 +10,7 @@
#include "Daemon.h"
#include "Utils.h"
namespace uCentral {
namespace OpenWifi {
class StorageArchiver *StorageArchiver::instance_ = nullptr;
@@ -126,6 +126,7 @@ namespace uCentral {
if(Running_) {
Running_=false;
Janitor_.wakeUp();
Janitor_.wakeUp();
Janitor_.join();
}
}

View File

@@ -9,7 +9,7 @@
#include "SubSystemServer.h"
namespace uCentral {
namespace OpenWifi {
struct ArchiverDBEntry {
std::string DBName;

View File

@@ -12,15 +12,10 @@
#include "Poco/Util/Application.h"
#include "Utils.h"
namespace uCentral {
namespace OpenWifi {
class Storage *Storage::instance_ = nullptr;
Storage::Storage() noexcept:
SubSystemServer("Storage", "STORAGE-SVR", "storage")
{
}
std::string Storage::ConvertParams(const std::string & S) const {
std::string R;

View File

@@ -21,7 +21,7 @@
#include "RESTAPI_GWobjects.h"
#include "SubSystemServer.h"
namespace uCentral {
namespace OpenWifi {
class Storage : public SubSystemServer {
@@ -81,6 +81,7 @@ namespace uCentral {
bool GetDevicesWithoutFirmware(std::string &DeviceType, std::string &Version, std::vector<std::string> & SerialNumbers);
bool GetDeviceFWUpdatePolicy(std::string & SerialNumber, std::string & Policy);
bool SetDevicePassword(std::string & SerialNumber, std::string & Password);
bool UpdateSerialNumberCache();
bool ExistingConfiguration(std::string &SerialNumber, uint64_t CurrentConfig, std::string &NewConfig, uint64_t &);
@@ -111,6 +112,7 @@ namespace uCentral {
bool CommandExecuted(std::string & UUID);
bool CommandCompleted(std::string & UUID, const Poco::JSON::Object::Ptr & ReturnVars, bool FullCommand);
bool AttachFileToCommand(std::string & UUID);
bool CancelWaitFile( std::string & UUID, std::string & ErrorText );
bool GetAttachedFile(std::string & UUID, std::string & SerialNumber, const std::string & FileName, std::string &Type);
bool RemoveAttachedFile(std::string & UUID);
bool SetCommandResult(std::string & UUID, std::string & Result);
@@ -144,16 +146,22 @@ namespace uCentral {
int Create_LifetimeStats();
bool AnalyzeCommands(Types::CountedMap &R);
bool AnalyzeDevices(GWObjects::Dashboard &D);
int Start() override;
void Stop() override;
int Setup_SQLite();
[[nodiscard]] std::string ConvertParams(const std::string &S) const;
#ifndef SMALL_BUILD
int Setup_MySQL();
int Setup_PostgreSQL();
#endif
[[nodiscard]] std::string ConvertParams(const std::string &S) const;
[[nodiscard]] inline std::string ComputeRange(uint64_t From, uint64_t HowMany) {
if(dbType_==sqlite) {
return " LIMIT " + std::to_string(From-1) + ", " + std::to_string(HowMany) + " ";
} else if(dbType_==pgsql) {
return " LIMIT " + std::to_string(HowMany) + " OFFSET " + std::to_string(From-1) + " ";
} else if(dbType_==mysql) {
return " LIMIT " + std::to_string(HowMany) + " OFFSET " + std::to_string(From-1) + " ";
}
return " LIMIT " + std::to_string(HowMany) + " OFFSET " + std::to_string(From-1) + " ";
}
private:
static Storage *instance_;
@@ -165,7 +173,15 @@ namespace uCentral {
std::unique_ptr<Poco::Data::MySQL::Connector> MySQLConn_= nullptr;
#endif
Storage() noexcept;
Storage() noexcept:
SubSystemServer("Storage", "STORAGE-SVR", "storage")
{
}
int Setup_SQLite();
int Setup_MySQL();
int Setup_PostgreSQL();
};
inline Storage * Storage() { return Storage::instance(); }

View File

@@ -19,7 +19,7 @@
#include "Daemon.h"
namespace uCentral {
namespace OpenWifi {
SubSystemServer::SubSystemServer(std::string Name, const std::string &LoggingPrefix,
std::string SubSystemConfigPrefix)
: Name_(std::move(Name)), Logger_(Poco::Logger::get(LoggingPrefix)),

View File

@@ -23,7 +23,7 @@
using SubMutex = std::recursive_mutex;
using SubMutexGuard = std::lock_guard<SubMutex>;
namespace uCentral {
namespace OpenWifi {
class PropertiesFileServerEntry {
public:
PropertiesFileServerEntry(std::string Address, uint32_t port, std::string Key_file,

View File

@@ -28,7 +28,7 @@
#include "uCentralProtocol.h"
#include "Daemon.h"
namespace uCentral::Utils {
namespace OpenWifi::Utils {
[[nodiscard]] bool ValidSerialNumber(const std::string &Serial) {
return ((Serial.size() < uCentralProtocol::SERIAL_NUMBER_LENGTH) &&

View File

@@ -11,16 +11,18 @@
#include <vector>
#include <string>
#include <iomanip>
#include <sstream>
#include "Poco/Net/NetworkInterface.h"
#include "Poco/Net/IPAddress.h"
#include "Poco/String.h"
#include "Poco/File.h"
#include "uCentralTypes.h"
#include "OpenWifiTypes.h"
#define DBGLINE { std::cout << __FILE__ << ":" << __func__ << ":" << __LINE__ << std::endl; };
namespace uCentral::Utils {
namespace OpenWifi::Utils {
enum MediaTypeEncodings {
PLAIN,
@@ -73,5 +75,16 @@ namespace uCentral::Utils {
[[nodiscard]] std::string SecondsToNiceText(uint64_t Seconds);
[[nodiscard]] bool IPinRange(const std::string &Range, const Poco::Net::IPAddress &IP);
template< typename T >
std::string int_to_hex( T i )
{
std::stringstream stream;
stream << std::setfill ('0') << std::setw(12)
<< std::hex << i;
return stream.str();
}
}
#endif // UCENTRALGW_UTILS_H

View File

@@ -25,12 +25,11 @@
#include "WebSocketServer.h"
#include "uCentralProtocol.h"
namespace uCentral {
namespace OpenWifi {
class WebSocketServer *WebSocketServer::instance_ = nullptr;
WebSocketServer::WebSocketServer() noexcept: SubSystemServer("WebSocketServer", "WS-SVR", "ucentral.websocket"),
Factory_(Logger_)
WebSocketServer::WebSocketServer() noexcept: SubSystemServer("WebSocketServer", "WS-SVR", "ucentral.websocket")
{
}
@@ -63,158 +62,137 @@ namespace uCentral {
IssuerCert_ = std::make_unique<Poco::Crypto::X509Certificate>(Svr.IssuerCertFile());
Logger_.information(Poco::format("Certificate Issuer Name:%s",IssuerCert_->issuerName()));
}
auto NewSocketReactor = std::make_unique<Poco::Net::SocketReactor>();
auto NewSocketAcceptor = std::make_unique<Poco::Net::SocketAcceptor<WSConnection>>( Sock, *NewSocketReactor);
auto NewThread = std::make_unique<Poco::Thread>();
NewThread->setName("WebSocketAcceptor."+Svr.Address()+":"+std::to_string(Svr.Port()));
NewThread->start(*NewSocketReactor);
WebSocketServerEntry WSE { .SocketReactor{std::move(NewSocketReactor)} ,
.SocketAcceptor{std::move(NewSocketAcceptor)} ,
.SocketReactorThread{std::move(NewThread)}};
Servers_.push_back(std::move(WSE));
auto NewSocketAcceptor = std::make_unique<Poco::Net::ParallelSocketAcceptor<WSConnection, Poco::Net::SocketReactor>>( Sock, Reactor_);
Acceptors_.push_back(std::move(NewSocketAcceptor));
}
uint64_t MaxThreads = Daemon()->ConfigGetInt("ucentral.websocket.maxreactors",5);
Factory_.Init(MaxThreads);
ReactorThread_.start(Reactor_);
return 0;
}
void WebSocketServer::Stop() {
Logger_.notice("Stopping reactors...");
for(auto const &Svr : Servers_) {
Svr.SocketReactor->stop();
Svr.SocketReactorThread->join();
}
Factory_.Close();
}
CountedReactor::CountedReactor()
{
Reactor_ = WebSocketServer()->GetAReactor();
}
CountedReactor::~CountedReactor()
{
Reactor_->Release();
Reactor_.stop();
ReactorThread_.join();
}
void WSConnection::LogException(const Poco::Exception &E) {
Logger_.information(Poco::format("EXCEPTION(%s): %s",CId_,E.displayText()));
}
void WSConnection::CompleteStartup() {
std::lock_guard Guard(WSMutex_);
try {
auto SS = dynamic_cast<Poco::Net::SecureStreamSocketImpl *>(Socket_.impl());
SS->completeHandshake();
CId_ = Utils::FormatIPv6(SS->peerAddress().toString());
if (!SS->secure()) {
Logger_.error(Poco::format("%s: Connection is NOT secure.", CId_));
} else {
Logger_.debug(Poco::format("%s: Connection is secure.", CId_));
}
if (SS->havePeerCertificate()) {
// Get the cert info...
CertValidation_ = GWObjects::VALID_CERTIFICATE;
try {
Poco::Crypto::X509Certificate PeerCert(SS->peerCertificate());
if (WebSocketServer()->ValidateCertificate(CId_, PeerCert)) {
CN_ = Poco::trim(Poco::toLower(PeerCert.commonName()));
CertValidation_ = GWObjects::MISMATCH_SERIAL;
Logger_.debug(Poco::format("%s: Valid certificate: CN=%s", CId_, CN_));
} else {
Logger_.debug(Poco::format("%s: Certificate is not valid", CId_));
}
} catch (const Poco::Exception &E) {
LogException(E);
}
} else {
Logger_.error(Poco::format("%s: No certificates available..", CId_));
}
auto Params =
Poco::AutoPtr<Poco::Net::HTTPServerParams>(new Poco::Net::HTTPServerParams);
Poco::Net::HTTPServerSession Session(Socket_, Params);
Poco::Net::HTTPServerResponseImpl Response(Session);
Poco::Net::HTTPServerRequestImpl Request(Response, Session, Params);
auto Now = time(nullptr);
Response.setDate(Now);
Response.setVersion(Request.getVersion());
Response.setKeepAlive(Params->getKeepAlive() && Request.getKeepAlive() &&
Session.canKeepAlive());
WS_ = std::make_unique<Poco::Net::WebSocket>(Request, Response);
WS_->setMaxPayloadSize(BufSize);
auto TS = Poco::Timespan(240,0);
WS_->setReceiveTimeout(TS);
WS_->setNoDelay(true);
WS_->setKeepAlive(true);
Reactor_.addEventHandler(*WS_,
Poco::NObserver<WSConnection, Poco::Net::ReadableNotification>(
*this, &WSConnection::OnSocketReadable));
Reactor_.addEventHandler(*WS_,
Poco::NObserver<WSConnection, Poco::Net::ShutdownNotification>(
*this, &WSConnection::OnSocketShutdown));
Reactor_.addEventHandler(*WS_,
Poco::NObserver<WSConnection, Poco::Net::ErrorNotification>(
*this, &WSConnection::OnSocketError));
Registered_ = true;
return;
} catch (const Poco::Exception &E ) {
Logger_.error("Exception caught during device connection. Device will have to retry.");
}
delete this;
}
WSConnection::WSConnection(Poco::Net::StreamSocket & socket, Poco::Net::SocketReactor & reactor):
Socket_(socket),
Logger_(WebSocketServer()->Logger())
Reactor_(reactor),
Logger_(WebSocketServer()->Logger())
{
auto SS = dynamic_cast<Poco::Net::SecureStreamSocketImpl *>(Socket_.impl());
SS->completeHandshake();
CId_ = uCentral::Utils::FormatIPv6(SS->peerAddress().toString());
if(!SS->secure()) {
Logger_.error(Poco::format("%s: Connection is NOT secure.",CId_));
} else {
Logger_.debug(Poco::format("%s: Connection is secure.",CId_));
}
if(SS->havePeerCertificate()) {
// Get the cert info...
CertValidation_ = GWObjects::VALID_CERTIFICATE;
try {
Poco::Crypto::X509Certificate PeerCert(SS->peerCertificate());
if(WebSocketServer()->ValidateCertificate(CId_, PeerCert)) {
CN_ = Poco::trim(Poco::toLower(PeerCert.commonName()));
CertValidation_ = GWObjects::MISMATCH_SERIAL;
Logger_.debug(Poco::format("%s: Valid certificate: CN=%s", CId_, CN_));
} else {
Logger_.debug( Poco::format("%s: Certificate is not valid", CId_));
}
} catch (const Poco::Exception &E) {
LogException(E);
}
} else {
Logger_.error(Poco::format("%s: No certificates available..",CId_));
}
auto Params = Poco::AutoPtr<Poco::Net::HTTPServerParams>(new Poco::Net::HTTPServerParams);
Poco::Net::HTTPServerSession Session(Socket_, Params);
Poco::Net::HTTPServerResponseImpl Response(Session);
Poco::Net::HTTPServerRequestImpl Request(Response,Session,Params);
auto Now = time(nullptr);
Response.setDate(Now);
Response.setVersion(Request.getVersion());
Response.setKeepAlive(Params->getKeepAlive() && Request.getKeepAlive() && Session.canKeepAlive());
WS_ = std::make_unique<Poco::Net::WebSocket>(Request, Response);
WS_->setMaxPayloadSize(BufSize);
Register();
std::thread T([this](){ this->CompleteStartup();});
T.detach();
}
WSConnection::~WSConnection() {
// std::cout << "Connection " << CId_ << " shutting down." << std::endl;
DeviceRegistry()->UnRegister(SerialNumber_,this);
DeRegister();
}
void WSConnection::Register() {
SubMutexGuard Guard(Mutex_);
if(!Registered_ && WS_)
{
auto TS = Poco::Timespan();
WS_->setReceiveTimeout(TS);
WS_->setNoDelay(true);
WS_->setKeepAlive(true);
Reactor_.Reactor()->addEventHandler(*WS_,
Poco::NObserver<WSConnection,
Poco::Net::ReadableNotification>(*this,&WSConnection::OnSocketReadable));
Reactor_.Reactor()->addEventHandler(*WS_,
Poco::NObserver<WSConnection,
Poco::Net::ShutdownNotification>(*this,&WSConnection::OnSocketShutdown));
Reactor_.Reactor()->addEventHandler(*WS_,
Poco::NObserver<WSConnection,
Poco::Net::ErrorNotification>(*this,&WSConnection::OnSocketError));
Registered_ = true ;
}
}
void WSConnection::DeRegister() {
SubMutexGuard Guard(Mutex_);
if(Registered_ && WS_)
{
Reactor_.Reactor()->removeEventHandler(*WS_,
Poco::NObserver<WSConnection,
Poco::Net::ReadableNotification>(*this,&WSConnection::OnSocketReadable));
Reactor_.Reactor()->removeEventHandler(*WS_,
Poco::NObserver<WSConnection,
Poco::Net::ShutdownNotification>(*this,&WSConnection::OnSocketShutdown));
Reactor_.Reactor()->removeEventHandler(*WS_,
Poco::NObserver<WSConnection,
Poco::Net::ErrorNotification>(*this,&WSConnection::OnSocketError));
(*WS_).close();
Registered_ = false ;
}
if(KafkaManager()->Enabled() && !SerialNumber_.empty()) {
Poco::JSON::Object Disconnect;
Poco::JSON::Object Details;
Details.set(uCentralProtocol::SERIALNUMBER, SerialNumber_);
Details.set(uCentralProtocol::TIMESTAMP,std::time(nullptr));
Disconnect.set(uCentralProtocol::DISCONNECTION,Details);
Poco::JSON::Stringifier Stringify;
std::ostringstream OS;
Stringify.condense(Disconnect,OS);
KafkaManager()->PostMessage(uCentral::KafkaTopics::CONNECTION, SerialNumber_, OS.str());
Reactor_.removeEventHandler(*WS_,
Poco::NObserver<WSConnection,
Poco::Net::ReadableNotification>(*this,&WSConnection::OnSocketReadable));
Reactor_.removeEventHandler(*WS_,
Poco::NObserver<WSConnection,
Poco::Net::ShutdownNotification>(*this,&WSConnection::OnSocketShutdown));
Reactor_.removeEventHandler(*WS_,
Poco::NObserver<WSConnection,
Poco::Net::ErrorNotification>(*this,&WSConnection::OnSocketError));
(*WS_).close();
Socket_.shutdown();
} else if(WS_) {
(*WS_).close();
Socket_.shutdown();
}
}
if(KafkaManager()->Enabled() && !SerialNumber_.empty()) {
Poco::JSON::Object Disconnect;
Poco::JSON::Object Details;
Details.set(uCentralProtocol::SERIALNUMBER, SerialNumber_);
Details.set(uCentralProtocol::TIMESTAMP,std::time(nullptr));
Disconnect.set(uCentralProtocol::DISCONNECTION,Details);
Poco::JSON::Stringifier Stringify;
std::ostringstream OS;
Stringify.condense(Disconnect,OS);
KafkaManager()->PostMessage(KafkaTopics::CONNECTION, SerialNumber_, OS.str());
}
}
bool WSConnection::LookForUpgrade(uint64_t UUID) {
@@ -269,7 +247,7 @@ namespace uCentral {
bool WSConnection::ExtractCompressedData(const std::string & CompressedData, std::string & UnCompressedData)
{
std::vector<uint8_t> OB = uCentral::Utils::base64decode(CompressedData);
std::vector<uint8_t> OB = Utils::base64decode(CompressedData);
unsigned long MaxSize=OB.size()*10;
std::vector<char> UncompressedBuffer(MaxSize);
@@ -282,14 +260,14 @@ namespace uCentral {
return false;
}
void WSConnection::ProcessJSONRPCResult(Poco::JSON::Object::Ptr Doc) {
void WSConnection::ProcessJSONRPCResult(Poco::JSON::Object::Ptr & Doc) {
CommandManager()->PostCommandResult(SerialNumber_, Doc);
}
void WSConnection::ProcessJSONRPCEvent(Poco::JSON::Object::Ptr Doc) {
void WSConnection::ProcessJSONRPCEvent(Poco::JSON::Object::Ptr & Doc) {
auto Method = Doc->get(uCentralProtocol::METHOD).toString();
auto EventType = uCentral::uCentralProtocol::EventFromString(Method);
auto EventType = uCentralProtocol::EventFromString(Method);
if(EventType == uCentralProtocol::ET_UNKNOWN) {
Logger_.error(Poco::format("ILLEGAL-PROTOCOL(%s): Unknown message type '%s'",Method));
Errors_++;
@@ -326,7 +304,7 @@ namespace uCentral {
}
auto Serial = Poco::trim(Poco::toLower(ParamsObj->get(uCentralProtocol::SERIAL).toString()));
if(!uCentral::Utils::ValidSerialNumber(Serial)) {
if(!Utils::ValidSerialNumber(Serial)) {
Poco::Exception E(Poco::format("ILLEGAL-DEVICE-NAME(%s): device name is illegal and not allowed to connect.",Serial), EACCES);
E.rethrow();
}
@@ -355,7 +333,7 @@ namespace uCentral {
Conn_->Firmware = Firmware;
Conn_->PendingUUID = 0;
Conn_->LastContact = std::time(nullptr);
Conn_->Address = uCentral::Utils::FormatIPv6(WS_->peerAddress().toString());
Conn_->Address = Utils::FormatIPv6(WS_->peerAddress().toString());
CId_ = SerialNumber_ + "@" + CId_ ;
// We need to verify the certificate if we have one
@@ -381,7 +359,7 @@ namespace uCentral {
}
Conn_->Compatible = Compatible_;
StatsProcessor_ = std::make_unique<uCentral::StateProcessor>();
StatsProcessor_ = std::make_unique<StateProcessor>(Conn_);
StatsProcessor_->Initialize(Serial);
LookForUpgrade(UUID);
@@ -389,7 +367,7 @@ namespace uCentral {
Poco::JSON::Stringifier Stringify;
std::ostringstream OS;
Stringify.condense(ParamsObj,OS);
KafkaManager()->PostMessage(uCentral::KafkaTopics::CONNECTION, SerialNumber_, OS.str());
KafkaManager()->PostMessage(KafkaTopics::CONNECTION, SerialNumber_, OS.str());
}
} else {
@@ -429,7 +407,7 @@ namespace uCentral {
Poco::JSON::Stringifier Stringify;
std::ostringstream OS;
Stringify.condense(ParamsObj,OS);
KafkaManager()->PostMessage(uCentral::KafkaTopics::STATE, SerialNumber_, OS.str());
KafkaManager()->PostMessage(KafkaTopics::STATE, SerialNumber_, OS.str());
}
} else {
Logger_.warning(Poco::format(
@@ -477,7 +455,7 @@ namespace uCentral {
Poco::JSON::Stringifier Stringify;
std::ostringstream OS;
Stringify.condense(ParamsObj,OS);
KafkaManager()->PostMessage(uCentral::KafkaTopics::HEALTHCHECK, SerialNumber_, OS.str());
KafkaManager()->PostMessage(KafkaTopics::HEALTHCHECK, SerialNumber_, OS.str());
}
} else {
Logger_.warning(Poco::format("HEALTHCHECK(%s): Missing parameter", CId_));
@@ -610,22 +588,24 @@ namespace uCentral {
}
void WSConnection::OnSocketShutdown(const Poco::AutoPtr<Poco::Net::ShutdownNotification>& pNf) {
SubMutexGuard Guard(Mutex_);
std::lock_guard Guard(WSMutex_);
// std::cout << "Socket shutdown: " << CId_ << std::endl;
Logger_.information(Poco::format("SOCKET-SHUTDOWN(%s): Closing.",CId_));
std::cout << "Socket shutdown for " << SerialNumber_ << std::endl;
delete this;
}
void WSConnection::OnSocketError(const Poco::AutoPtr<Poco::Net::ErrorNotification>& pNf) {
SubMutexGuard Guard(Mutex_);
std::lock_guard Guard(WSMutex_);
// std::cout << "Socket error: " << CId_ << std::endl;
Logger_.information(Poco::format("SOCKET-ERROR(%s): Closing.",CId_));
std::cout << "Socket error for " << SerialNumber_ << std::endl;
delete this;
}
void WSConnection::OnSocketReadable(const Poco::AutoPtr<Poco::Net::ReadableNotification>& pNf) {
std::lock_guard Guard(WSMutex_);
try
{
ProcessIncomingFrame();
@@ -658,8 +638,6 @@ namespace uCentral {
Poco::Buffer<char> IncomingFrame(0);
try {
SubMutexGuard Guard(Mutex_);
IncomingSize = WS_->receiveFrame(IncomingFrame,flags);
Op = flags & Poco::Net::WebSocket::FRAME_OP_BITMASK;
@@ -685,7 +663,7 @@ namespace uCentral {
Poco::JSON::Stringifier Stringify;
std::ostringstream OS;
Stringify.condense(PingObject, OS);
KafkaManager()->PostMessage(uCentral::KafkaTopics::CONNECTION, SerialNumber_,
KafkaManager()->PostMessage(KafkaTopics::CONNECTION, SerialNumber_,
OS.str());
}
}
@@ -796,14 +774,20 @@ namespace uCentral {
MustDisconnect = true ;
}
if(!MustDisconnect || Errors_>10)
return;
if(!MustDisconnect && Errors_<10) {
return;
}
if(Errors_>10) {
Logger_.information(Poco::format("DISCONNECTING(%s): Too many errors",CId_));
}
delete this;
}
bool WSConnection::Send(const std::string &Payload) {
SubMutexGuard Guard(Mutex_);
std::lock_guard Guard(WSMutex_);
auto BytesSent = WS_->sendFrame(Payload.c_str(),(int)Payload.size());
if(Conn_)
Conn_->TX += BytesSent;

View File

@@ -32,144 +32,32 @@
#include "Poco/Net/StreamSocket.h"
#include "Poco/Net/SecureStreamSocket.h"
#include "Poco/Net/SecureStreamSocketImpl.h"
#include "Poco/Net/ParallelSocketAcceptor.h"
namespace uCentral {
class CountedSocketReactor : public Poco::Net::SocketReactor {
public:
explicit CountedSocketReactor(uint64_t Id): Id_(Id),SocketCount_(0) {
setTimeout(Poco::Timespan(0,10000));
}
~CountedSocketReactor() override {
Poco::Net::SocketReactor::stop();
}
uint64_t Count() const {
return SocketCount_; }
void Get() {
std::lock_guard<std::mutex> guard(Mutex_);
SocketCount_++; }
void Release() {
std::lock_guard<std::mutex> guard(Mutex_);
SocketCount_--; }
uint64_t Id() const { return Id_;}
private:
std::mutex Mutex_{};
uint64_t SocketCount_;
uint64_t Id_;
};
class CountedSocketReactorFactory {
public:
explicit CountedSocketReactorFactory(Poco::Logger & Logger):
Logger_(Logger),
NumReactors_(0)
{
}
void Init(unsigned int NumReactors) {
NumReactors_ = NumReactors;
for(auto i=0;i<NumReactors_;i++)
{
auto NewReactor = new CountedSocketReactor(i);
auto NewThread = new Poco::Thread;
ReactorThreads_.emplace_back( std::pair(NewReactor, NewThread));
NewThread->start(*NewReactor);
NewThread->setName( "Reactor:" + std::to_string(i));
}
}
void Close() {
Logger_.information("Closing Reactor factory...");
for(auto &[Reactor,Thread]:ReactorThreads_)
{
Reactor->stop();
Thread->join();
}
}
~CountedSocketReactorFactory() {
for(auto &[Reactor,Thread]:ReactorThreads_)
{
delete Reactor;
delete Thread;
}
}
CountedSocketReactor * GetAReactor() {
uint64_t Min;
std::lock_guard<std::mutex> guard(Mutex_);
auto Tmp = ReactorThreads_.end();
uint64_t TotalSockets = 0 ;
for( auto i = ReactorThreads_.begin() ; i != ReactorThreads_.end() ; i++ )
{
TotalSockets += i->first->Count();
if((Tmp == ReactorThreads_.end()) || (i->first->Count()<Min) ) {
Tmp = i;
Min = i->first->Count();
}
}
Tmp->first->Get();
return Tmp->first;
}
private:
std::mutex Mutex_{};
Poco::Logger & Logger_;
uint64_t NumReactors_;
std::vector<std::pair<CountedSocketReactor *, Poco::Thread *>> ReactorThreads_;
};
struct CommandIDPair {
std::string UUID;
bool Full=true;
};
class CountedReactor {
public:
CountedReactor();
~CountedReactor();
CountedSocketReactor * Reactor() { return Reactor_; }
private:
CountedSocketReactor * Reactor_;
};
using SubMutex = std::recursive_mutex;
using SubMutexGuard = std::lock_guard<SubMutex>;
namespace OpenWifi {
class WSConnection {
static constexpr int BufSize = 64000;
public:
WSConnection(Poco::Net::StreamSocket& socket, Poco::Net::SocketReactor& reactor);
WSConnection(Poco::Net::StreamSocket& Socket, Poco::Net::SocketReactor& Reactor);
~WSConnection();
void ProcessJSONRPCEvent(Poco::JSON::Object::Ptr Doc);
void ProcessJSONRPCResult(Poco::JSON::Object::Ptr Doc);
void ProcessJSONRPCEvent(Poco::JSON::Object::Ptr & Doc);
void ProcessJSONRPCResult(Poco::JSON::Object::Ptr & Doc);
void ProcessIncomingFrame();
// bool SendCommand(uCentral::Objects::CommandDetails & Command);
bool Send(const std::string &Payload);
void OnSocketReadable(const Poco::AutoPtr<Poco::Net::ReadableNotification>& pNf);
void OnSocketShutdown(const Poco::AutoPtr<Poco::Net::ShutdownNotification>& pNf);
void OnSocketError(const Poco::AutoPtr<Poco::Net::ErrorNotification>& pNf);
bool LookForUpgrade(uint64_t UUID);
static bool ExtractCompressedData(const std::string & CompressedData, std::string & UnCompressedData);
void Register();
void DeRegister();
void LogException(const Poco::Exception &E);
[[nodiscard]] GWObjects::CertificateValidation CertificateValidation() const { return CertValidation_; };
private:
SubMutex Mutex_{};
CountedReactor Reactor_;
Poco::Logger & Logger_;
std::recursive_mutex WSMutex_;
Poco::Logger &Logger_;
Poco::Net::StreamSocket Socket_;
Poco::Net::SocketReactor & Reactor_;
std::unique_ptr<Poco::Net::WebSocket> WS_;
std::string SerialNumber_;
std::string Compatible_;
@@ -179,13 +67,9 @@ namespace uCentral {
std::string CN_;
GWObjects::CertificateValidation CertValidation_ = GWObjects::CertificateValidation::NO_CERTIFICATE;
uint64_t Errors_=0;
std::unique_ptr<uCentral::StateProcessor> StatsProcessor_;
};
std::unique_ptr<StateProcessor> StatsProcessor_;
struct WebSocketServerEntry {
std::unique_ptr<Poco::Net::SocketReactor> SocketReactor;
std::unique_ptr<Poco::Net::SocketAcceptor<WSConnection>> SocketAcceptor;
std::unique_ptr<Poco::Thread> SocketReactorThread;
void CompleteStartup();
};
class WebSocketServer : public SubSystemServer {
@@ -197,10 +81,6 @@ namespace uCentral {
return instance_;
}
CountedSocketReactor * GetAReactor() {
return Factory_.GetAReactor();
}
int Start() override;
void Stop() override;
bool IsCertOk() { return IssuerCert_!= nullptr; }
@@ -210,8 +90,9 @@ namespace uCentral {
private:
static WebSocketServer *instance_;
std::unique_ptr<Poco::Crypto::X509Certificate> IssuerCert_;
std::vector<WebSocketServerEntry> Servers_;
CountedSocketReactorFactory Factory_;
std::vector<std::unique_ptr<Poco::Net::ParallelSocketAcceptor<WSConnection, Poco::Net::SocketReactor>>> Acceptors_;
Poco::Net::SocketReactor Reactor_;
Poco::Thread ReactorThread_;
WebSocketServer() noexcept;
};

View File

@@ -19,7 +19,7 @@
#include "RESTAPI_GWobjects.h"
namespace uCentral {
namespace OpenWifi {
bool Storage::AddBlackListDevices(std::vector<GWObjects::BlackListedDevice> &Devices) {
try {
@@ -70,9 +70,9 @@ namespace uCentral {
Poco::Data::Session Sess = Pool_->get();
Poco::Data::Statement Select(Sess);
Select << "SELECT SerialNumber, Reason, Author, Created FROM BlackList",
Poco::Data::Keywords::into(Records),
Poco::Data::Keywords::range(Offset, Offset + HowMany);
Select << "SELECT SerialNumber, Reason, Author, Created FROM BlackList"
+ ComputeRange(Offset,HowMany),
Poco::Data::Keywords::into(Records);
Select.execute();
for (auto i : Records) {

View File

@@ -11,7 +11,7 @@
#include "Poco/JSON/Parser.h"
#include "Poco/JSON/Object.h"
namespace uCentral {
namespace OpenWifi {
bool Storage::UpdateDeviceCapabilities(std::string &SerialNumber, std::string & Capabilities, std::string & Compat) {
// std::lock_guard<std::mutex> guard(Mutex_);
@@ -75,7 +75,7 @@ namespace uCentral {
Update.execute();
}
uCentral::Storage::SetDeviceCompatibility(SerialNumber, Compatible);
Storage::SetDeviceCompatibility(SerialNumber, Compatible);
return true;
}
catch (const Poco::Exception &E) {

View File

@@ -15,8 +15,9 @@
#include "Daemon.h"
#include "DeviceRegistry.h"
#include "StorageService.h"
#include "FileUploader.h"
namespace uCentral {
namespace OpenWifi {
typedef Poco::Tuple<
std::string,
@@ -142,7 +143,7 @@ namespace uCentral {
std::string Fields{
"SELECT UUID, SerialNumber, Command, Status, SubmittedBy, Results, Details, ErrorText, "
"Submitted, Executed, Completed, RunAt, ErrorCode, Custom, WaitingForFile, AttachDate, "
"AttachSize, AttachType FROM CommandList "};
"AttachSize, AttachType FROM CommandList ORDER BY UUID ASC "};
std::string IntroStatement = SerialNumber.empty()
? Fields + std::string(DatesIncluded ? "WHERE " : "")
: Fields + "WHERE SerialNumber='" + SerialNumber + "'" +
@@ -160,8 +161,8 @@ namespace uCentral {
Poco::Data::Statement Select(Sess);
Select << IntroStatement + DateSelector, Poco::Data::Keywords::into(Records),
Poco::Data::Keywords::range(Offset, Offset + HowMany);
Select << IntroStatement + DateSelector +
ComputeRange(Offset, HowMany), Poco::Data::Keywords::into(Records);
Select.execute();
@@ -268,11 +269,10 @@ namespace uCentral {
// range(Offset, Offset + HowMany - 1)
std::string st{ "SELECT UUID, SerialNumber, Command, Status, SubmittedBy, Results, Details, ErrorText,"
"Submitted, Executed, Completed, RunAt, ErrorCode, Custom, WaitingForFile, AttachDate,"
"AttachSize, AttachType FROM CommandList "
"WHERE Executed=0"};
Select << ConvertParams(st),
Poco::Data::Keywords::into(Records),
Poco::Data::Keywords::range(Offset, Offset + HowMany);
"AttachSize, AttachType FROM CommandList ORDER BY UUID ASC "
"WHERE Executed=0" };
Select << ConvertParams(st) + ComputeRange(Offset, HowMany),
Poco::Data::Keywords::into(Records);
Select.execute();
for (auto i : Records) {
@@ -513,7 +513,7 @@ namespace uCentral {
bool Storage::GetReadyToExecuteCommands(uint64_t Offset, uint64_t HowMany,
std::vector<GWObjects::CommandDetails> &Commands) {
// todo: finish the GetReadyToExecuteCommands call...
try {
typedef std::vector<CommandDetailsRecordTuple> RecordList;
uint64_t Now = time(nullptr);
@@ -522,13 +522,14 @@ namespace uCentral {
std::string St{
"SELECT UUID, SerialNumber, Command, Status, SubmittedBy, Results, Details, ErrorText, "
"Submitted, Executed, Completed, RunAt, ErrorCode, Custom, WaitingForFile, AttachDate, AttachSize, AttachType FROM CommandList "
"WHERE RunAt < ? And Executed=0"};
" Submitted, Executed, Completed, RunAt, ErrorCode, Custom, WaitingForFile, AttachDate, AttachSize, AttachType FROM CommandList "
" WHERE ((RunAt<=?) And (Executed=0)) ORDER BY UUID ASC "};
RecordList Records;
Select << ConvertParams(St), Poco::Data::Keywords::into(Records),
Poco::Data::Keywords::use(Now), Poco::Data::Keywords::range(Offset, Offset + HowMany);
std::string SS = ConvertParams(St) + ComputeRange(Offset, HowMany);
Select << SS,
Poco::Data::Keywords::into(Records),
Poco::Data::Keywords::use(Now);
Select.execute();
for (auto i : Records) {
@@ -554,9 +555,9 @@ namespace uCentral {
if (DeviceRegistry()->Connected(R.SerialNumber))
Commands.push_back(R);
}
return true;
} catch (const Poco::Exception &E) {
// std::cout << "Exception: " << E.displayText() << std::endl;
Logger_.warning(Poco::format("GetReadyToExecuteCommands(): Failed to retrieve the list. %s",
E.displayText()));
}
@@ -633,6 +634,33 @@ namespace uCentral {
return false;
}
bool Storage::CancelWaitFile( std::string & UUID, std::string & ErrorText ) {
try {
Poco::Data::Session Sess = Pool_->get();
uint64_t Now = time(nullptr);
uint64_t Size = 0, WaitForFile = 0;
Poco::Data::Statement Update(Sess);
std::string St{
"UPDATE CommandList SET WaitingForFile=?, AttachDate=?, AttachSize=?, ErrorText=?, Completed=? WHERE UUID=?"};
Update << ConvertParams(St),
Poco::Data::Keywords::use(WaitForFile),
Poco::Data::Keywords::use(Now),
Poco::Data::Keywords::use(Size),
Poco::Data::Keywords::use(ErrorText),
Poco::Data::Keywords::use(Now),
Poco::Data::Keywords::use(UUID);
Update.execute();
return true;
} catch (const Poco::Exception &E) {
Logger_.log(E);
}
return false;
}
bool Storage::AttachFileToCommand(std::string &UUID) {
try {
Poco::Data::Session Sess = Pool_->get();
@@ -641,14 +669,16 @@ namespace uCentral {
Poco::Data::Statement Update(Sess);
Poco::File FileName = Daemon()->ConfigPath("ucentral.fileuploader.path", "/tmp") + "/" + UUID;
Poco::File FileName = FileUploader()->Path() + "/" + UUID;
uint64_t Size = FileName.getSize();
std::string St{
"UPDATE CommandList SET WaitingForFile=?, AttachDate=?, AttachSize=? WHERE UUID=?"};
Update << ConvertParams(St), Poco::Data::Keywords::use(WaitForFile),
Poco::Data::Keywords::use(Now), Poco::Data::Keywords::use(Size),
Update << ConvertParams(St),
Poco::Data::Keywords::use(WaitForFile),
Poco::Data::Keywords::use(Now),
Poco::Data::Keywords::use(Size),
Poco::Data::Keywords::use(UUID);
Update.execute();
@@ -673,7 +703,8 @@ namespace uCentral {
"INSERT INTO FileUploads (UUID,Type,Created,FileContent) VALUES(?,?,?,?)"};
Insert << ConvertParams(St2), Poco::Data::Keywords::use(UUID),
Poco::Data::Keywords::use(FileType), Poco::Data::Keywords::use(Now),
Poco::Data::Keywords::use(FileType),
Poco::Data::Keywords::use(Now),
Poco::Data::Keywords::use(L);
Insert.execute();

View File

@@ -10,7 +10,7 @@
#include "CentralConfig.h"
namespace uCentral {
namespace OpenWifi {
/*
* Data model for DefaultConfigurations:
@@ -40,7 +40,7 @@ namespace uCentral {
if (TmpName.empty()) {
uCentral::Config::Config Cfg(DefConfig.Configuration);
Config::Config Cfg(DefConfig.Configuration);
/*
"Name VARCHAR(30) PRIMARY KEY, "
"Configuration TEXT, "
@@ -108,7 +108,7 @@ namespace uCentral {
Poco::Data::Session Sess = Pool_->get();
uCentral::Config::Config Cfg(DefConfig.Configuration);
Config::Config Cfg(DefConfig.Configuration);
if (Cfg.Valid()) {
@@ -199,9 +199,9 @@ namespace uCentral {
"Description, "
"Created, "
"LastModified "
"FROM DefaultConfigs",
Poco::Data::Keywords::into(Records),
Poco::Data::Keywords::range(From, From + HowMany );
"FROM DefaultConfigs ORDER BY NAME ASC " +
ComputeRange(From, HowMany),
Poco::Data::Keywords::into(Records);
Select.execute();
@@ -267,9 +267,9 @@ namespace uCentral {
"Description, "
"Created, "
"LastModified "
"FROM DefaultConfigs",
Poco::Data::Keywords::into(Records),
Poco::Data::Keywords::range(0, 2);
"FROM DefaultConfigs ORDER BY NAME ASC " +
ComputeRange(1,1),
Poco::Data::Keywords::into(Records);
Select.execute();
for (auto i: Records) {

View File

@@ -6,14 +6,18 @@
// Arilia Wireless Inc.
//
#include "Poco/Data/RecordSet.h"
#include "CentralConfig.h"
#include "StorageService.h"
#include "Utils.h"
#include "RESTAPI_utils.h"
#include "Daemon.h"
#include "DeviceRegistry.h"
#include "OUIServer.h"
#include "StateProcessor.h"
#include "SerialNumberCache.h"
namespace uCentral {
namespace OpenWifi {
bool Storage::GetDeviceCount(uint64_t &Count) {
try {
@@ -37,11 +41,10 @@ namespace uCentral {
Poco::Data::Session Sess = Pool_->get();
Poco::Data::Statement Select(Sess);
std::string st{"SELECT SerialNumber From Devices"};
std::string st{"SELECT SerialNumber From Devices ORDER BY SerialNumber ASC " };
Select << st,
Poco::Data::Keywords::into(SerialNumbers),
Poco::Data::Keywords::range(From, From + HowMany );
Select << st + ComputeRange(From, HowMany),
Poco::Data::Keywords::into(SerialNumbers);
Select.execute();
return true;
} catch (const Poco::Exception &E ) {
@@ -53,7 +56,7 @@ namespace uCentral {
bool Storage::UpdateDeviceConfiguration(std::string &SerialNumber, std::string &Configuration, uint64_t &NewUUID) {
try {
uCentral::Config::Config Cfg(Configuration);
Config::Config Cfg(Configuration);
if (!Cfg.Valid()) {
Logger_.warning(Poco::format("CONFIG-UPDATE(%s): Configuration was not valid", SerialNumber));
return false;
@@ -118,7 +121,7 @@ namespace uCentral {
Select.execute();
if (SerialNumber.empty()) {
uCentral::Config::Config Cfg(DeviceDetails.Configuration);
Config::Config Cfg(DeviceDetails.Configuration);
if (Cfg.Valid() && Cfg.SetUUID(DeviceDetails.UUID)) {
DeviceDetails.Configuration = Cfg.get();
@@ -168,6 +171,7 @@ namespace uCentral {
Poco::Data::Keywords::use(Now),
Poco::Data::Keywords::use(DeviceDetails.Venue);
Insert.execute();
SerialNumberCache()->AddSerialNumber(DeviceDetails.SerialNumber);
return true;
} else {
Logger_.warning("Cannot create device: invalid configuration.");
@@ -188,15 +192,15 @@ namespace uCentral {
Logger_.information(Poco::format("AUTO-CREATION(%s)", SerialNumber));
uint64_t Now = time(nullptr);
uCentral::Config::Capabilities Caps(Capabilities);
Config::Capabilities Caps(Capabilities);
GWObjects::DefaultConfiguration DefConfig;
if (FindDefaultConfigurationForModel(Caps.Model(), DefConfig)) {
uCentral::Config::Config NewConfig(DefConfig.Configuration);
Config::Config NewConfig(DefConfig.Configuration);
NewConfig.SetUUID(Now);
D.Configuration = NewConfig.get();
} else {
uCentral::Config::Config NewConfig;
Config::Config NewConfig;
NewConfig.SetUUID(Now);
D.Configuration = NewConfig.get();
}
@@ -357,6 +361,7 @@ namespace uCentral {
Delete << ConvertParams(St),
Poco::Data::Keywords::use(SerialNumber);
Delete.execute();
SerialNumberCache()->DeleteSerialNumber(SerialNumber);
return true;
}
catch (const Poco::Exception &E) {
@@ -536,10 +541,6 @@ namespace uCentral {
return false;
}
bool Storage::GetDevices(uint64_t From, uint64_t HowMany, const std::string &Select, std::vector<GWObjects::Device> &Devices) {
return false;
}
bool Storage::GetDevices(uint64_t From, uint64_t HowMany, std::vector<GWObjects::Device> &Devices) {
typedef Poco::Tuple<
@@ -589,9 +590,9 @@ namespace uCentral {
"LastFWUpdate, "
"Venue, "
"DevicePassword "
"FROM Devices",
Poco::Data::Keywords::into(Records),
Poco::Data::Keywords::range(From, From + HowMany );
"FROM Devices ORDER BY SerialNumber ASC " +
ComputeRange(From, HowMany),
Poco::Data::Keywords::into(Records);
Select.execute();
@@ -687,5 +688,164 @@ namespace uCentral {
}
return false;
}
bool Storage::UpdateSerialNumberCache() {
try {
Poco::Data::Session Sess = Pool_->get();
Poco::Data::Statement Select(Sess);
Select << "SELECT SerialNumber FROM Devices";
Select.execute();
Poco::Data::RecordSet RSet(Select);
bool More = RSet.moveFirst();
while(More) {
auto SerialNumber = RSet[0].convert<std::string>();
SerialNumberCache()->AddSerialNumber(SerialNumber);
More = RSet.moveNext();
}
return true;
} catch(const Poco::Exception &E) {
Logger_.log(E);
}
return false;
}
static std::string ComputeCertificateTag( GWObjects::CertificateValidation V) {
switch(V) {
case GWObjects::NO_CERTIFICATE: return "no certificate";
case GWObjects::VALID_CERTIFICATE: return "non TIP certificate";
case GWObjects::MISMATCH_SERIAL: return "serial mismatch";
case GWObjects::VERIFIED: return "verified";
}
return "unknown";
}
static const uint64_t SECONDS_MONTH = 30*24*60*60;
static const uint64_t SECONDS_WEEK = 7*24*60*60;
static const uint64_t SECONDS_DAY = 1*24*60*60;
static const uint64_t SECONDS_HOUR = 1*24*60*60;
static std::string ComputeUpLastContactTag(uint64_t T1) {
uint64_t T = T1 - std::time(nullptr);
if( T>SECONDS_MONTH) return ">month";
if( T>SECONDS_WEEK) return ">week";
if( T>SECONDS_DAY) return ">day";
if( T>SECONDS_HOUR) return ">hour";
return "now";
}
static std::string ComputeSanityTag(uint64_t T) {
if( T==100) return "100%";
if( T>90) return ">90%";
if( T>60) return ">60%";
return "<60%";
}
static std::string ComputeUpTimeTag(uint64_t T) {
if( T>SECONDS_MONTH) return ">month";
if( T>SECONDS_WEEK) return ">week";
if( T>SECONDS_DAY) return ">day";
if( T>SECONDS_HOUR) return ">hour";
return "now";
}
static std::string ComputeLoadTag(uint64_t T) {
float V=100.0*((float)T/65536.0);
if(V<5.0) return "< 5%";
if(V<25.0) return "< 25%";
if(V<50.0) return "< 50%";
if(V<75.0) return "< 75%";
return ">75%";
}
static std::string ComputeFreeMemoryTag(uint64_t Free, uint64_t Total) {
float V = 100.0 * ((float)Free/(float(Total)));
if(V<5.0) return "< 5%";
if(V<25.0) return "< 25%";
if(V<50.0) return "< 50%";
if(V<75.0) return "< 75%";
return ">75%";
}
int ChannelToBand(uint64_t C) {
if(C>=1 && C<=16) return 2;
return 5;
}
bool Storage::AnalyzeDevices(GWObjects::Dashboard &Dashboard) {
try {
Poco::Data::Session Sess = Pool_->get();
Poco::Data::Statement Select(Sess);
Select << "SELECT SerialNumber, Compatible, Firmware FROM Devices";
Select.execute();
Poco::Data::RecordSet RSet(Select);
bool More = RSet.moveFirst();
while(More) {
Dashboard.numberOfDevices++;
auto SerialNumber = RSet[0].convert<std::string>();
auto DeviceType = RSet[1].convert<std::string>();
auto Revision = RSet[2].convert<std::string>();
Types::UpdateCountedMap(Dashboard.vendors, OUIServer()->GetManufacturer(SerialNumber));
Types::UpdateCountedMap(Dashboard.deviceType, DeviceType);
GWObjects::ConnectionState ConnState;
if(DeviceRegistry()->GetState(SerialNumber, ConnState)) {
Types::UpdateCountedMap(Dashboard.status, ConnState.Connected ? "connected" : "not connected");
Types::UpdateCountedMap(Dashboard.certificates, ComputeCertificateTag(ConnState.VerifiedCertificate));
Types::UpdateCountedMap(Dashboard.lastContact, ComputeUpLastContactTag(ConnState.LastContact));
GWObjects::HealthCheck HC;
if(DeviceRegistry()->GetHealthcheck(SerialNumber,HC))
Types::UpdateCountedMap(Dashboard.healths, ComputeSanityTag(HC.Sanity));
std::string LastStats;
if(DeviceRegistry()->GetStatistics(SerialNumber, LastStats) && !LastStats.empty()) {
Poco::JSON::Parser P;
auto RawObject = P.parse(LastStats).extract<Poco::JSON::Object::Ptr>();
if(RawObject->has("unit")) {
auto Unit = RawObject->getObject("unit");
if (Unit->has("uptime")) {
Types::UpdateCountedMap(Dashboard.upTimes, ComputeUpTimeTag(Unit->get("uptime")));
}
if (Unit->has("memory")) {
auto Memory = Unit->getObject("memory");
uint64_t Free = Memory->get("free");
uint64_t Total = Memory->get("total");
Types::UpdateCountedMap(Dashboard.memoryUsed, ComputeFreeMemoryTag(Free, Total));
}
if (Unit->has("load")) {
auto Load = Unit->getArray("load");
Types::UpdateCountedMap(Dashboard.load1,
ComputeLoadTag(Load->getElement<uint64_t>(0)));
Types::UpdateCountedMap(Dashboard.load5,
ComputeLoadTag(Load->getElement<uint64_t>(1)));
Types::UpdateCountedMap(Dashboard.load15,
ComputeLoadTag(Load->getElement<uint64_t>(2)));
}
}
uint64_t Associations_2G, Associations_5G;
StateProcessor::GetAssociations(RawObject, Associations_2G, Associations_5G);
Types::UpdateCountedMap(Dashboard.associations, "2G", Associations_2G);
Types::UpdateCountedMap(Dashboard.associations, "5G", Associations_5G);
}
Types::UpdateCountedMap(Dashboard.status, ConnState.Connected ? "connected" : "not connected");
} else {
Types::UpdateCountedMap(Dashboard.status, "not connected");
}
More = RSet.moveNext();
}
return true;
} catch(const Poco::Exception &E) {
Logger_.log(E);
}
return false;
}
}

Some files were not shown because too many files have changed in this diff Show More