mirror of
https://github.com/Telecominfraproject/wlan-cloud-ucentralgw.git
synced 2025-11-02 03:37:57 +00:00
Compare commits
154 Commits
release/v2
...
v2.4.0-RC6
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c86227de9e | ||
|
|
04063ddd41 | ||
|
|
1808376445 | ||
|
|
83211baba8 | ||
|
|
9b87fb756f | ||
|
|
1064bfe137 | ||
|
|
5125dc5eb6 | ||
|
|
ec1acd922d | ||
|
|
6a29facd59 | ||
|
|
aef76b12e4 | ||
|
|
1f2aaa94ba | ||
|
|
2f4ff94280 | ||
|
|
26ac5b836e | ||
|
|
e2508846b3 | ||
|
|
2d8ee9b033 | ||
|
|
bf3ba546b6 | ||
|
|
8b282a032c | ||
|
|
4aa9e93d8a | ||
|
|
515f6cdf91 | ||
|
|
9d91b15110 | ||
|
|
c73aba6ad4 | ||
|
|
15fcd30030 | ||
|
|
6fa4432f74 | ||
|
|
c1367ddf3b | ||
|
|
d80f146877 | ||
|
|
e43b032d3a | ||
|
|
b84ad117cf | ||
|
|
03d29c4bd8 | ||
|
|
2344cea825 | ||
|
|
b431dc1293 | ||
|
|
566368638a | ||
|
|
957f1fe7d8 | ||
|
|
570f9de425 | ||
|
|
4121f70315 | ||
|
|
fec45de4e8 | ||
|
|
f981513ee2 | ||
|
|
e997eac63c | ||
|
|
736f9aa099 | ||
|
|
1e3711f293 | ||
|
|
76eca308c9 | ||
|
|
7a77497522 | ||
|
|
dd04572aef | ||
|
|
d6a4ab86e7 | ||
|
|
1367b5a4a2 | ||
|
|
7dbc1476d8 | ||
|
|
63fc7055f8 | ||
|
|
1c61ad8798 | ||
|
|
8f641df7e4 | ||
|
|
8241a4f287 | ||
|
|
8008bac1af | ||
|
|
b1fe5bcd39 | ||
|
|
aacc230ff2 | ||
|
|
a6823b2e2c | ||
|
|
756ee323a5 | ||
|
|
5f0a432cdc | ||
|
|
a7ee104828 | ||
|
|
980564d945 | ||
|
|
085e8b93ee | ||
|
|
ffe85278f1 | ||
|
|
240d94c687 | ||
|
|
31466efde8 | ||
|
|
aa9fd229b6 | ||
|
|
daf1563636 | ||
|
|
ac74dffd0c | ||
|
|
c85f22bfb5 | ||
|
|
126b391080 | ||
|
|
48b2c57245 | ||
|
|
c82126234d | ||
|
|
d9488cdd79 | ||
|
|
0745badb8a | ||
|
|
c13a6c1852 | ||
|
|
053b9de558 | ||
|
|
6d058930c9 | ||
|
|
9e52c9d7da | ||
|
|
7fbdc4b18b | ||
|
|
d2ce73f75e | ||
|
|
8bfd0f57ab | ||
|
|
66c17e7691 | ||
|
|
05b7be1270 | ||
|
|
57c11d9a09 | ||
|
|
5664dbef6d | ||
|
|
874cd297b1 | ||
|
|
cef65da7d8 | ||
|
|
c7bb51e73f | ||
|
|
cfc9422266 | ||
|
|
e15f3af410 | ||
|
|
c1797d9caf | ||
|
|
ddc26b7e08 | ||
|
|
1ba31d3480 | ||
|
|
b38043c02d | ||
|
|
bc5b430c2e | ||
|
|
03503cc525 | ||
|
|
310cdd6245 | ||
|
|
5f089105b7 | ||
|
|
3548c004cb | ||
|
|
f9f1101ac9 | ||
|
|
1f8294a208 | ||
|
|
6b2e3db363 | ||
|
|
8faa8a82fd | ||
|
|
24bb3fc2f6 | ||
|
|
38dd9f592a | ||
|
|
bb176c23bb | ||
|
|
124f941a10 | ||
|
|
fa6a00cf99 | ||
|
|
e58fa4b0fb | ||
|
|
645f484d1d | ||
|
|
1e0f43bd4b | ||
|
|
09a1e5d429 | ||
|
|
a0beee77aa | ||
|
|
04c221784b | ||
|
|
544d6babe5 | ||
|
|
5d16414bb2 | ||
|
|
925a48929f | ||
|
|
816bc9c799 | ||
|
|
7f0148a33d | ||
|
|
e2f07d6d05 | ||
|
|
c708ffd23a | ||
|
|
9db5b5f39a | ||
|
|
e47feab9ad | ||
|
|
f673cdc1ba | ||
|
|
4fa59fdfd2 | ||
|
|
1d6bafa75a | ||
|
|
aa0a9aabce | ||
|
|
2a0b45fde1 | ||
|
|
816f0a6e7c | ||
|
|
02e8c59052 | ||
|
|
b26509c8b7 | ||
|
|
cd3b663f0a | ||
|
|
9172ec6532 | ||
|
|
eab9557f51 | ||
|
|
ee1d0fbde9 | ||
|
|
352e4c3857 | ||
|
|
80cf939503 | ||
|
|
60c0d83a95 | ||
|
|
1de5d2902d | ||
|
|
62e5060204 | ||
|
|
e317f1c0e2 | ||
|
|
e87d9efd09 | ||
|
|
a92601b285 | ||
|
|
6fa7165171 | ||
|
|
7703955b0e | ||
|
|
20bfda45bc | ||
|
|
53d914f58a | ||
|
|
b91ddf5272 | ||
|
|
621b1953d9 | ||
|
|
63d78d5c14 | ||
|
|
e32bf08ef8 | ||
|
|
bc7d291262 | ||
|
|
28e1da2f08 | ||
|
|
f7d6487306 | ||
|
|
b8448355db | ||
|
|
b26dd1b709 | ||
|
|
7eed435e68 | ||
|
|
29ddc81814 |
6
.github/workflows/ci.yml
vendored
6
.github/workflows/ci.yml
vendored
@@ -84,7 +84,7 @@ jobs:
|
||||
env:
|
||||
OWGW_TAG: ${{ github.sha }}
|
||||
run: |
|
||||
docker-compose -f docker-compose.yml -f docker-compose.selfsigned.yml --env-file .env.selfsigned up -d
|
||||
docker-compose up -d
|
||||
|
||||
- name: Wait for OWSec to be alive and kicking
|
||||
run: |
|
||||
@@ -116,8 +116,8 @@ jobs:
|
||||
working-directory: ./wlan-cloud-ucentral-deploy/docker-compose
|
||||
if: always()
|
||||
run: |
|
||||
docker-compose -f docker-compose.yml -f docker-compose.selfsigned.yml --env-file .env.selfsigned ps -a
|
||||
docker-compose -f docker-compose.yml -f docker-compose.selfsigned.yml --env-file .env.selfsigned logs
|
||||
docker-compose ps -a
|
||||
docker-compose logs
|
||||
|
||||
# disable until repo is public
|
||||
#- name: export Docker image
|
||||
|
||||
122
CMakeLists.txt
122
CMakeLists.txt
@@ -1,5 +1,5 @@
|
||||
cmake_minimum_required(VERSION 3.13)
|
||||
project(owgw VERSION 2.2.0)
|
||||
project(owgw VERSION 2.4.0)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
|
||||
@@ -29,7 +29,20 @@ else()
|
||||
set(BUILD_NUM 1)
|
||||
file(WRITE build ${BUILD_NUM})
|
||||
endif()
|
||||
add_definitions(-DAPP_VERSION="${CMAKE_PROJECT_VERSION}" -DBUILD_NUMBER="${BUILD_NUM}")
|
||||
|
||||
find_package(Git QUIET)
|
||||
if(GIT_FOUND AND EXISTS "${PROJECT_SOURCE_DIR}/.git")
|
||||
execute_process(COMMAND ${GIT_EXECUTABLE} describe --always --tags
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
RESULT_VARIABLE GIT_RESULT
|
||||
OUTPUT_VARIABLE GIT_HASH)
|
||||
if(NOT GIT_RESULT EQUAL "0")
|
||||
message(FATAL_ERROR "git describe --always --tags failed with ${GIT_RESULT}")
|
||||
endif()
|
||||
string(REGEX REPLACE "\n$" "" GIT_HASH "${GIT_HASH}")
|
||||
endif()
|
||||
add_definitions(-DAWS_CUSTOM_MEMORY_MANAGEMENT)
|
||||
|
||||
add_definitions(-DTIP_GATEWAY_SERVICE="1")
|
||||
|
||||
set(Boost_USE_STATIC_LIBS OFF)
|
||||
@@ -52,58 +65,65 @@ endif()
|
||||
|
||||
include_directories(/usr/local/include /usr/local/opt/openssl/include src include/kafka /usr/local/opt/mysql-client/include)
|
||||
|
||||
configure_file(src/ow_version.h.in ${PROJECT_SOURCE_DIR}/src/ow_version.h @ONLY)
|
||||
|
||||
add_executable( owgw
|
||||
build
|
||||
src/Daemon.cpp src/Daemon.h
|
||||
src/RESTAPI_server.cpp src/RESTAPI_server.h
|
||||
src/WebSocketServer.cpp src/WebSocketServer.h
|
||||
src/SubSystemServer.cpp src/SubSystemServer.h
|
||||
src/StorageService.cpp src/StorageService.h
|
||||
src/RESTAPI_SecurityObjects.cpp src/RESTAPI_SecurityObjects.h
|
||||
src/DeviceRegistry.cpp src/DeviceRegistry.h
|
||||
src/RESTAPI_devices_handler.cpp src/RESTAPI_devices_handler.h
|
||||
src/RESTAPI_device_handler.cpp src/RESTAPI_device_handler.h
|
||||
src/RESTAPI_handler.cpp src/RESTAPI_handler.h
|
||||
src/RESTAPI_device_commandHandler.cpp src/RESTAPI_device_commandHandler.h
|
||||
src/RESTAPI_GWobjects.h src/RESTAPI_GWobjects.cpp
|
||||
src/CentralConfig.cpp src/CentralConfig.h
|
||||
src/RESTAPI_default_configuration.cpp
|
||||
src/RESTAPI_InternalServer.cpp src/RESTAPI_InternalServer.h
|
||||
src/RESTAPI_default_configuration.h src/RESTAPI_default_configurations.cpp src/RESTAPI_default_configurations.h
|
||||
src/RESTAPI_commands.cpp src/RESTAPI_commands.h
|
||||
src/CommandManager.cpp src/CommandManager.h
|
||||
src/RESTAPI_command.cpp src/RESTAPI_command.h
|
||||
src/FileUploader.cpp src/FileUploader.h
|
||||
src/RESTAPI_file.cpp src/RESTAPI_file.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_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/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/SerialNumberCache.cpp src/SerialNumberCache.h
|
||||
src/RESTAPI_webSocketServer.cpp src/RESTAPI_webSocketServer.h
|
||||
src/OpenWifiTypes.h src/TelemetryStream.cpp src/TelemetryStream.h
|
||||
src/RESTAPI_GenericServer.cpp src/RESTAPI_GenericServer.h
|
||||
src/RESTAPI_errors.h src/RESTAPI_TelemetryWebSocket.cpp src/RESTAPI_TelemetryWebSocket.h
|
||||
src/ConfigurationValidator.cpp src/ConfigurationValidator.h src/ConfigurationCache.cpp src/ConfigurationCache.h)
|
||||
build
|
||||
src/ow_version.h.in
|
||||
src/framework/CountryCodes.h
|
||||
src/framework/KafkaTopics.h
|
||||
src/framework/MicroService.h
|
||||
src/framework/OpenWifiTypes.h
|
||||
src/framework/orm.h
|
||||
src/framework/RESTAPI_errors.h
|
||||
src/framework/RESTAPI_protocol.h
|
||||
src/framework/StorageClass.h
|
||||
src/framework/uCentral_Protocol.h
|
||||
src/RESTObjects/RESTAPI_SecurityObjects.h src/RESTObjects/RESTAPI_SecurityObjects.cpp
|
||||
src/RESTObjects/RESTAPI_ProvObjects.cpp src/RESTObjects/RESTAPI_ProvObjects.h
|
||||
src/RESTObjects/RESTAPI_GWobjects.h src/RESTObjects/RESTAPI_GWobjects.cpp
|
||||
src/RESTObjects/RESTAPI_FMSObjects.h src/RESTObjects/RESTAPI_FMSObjects.cpp
|
||||
src/RESTAPI/RESTAPI_devices_handler.cpp src/RESTAPI/RESTAPI_devices_handler.h
|
||||
src/RESTAPI/RESTAPI_device_handler.cpp src/RESTAPI/RESTAPI_device_handler.h
|
||||
src/RESTAPI/RESTAPI_device_commandHandler.cpp src/RESTAPI/RESTAPI_device_commandHandler.h
|
||||
src/RESTAPI/RESTAPI_default_configuration.cpp
|
||||
src/RESTAPI/RESTAPI_default_configuration.h src/RESTAPI/RESTAPI_default_configurations.cpp src/RESTAPI/RESTAPI_default_configurations.h
|
||||
src/RESTAPI/RESTAPI_commands.cpp src/RESTAPI/RESTAPI_commands.h
|
||||
src/RESTAPI/RESTAPI_command.cpp src/RESTAPI/RESTAPI_command.h
|
||||
src/RESTAPI/RESTAPI_file.cpp src/RESTAPI/RESTAPI_file.h
|
||||
src/RESTAPI/RESTAPI_blacklist.cpp src/RESTAPI/RESTAPI_blacklist.h
|
||||
src/RESTAPI/RESTAPI_ouis.cpp src/RESTAPI/RESTAPI_ouis.h
|
||||
src/RESTAPI/RESTAPI_blacklist_list.cpp src/RESTAPI/RESTAPI_blacklist_list.h
|
||||
src/RESTAPI/RESTAPI_capabilities_handler.cpp src/RESTAPI/RESTAPI_capabilities_handler.h
|
||||
src/RESTAPI/RESTAPI_RPC.cpp src/RESTAPI/RESTAPI_RPC.h
|
||||
src/RESTAPI/RESTAPI_deviceDashboardHandler.cpp src/RESTAPI/RESTAPI_deviceDashboardHandler.h
|
||||
src/RESTAPI/RESTAPI_TelemetryWebSocket.cpp src/RESTAPI/RESTAPI_TelemetryWebSocket.h
|
||||
src/RESTAPI/RESTAPI_webSocketServer.cpp src/RESTAPI/RESTAPI_webSocketServer.h
|
||||
src/storage/storage_blacklist.cpp src/storage/storage_tables.cpp src/storage/storage_logs.cpp
|
||||
src/storage/storage_command.cpp src/storage/storage_healthcheck.cpp src/storage/storage_statistics.cpp
|
||||
src/storage/storage_device.cpp src/storage/storage_capabilities.cpp src/storage/storage_defconfig.cpp
|
||||
src/storage/storage_tables.cpp
|
||||
src/APIServers.cpp
|
||||
src/Daemon.cpp src/Daemon.h
|
||||
src/StateProcessor.cpp src/StateProcessor.h
|
||||
src/storage/storage_lifetime_stats.cpp
|
||||
src/WebSocketServer.cpp src/WebSocketServer.h
|
||||
src/StorageService.cpp src/StorageService.h
|
||||
src/DeviceRegistry.cpp src/DeviceRegistry.h
|
||||
src/CommandManager.cpp src/CommandManager.h
|
||||
src/CentralConfig.cpp src/CentralConfig.h
|
||||
src/FileUploader.cpp src/FileUploader.h
|
||||
src/OUIServer.cpp src/OUIServer.h
|
||||
src/StorageArchiver.cpp src/StorageArchiver.h
|
||||
src/Dashboard.cpp src/Dashboard.h
|
||||
src/SerialNumberCache.cpp src/SerialNumberCache.h
|
||||
src/TelemetryStream.cpp src/TelemetryStream.h
|
||||
src/framework/ConfigurationValidator.cpp src/framework/ConfigurationValidator.h
|
||||
src/ConfigurationCache.cpp src/ConfigurationCache.h
|
||||
)
|
||||
|
||||
if(NOT SMALL_BUILD)
|
||||
target_sources(owgw PUBLIC src/KafkaManager.cpp src/KafkaManager.h)
|
||||
|
||||
endif()
|
||||
|
||||
INSTALL(TARGETS owgw
|
||||
|
||||
@@ -38,6 +38,7 @@ RUN make install
|
||||
ADD CMakeLists.txt build /owgw/
|
||||
ADD cmake /owgw/cmake
|
||||
ADD src /owgw/src
|
||||
ADD .git /owgw/.git
|
||||
|
||||
WORKDIR /owgw
|
||||
RUN mkdir cmake-build
|
||||
@@ -57,16 +58,18 @@ RUN addgroup -S "$OWGW_USER" && \
|
||||
RUN mkdir /openwifi
|
||||
RUN mkdir -p "$OWGW_ROOT" "$OWGW_CONFIG" && \
|
||||
chown "$OWGW_USER": "$OWGW_ROOT" "$OWGW_CONFIG"
|
||||
RUN apk add --update --no-cache librdkafka mariadb-connector-c libpq unixodbc su-exec gettext ca-certificates
|
||||
RUN apk add --update --no-cache librdkafka mariadb-connector-c libpq unixodbc su-exec gettext ca-certificates bash jq curl
|
||||
|
||||
COPY --from=builder /owgw/cmake-build/owgw /openwifi/owgw
|
||||
COPY --from=builder /cppkafka/cmake-build/src/lib/* /lib/
|
||||
COPY --from=builder /poco/cmake-build/lib/* /lib/
|
||||
|
||||
COPY owgw.properties.tmpl ${OWGW_CONFIG}/
|
||||
COPY owgw.properties.tmpl /
|
||||
COPY docker-entrypoint.sh /
|
||||
RUN wget https://raw.githubusercontent.com/Telecominfraproject/wlan-cloud-ucentral-deploy/main/docker-compose/certs/restapi-ca.pem \
|
||||
-O /usr/local/share/ca-certificates/restapi-ca-selfsigned.pem
|
||||
-O /usr/local/share/ca-certificates/restapi-ca-selfsigned.pem
|
||||
|
||||
COPY readiness_check /readiness_check
|
||||
|
||||
EXPOSE 15002 16002 16003 17002 16102
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
This document will describe how the API is built and how to use it.
|
||||
|
||||
## Where is the OpenAPI.
|
||||
This uses OpenAPI definition 3.0 and can be found [here](https://github.com/Telecominfraproject/wlan-cloud-ucentralgw/blob/main/openapi/ucentral/ucentral.yaml).
|
||||
This uses OpenAPI definition 3.0 and can be found [here](https://github.com/Telecominfraproject/wlan-cloud-ucentralgw/blob/main/openapi/ucentral/owgw.yaml).
|
||||
All endpoints begin with `/api/v1`.
|
||||
|
||||
## The flow
|
||||
|
||||
16
PROTOCOL.md
16
PROTOCOL.md
@@ -155,6 +155,22 @@ which version it is running. The Controller may decide to send the device a newe
|
||||
}
|
||||
```
|
||||
|
||||
#### Recovery Event
|
||||
Device may decide it has to do into recovery mode. This event should be used.
|
||||
```
|
||||
{ "jsonrpc" : "2.0" ,
|
||||
"method" : "recovery" ,
|
||||
"params" : {
|
||||
"serial" : <serial number> ,
|
||||
"uuid" : <the UUID of the configuration that generated the crash log>,
|
||||
"firmware: <the string describing the current firmware>,
|
||||
"reboot" : true/false (shoudld the device be instructed to reboot after loggin the information),
|
||||
"loglines" : [ an array of strings representing the logs from the log file ]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### Controller commands
|
||||
Most controller commands include a `when` member. This is a UTC clock time asking the AP
|
||||
to perform the command at that time. This is a suggestion only. The AP may ignore this
|
||||
|
||||
@@ -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 libmariadb-dev unixodbc-dev
|
||||
sudo apt install git cmake g++ libssl-dev libmariadb-dev
|
||||
sudo apt install libpq-dev libaprutil1-dev apache2-dev libboost-all-dev
|
||||
sudo apt install librdkafka-dev liblua5.3-dev libmysqlclient-dev
|
||||
sudo apt install librdkafka-dev libmysqlclient-dev default-libmysqlclient-dev
|
||||
|
||||
git clone https://github.com/stephb9959/poco
|
||||
cd poco
|
||||
@@ -502,7 +502,7 @@ environment variables. Here is a sample configuration:
|
||||
The communication protocol between the device and the controller is detailed in this [document](https://github.com/Telecominfraproject/wlan-cloud-ucentralgw/blob/main/PROTOCOL.md).
|
||||
|
||||
## OpenAPI
|
||||
The service supports an OpenAPI REST based interface for management. You can find the [definition here](https://github.com/Telecominfraproject/wlan-cloud-ucentralgw/blob/main/openapi/ucentral/ucentral.yaml).
|
||||
The service supports an OpenAPI REST based interface for management. You can find the [definition here](https://github.com/Telecominfraproject/wlan-cloud-ucentralgw/blob/main/openapi/ucentral/owgw.yaml).
|
||||
And here is [how to use it](https://github.com/Telecominfraproject/wlan-cloud-ucentralgw/blob/main/OPENAPI.md)
|
||||
|
||||
## Using the API
|
||||
|
||||
@@ -57,7 +57,7 @@ if [[ "$TEMPLATE_CONFIG" = 'true' && ! -f "$OWGW_CONFIG"/owgw.properties ]]; the
|
||||
STORAGE_TYPE_MYSQL_PASSWORD=${STORAGE_TYPE_MYSQL_PASSWORD:-"owgw"} \
|
||||
STORAGE_TYPE_MYSQL_DATABASE=${STORAGE_TYPE_MYSQL_DATABASE:-"owgw"} \
|
||||
STORAGE_TYPE_MYSQL_PORT=${STORAGE_TYPE_MYSQL_PORT:-"3306"} \
|
||||
envsubst < $OWGW_CONFIG/owgw.properties.tmpl > $OWGW_CONFIG/owgw.properties
|
||||
envsubst < /owgw.properties.tmpl > $OWGW_CONFIG/owgw.properties
|
||||
fi
|
||||
|
||||
if [ "$1" = '/openwifi/owgw' -a "$(id -u)" = '0' ]; then
|
||||
|
||||
@@ -20,7 +20,7 @@ Currently this chart is not assembled in charts archives, so [helm-git](https://
|
||||
To install the chart with the release name `my-release`:
|
||||
|
||||
```bash
|
||||
$ helm install --name my-release git+https://github.com/Telecominfraproject/wlan-cloud-ucentralgw@helm?ref=master
|
||||
$ helm install --name my-release git+https://github.com/Telecominfraproject/wlan-cloud-ucentralgw@helm/owgw-0.1.0.tgz?ref=master
|
||||
```
|
||||
|
||||
The command deploys the Gateway on the Kubernetes cluster in the default configuration. The [configuration](#configuration) section lists the parameters that can be configured during installation.
|
||||
|
||||
@@ -24,6 +24,12 @@ spec:
|
||||
metadata:
|
||||
annotations:
|
||||
checksum/config: {{ include "owgw.config" . | sha256sum }}
|
||||
{{- if .Values.podSecurityPolicy.enabled }}
|
||||
kubernetes.io/psp: {{ include "owgw.fullname" . }}-{{ .Release.Namespace }}-owgw-unsafe-sysctl
|
||||
{{- end }}
|
||||
{{- with .Values.podAnnotations }}
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
labels:
|
||||
app.kubernetes.io/name: {{ include "owgw.name" . }}
|
||||
app.kubernetes.io/instance: {{ .Release.Name }}
|
||||
|
||||
28
helm/templates/psp.yaml
Normal file
28
helm/templates/psp.yaml
Normal file
@@ -0,0 +1,28 @@
|
||||
{{- if .Values.podSecurityPolicy.enabled }}
|
||||
---
|
||||
apiVersion: policy/v1beta1
|
||||
kind: PodSecurityPolicy
|
||||
metadata:
|
||||
name: {{ include "owgw.fullname" . }}-{{ .Release.Namespace }}-owgw-unsafe-sysctl
|
||||
labels:
|
||||
app.kubernetes.io/name: {{ include "owgw.name" . }}
|
||||
helm.sh/chart: {{ include "owgw.chart" . }}
|
||||
app.kubernetes.io/instance: {{ .Release.Name }}
|
||||
app.kubernetes.io/managed-by: {{ .Release.Service }}
|
||||
spec:
|
||||
allowedUnsafeSysctls:
|
||||
{{- range $unsafeSysctl := .Values.securityContext.sysctls }}
|
||||
- {{ $unsafeSysctl.name }}
|
||||
{{- end }}
|
||||
privileged: false
|
||||
seLinux:
|
||||
rule: RunAsAny
|
||||
supplementalGroups:
|
||||
rule: RunAsAny
|
||||
runAsUser:
|
||||
rule: RunAsAny
|
||||
fsGroup:
|
||||
rule: RunAsAny
|
||||
volumes:
|
||||
- '*'
|
||||
{{- end }}
|
||||
16
helm/templates/role.yaml
Normal file
16
helm/templates/role.yaml
Normal file
@@ -0,0 +1,16 @@
|
||||
{{- if .Values.podSecurityPolicy.enabled }}
|
||||
---
|
||||
kind: Role
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
metadata:
|
||||
name: {{ include "owgw.fullname" . }}-owgw-use-unsafe-sysctl
|
||||
rules:
|
||||
- apiGroups:
|
||||
- policy
|
||||
resources:
|
||||
- podsecuritypolicies
|
||||
verbs:
|
||||
- use
|
||||
resourceNames:
|
||||
- {{ include "owgw.fullname" . }}-{{ .Release.Namespace }}-owgw-unsafe-sysctl
|
||||
{{- end }}
|
||||
15
helm/templates/rolebinding.yaml
Normal file
15
helm/templates/rolebinding.yaml
Normal file
@@ -0,0 +1,15 @@
|
||||
{{- if .Values.podSecurityPolicy.enabled }}
|
||||
---
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: RoleBinding
|
||||
metadata:
|
||||
name: {{ include "owgw.fullname" . }}-owgw-use-unsafe-sysctl-to-default
|
||||
roleRef:
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
kind: Role
|
||||
name: {{ include "owgw.fullname" . }}-owgw-use-unsafe-sysctl
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: default
|
||||
namespace: {{ .Release.Namespace }}
|
||||
{{- end }}
|
||||
@@ -8,7 +8,7 @@ fullnameOverride: ""
|
||||
images:
|
||||
owgw:
|
||||
repository: tip-tip-wlan-cloud-ucentral.jfrog.io/owgw
|
||||
tag: master
|
||||
tag: v2.4.0-RC6
|
||||
pullPolicy: Always
|
||||
# regcred:
|
||||
# registry: tip-tip-wlan-cloud-ucentral.jfrog.io
|
||||
@@ -43,9 +43,10 @@ checks:
|
||||
path: /
|
||||
port: 16102
|
||||
readiness:
|
||||
httpGet:
|
||||
path: /
|
||||
port: 16102
|
||||
exec:
|
||||
command:
|
||||
- /readiness_check
|
||||
failureThreshold: 1
|
||||
|
||||
ingresses:
|
||||
restapi:
|
||||
@@ -111,6 +112,17 @@ resources: {}
|
||||
|
||||
securityContext:
|
||||
fsGroup: 101
|
||||
# Usage of unsafe sysctls requires multiple things:
|
||||
# - allow these unsafe sysctls on kubelet level (by adding --allowed-unsafe-sysctls flag)
|
||||
# - enabling addition of PodSecurityContext setting podSecurityPolicy.enabled to "true" below
|
||||
# - uncommenting parameters below
|
||||
#sysctls:
|
||||
#- name: net.ipv4.tcp_keepalive_intvl
|
||||
# value: "5"
|
||||
#- name: net.ipv4.tcp_keepalive_probes
|
||||
# value: "2"
|
||||
#- name: net.ipv4.tcp_keepalive_time
|
||||
# value: "45"
|
||||
|
||||
nodeSelector: {}
|
||||
|
||||
@@ -118,6 +130,11 @@ tolerations: []
|
||||
|
||||
affinity: {}
|
||||
|
||||
podAnnotations: {}
|
||||
|
||||
podSecurityPolicy:
|
||||
enabled: false
|
||||
|
||||
persistence:
|
||||
enabled: true
|
||||
# storageClassName: "-"
|
||||
@@ -130,8 +147,16 @@ persistence:
|
||||
public_env_variables:
|
||||
OWGW_ROOT: /owgw-data
|
||||
OWGW_CONFIG: /owgw-data
|
||||
# Environment variables required for the readiness checks using script
|
||||
FLAGS: "-s --connect-timeout 3"
|
||||
# NOTE in order for readiness check to use system info you need to set READINESS_METHOD to "systeminfo" and set OWSEC to the OWSEC's REST API endpoint
|
||||
#READINESS_METHOD: systeminfo
|
||||
#OWSEC: gw-qa01.cicd.lab.wlan.tip.build:16001
|
||||
|
||||
secret_env_variables: {}
|
||||
secret_env_variables:
|
||||
# NOTE in order for readiness check to use system info method you need to override these values to the real OWSEC credentials
|
||||
OWSEC_USERNAME: tip@ucentral.com
|
||||
OWSEC_PASSWORD: openwifi
|
||||
|
||||
configProperties:
|
||||
# -> Public part
|
||||
|
||||
@@ -51,6 +51,16 @@ components:
|
||||
properties:
|
||||
ErrorCode:
|
||||
type: integer
|
||||
enum:
|
||||
- 0 # Success
|
||||
- 1 # PASSWORD_CHANGE_REQUIRED,
|
||||
- 2 # INVALID_CREDENTIALS,
|
||||
- 3 # PASSWORD_ALREADY_USED,
|
||||
- 4 # USERNAME_PENDING_VERIFICATION,
|
||||
- 5 # PASSWORD_INVALID,
|
||||
- 6 # INTERNAL_ERROR,
|
||||
- 7 # ACCESS_DENIED,
|
||||
- 8 # INVALID_TOKEN
|
||||
ErrorDetails:
|
||||
type: string
|
||||
ErrorDescription:
|
||||
@@ -647,6 +657,10 @@ components:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
enum:
|
||||
- dhcp-snooping
|
||||
- wire-frames
|
||||
- state
|
||||
uuid:
|
||||
type: string
|
||||
example:
|
||||
@@ -844,7 +858,7 @@ components:
|
||||
items:
|
||||
type: string
|
||||
|
||||
SystemGetSubSystemNemesResult:
|
||||
SystemGetSubSystemNamesResult:
|
||||
type: object
|
||||
properties:
|
||||
taglist:
|
||||
@@ -965,6 +979,22 @@ components:
|
||||
password:
|
||||
type: string
|
||||
|
||||
CapabilitiesModel:
|
||||
type: object
|
||||
properties:
|
||||
deviceType:
|
||||
type: string
|
||||
capabilities:
|
||||
type: string
|
||||
|
||||
CapabilitiesModelList:
|
||||
type: object
|
||||
properties:
|
||||
devices:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/CapabilitiesModel'
|
||||
|
||||
paths:
|
||||
/devices:
|
||||
get:
|
||||
@@ -1122,7 +1152,7 @@ paths:
|
||||
get:
|
||||
tags:
|
||||
- Commands
|
||||
summary: Returns a specific command
|
||||
summary: Returns a specific command.
|
||||
description: Returns a specific command
|
||||
operationId: getACommandDetails
|
||||
parameters:
|
||||
@@ -1147,7 +1177,7 @@ paths:
|
||||
delete:
|
||||
tags:
|
||||
- Commands
|
||||
summary: Delete a specific command
|
||||
summary: Delete a specific command.
|
||||
description: Delete a specific command
|
||||
operationId: deleteACommand
|
||||
parameters:
|
||||
@@ -1173,8 +1203,8 @@ paths:
|
||||
get:
|
||||
tags:
|
||||
- Configurations
|
||||
summary: Retrieve the lists of all default configurations
|
||||
description: Retrieve the lists of all default configurations
|
||||
summary: Retrieve the lists of all default configurations.
|
||||
description: Retrieve the lists of all default configurations.
|
||||
operationId: getDefaultConfigurations
|
||||
|
||||
responses:
|
||||
@@ -1193,8 +1223,8 @@ paths:
|
||||
get:
|
||||
tags:
|
||||
- Configurations
|
||||
summary: Retrieve a default configuration
|
||||
description: Retrieve a default configuration
|
||||
summary: Retrieve a default configuration.
|
||||
description: Retrieve a default configuration.
|
||||
operationId: getDefaultConfiguration
|
||||
parameters:
|
||||
- in: path
|
||||
@@ -1217,8 +1247,8 @@ paths:
|
||||
post:
|
||||
tags:
|
||||
- Configurations
|
||||
summary: Create a default configuration
|
||||
description: Create a default configuration
|
||||
summary: Create a default configuration.
|
||||
description: Create a default configuration.
|
||||
operationId: createDefaultConfiguration
|
||||
parameters:
|
||||
- in: path
|
||||
@@ -1290,7 +1320,7 @@ paths:
|
||||
get:
|
||||
tags:
|
||||
- Devices
|
||||
summary: Retrieve information for a single device
|
||||
summary: Retrieve information for a single device.
|
||||
description: Retrieve all the inforamtion about a single device
|
||||
operationId: getDeviceInformation
|
||||
parameters:
|
||||
@@ -1314,7 +1344,7 @@ paths:
|
||||
post:
|
||||
tags:
|
||||
- Devices
|
||||
summary: Creating a new device
|
||||
summary: Create a new device.
|
||||
operationId: createNewDevice
|
||||
parameters:
|
||||
- in: path
|
||||
@@ -1348,7 +1378,7 @@ paths:
|
||||
put:
|
||||
tags:
|
||||
- Devices
|
||||
summary: Updating a new device
|
||||
summary: Update a device.
|
||||
operationId: updateNewDevice
|
||||
parameters:
|
||||
- in: path
|
||||
@@ -1377,7 +1407,7 @@ paths:
|
||||
delete:
|
||||
tags:
|
||||
- Devices
|
||||
summary: Deleting a single device
|
||||
summary: Delete a single device.
|
||||
operationId: deleteDevice
|
||||
parameters:
|
||||
- in: path
|
||||
@@ -1454,7 +1484,7 @@ paths:
|
||||
delete:
|
||||
tags:
|
||||
- Commands
|
||||
summary: Delete some device logs
|
||||
summary: Delete some device logs.
|
||||
operationId: deleteDeviceLogs
|
||||
parameters:
|
||||
- in: path
|
||||
@@ -1496,7 +1526,7 @@ paths:
|
||||
get:
|
||||
tags:
|
||||
- Commands
|
||||
summary: Get the latest health checks for a given device
|
||||
summary: Get the latest health checks for a given device.
|
||||
operationId: getDeviceHealthChecks
|
||||
parameters:
|
||||
- in: path
|
||||
@@ -1543,7 +1573,7 @@ paths:
|
||||
|
||||
responses:
|
||||
200:
|
||||
description: Array of device health checks for this device
|
||||
description: Array of device health checks for this device
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
@@ -1556,7 +1586,7 @@ paths:
|
||||
delete:
|
||||
tags:
|
||||
- Commands
|
||||
summary: Delete some device health checks
|
||||
summary: Delete some device health checks.
|
||||
operationId: deleteDeviceHealthChecks
|
||||
parameters:
|
||||
- in: path
|
||||
@@ -1593,7 +1623,7 @@ paths:
|
||||
get:
|
||||
tags:
|
||||
- Commands
|
||||
summary: Get the latest capabilities for a given device
|
||||
summary: Get the latest capabilities for a given device.
|
||||
operationId: getDeviceCapabilities
|
||||
parameters:
|
||||
- in: path
|
||||
@@ -1616,7 +1646,7 @@ paths:
|
||||
delete:
|
||||
tags:
|
||||
- Commands
|
||||
summary: Delete the capabilities for a given device
|
||||
summary: Delete the capabilities for a given device.
|
||||
operationId: deleteDeviceCapabilities
|
||||
parameters:
|
||||
- in: path
|
||||
@@ -1640,7 +1670,7 @@ paths:
|
||||
get:
|
||||
tags:
|
||||
- Commands
|
||||
summary: Get the latest statistics for a given device
|
||||
summary: Get the latest statistics for a given device.
|
||||
operationId: getDeviceStats
|
||||
parameters:
|
||||
- in: path
|
||||
@@ -1708,7 +1738,7 @@ paths:
|
||||
delete:
|
||||
tags:
|
||||
- Commands
|
||||
summary: Get the latest statistics for a given device
|
||||
summary: Get the latest statistics for a given device.
|
||||
operationId: deleteDeviceStats
|
||||
parameters:
|
||||
- in: path
|
||||
@@ -1745,7 +1775,7 @@ paths:
|
||||
get:
|
||||
tags:
|
||||
- Commands
|
||||
summary: Get the latest status for a given device
|
||||
summary: Get the latest status for a given device.
|
||||
operationId: getDeviceStatus
|
||||
parameters:
|
||||
- in: path
|
||||
@@ -1795,7 +1825,7 @@ paths:
|
||||
post:
|
||||
tags:
|
||||
- Commands
|
||||
summary: Configura a device
|
||||
summary: Configure a device.
|
||||
operationId: updateConfigurationForADevice
|
||||
parameters:
|
||||
- in: path
|
||||
@@ -1821,7 +1851,7 @@ paths:
|
||||
post:
|
||||
tags:
|
||||
- Commands
|
||||
summary: Upgrade a device
|
||||
summary: Upgrade a device.
|
||||
operationId: UpgradeDeviceFirmware
|
||||
parameters:
|
||||
- in: path
|
||||
@@ -1847,7 +1877,7 @@ paths:
|
||||
post:
|
||||
tags:
|
||||
- Commands
|
||||
summary: Upgrade a device
|
||||
summary: Reboot a device.
|
||||
operationId: rebootDevice
|
||||
parameters:
|
||||
- in: path
|
||||
@@ -1873,7 +1903,7 @@ paths:
|
||||
post:
|
||||
tags:
|
||||
- Commands
|
||||
summary: Factory reset a device a device
|
||||
summary: Factory reset a device.
|
||||
operationId: factoryReset
|
||||
parameters:
|
||||
- in: path
|
||||
@@ -1899,7 +1929,7 @@ paths:
|
||||
post:
|
||||
tags:
|
||||
- Commands
|
||||
summary: Blink the LEDs on a device
|
||||
summary: Blink the LEDs on a device.
|
||||
operationId: ledsRequest
|
||||
parameters:
|
||||
- in: path
|
||||
@@ -1925,7 +1955,7 @@ paths:
|
||||
post:
|
||||
tags:
|
||||
- Commands
|
||||
summary: Launch a trace for a device
|
||||
summary: Launch a trace for a device.
|
||||
operationId: traceRequest
|
||||
parameters:
|
||||
- in: path
|
||||
@@ -1951,7 +1981,7 @@ paths:
|
||||
post:
|
||||
tags:
|
||||
- Commands
|
||||
summary: Launch a wifi scan for a device
|
||||
summary: Launch a wifi scan for a device.
|
||||
operationId: wifiscanRequest
|
||||
parameters:
|
||||
- in: path
|
||||
@@ -2003,7 +2033,7 @@ paths:
|
||||
post:
|
||||
tags:
|
||||
- Commands
|
||||
summary: Request a list of queued events
|
||||
summary: Request a list of queued events.
|
||||
operationId: eventQueueRequest
|
||||
parameters:
|
||||
- in: path
|
||||
@@ -2029,7 +2059,7 @@ paths:
|
||||
post:
|
||||
tags:
|
||||
- Commands
|
||||
summary: Request a telemetry stream
|
||||
summary: Request a telemetry stream.
|
||||
operationId: eventTelemetryStreamRequest
|
||||
parameters:
|
||||
- in: path
|
||||
@@ -2056,7 +2086,7 @@ paths:
|
||||
tags:
|
||||
- OUIs
|
||||
operationId: getOUIs
|
||||
summary: Get a list of OUIs
|
||||
summary: Get a list of OUIs.
|
||||
parameters:
|
||||
- in: query
|
||||
name: macList
|
||||
@@ -2075,7 +2105,7 @@ paths:
|
||||
get:
|
||||
tags:
|
||||
- Commands
|
||||
summary: Get the rtty parameters to initiate a session
|
||||
summary: Get the rtty parameters to initiate a session.
|
||||
operationId: getRttySessionInfo
|
||||
parameters:
|
||||
- in: path
|
||||
@@ -2099,7 +2129,7 @@ paths:
|
||||
get:
|
||||
tags:
|
||||
- Files
|
||||
summary: Get a file from the upload directory
|
||||
summary: Get a file from the upload directory.
|
||||
operationId: getUploadFile
|
||||
parameters:
|
||||
- in: path
|
||||
@@ -2129,7 +2159,7 @@ paths:
|
||||
delete:
|
||||
tags:
|
||||
- Files
|
||||
summary: Delete a file from the upload directory
|
||||
summary: Delete a file from the upload directory.
|
||||
operationId: deleteUploadFidelete
|
||||
parameters:
|
||||
- in: path
|
||||
@@ -2156,7 +2186,7 @@ paths:
|
||||
tags:
|
||||
- Blacklist
|
||||
summary: Returns a list blacklisted devices.
|
||||
description: Get a list of blacklisteddevices.
|
||||
description: Get a list of blacklisted devices.
|
||||
operationId: getBlacklistDeviceList
|
||||
parameters:
|
||||
- in: query
|
||||
@@ -2189,17 +2219,76 @@ paths:
|
||||
404:
|
||||
$ref: '#/components/responses/NotFound'
|
||||
|
||||
/blacklist/{serialNumber}:
|
||||
get:
|
||||
tags:
|
||||
- Blacklist
|
||||
summary: Returns a blacklist entry.
|
||||
description: Get a list of blacklisted devices.
|
||||
operationId: getBlacklistDevice
|
||||
parameters:
|
||||
- in: path
|
||||
description: Pagination start (starts at 1. If not specified, 1 is assumed)
|
||||
name: serialNumber
|
||||
schema:
|
||||
type: string
|
||||
required: true
|
||||
responses:
|
||||
200:
|
||||
description: List blacklisted devices
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/BlackDeviceInfo'
|
||||
403:
|
||||
$ref: '#/components/responses/Unauthorized'
|
||||
404:
|
||||
$ref: '#/components/responses/NotFound'
|
||||
|
||||
post:
|
||||
tags:
|
||||
- Blacklist
|
||||
summary: Adds to the blacklist
|
||||
operationId: addToBlackList
|
||||
summary: Create to the blacklist.
|
||||
operationId: createBlackListDevice
|
||||
parameters:
|
||||
- in: path
|
||||
description: Pagination start (starts at 1. If not specified, 1 is assumed)
|
||||
name: serialNumber
|
||||
schema:
|
||||
type: string
|
||||
required: true
|
||||
requestBody:
|
||||
description: Add blacklisted device
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/BlackDeviceInfo'
|
||||
responses:
|
||||
200:
|
||||
$ref: '#/components/responses/Success'
|
||||
403:
|
||||
$ref: '#/components/responses/Unauthorized'
|
||||
404:
|
||||
$ref: '#/components/responses/NotFound'
|
||||
|
||||
put:
|
||||
tags:
|
||||
- Blacklist
|
||||
summary: Modify to the blacklist.
|
||||
operationId: modifyBlackList
|
||||
parameters:
|
||||
- in: path
|
||||
description: Pagination start (starts at 1. If not specified, 1 is assumed)
|
||||
name: serialNumber
|
||||
schema:
|
||||
type: string
|
||||
required: true
|
||||
requestBody:
|
||||
description: Add blacklisted devices
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/BlackDeviceList'
|
||||
$ref: '#/components/schemas/BlackDeviceInfo'
|
||||
responses:
|
||||
200:
|
||||
$ref: '#/components/responses/Success'
|
||||
@@ -2211,11 +2300,10 @@ paths:
|
||||
delete:
|
||||
tags:
|
||||
- Blacklist
|
||||
summary: Delete from the blacklist
|
||||
summary: Delete from the blacklist.
|
||||
operationId: deleteFromBlackList
|
||||
parameters:
|
||||
- in: query
|
||||
description: Serial Number
|
||||
- in: path
|
||||
name: serialNumber
|
||||
schema:
|
||||
type: string
|
||||
@@ -2228,11 +2316,29 @@ paths:
|
||||
404:
|
||||
$ref: '#/components/responses/NotFound'
|
||||
|
||||
/capabilities:
|
||||
get:
|
||||
tags:
|
||||
- Devices
|
||||
summary: Get the list of device types and capabilities.
|
||||
operationId: getCapabilitiesList
|
||||
responses:
|
||||
200:
|
||||
description: Successful command execution
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/CapabilitiesModelList'
|
||||
403:
|
||||
$ref: '#/components/responses/Unauthorized'
|
||||
404:
|
||||
$ref: '#/components/responses/NotFound'
|
||||
|
||||
/deviceDashboard:
|
||||
get:
|
||||
tags:
|
||||
- Dashboards
|
||||
summary: Get the last version of the dashboard
|
||||
summary: Get the last version of the dashboard.
|
||||
operationId: getDeviceDashboard
|
||||
responses:
|
||||
200:
|
||||
@@ -2251,7 +2357,7 @@ paths:
|
||||
post:
|
||||
tags:
|
||||
- System Commands
|
||||
summary: Perform some systeme wide commands
|
||||
summary: Perform some system wide commands.
|
||||
operationId: systemCommand
|
||||
requestBody:
|
||||
description: Command details
|
||||
@@ -2266,14 +2372,14 @@ paths:
|
||||
- $ref: '#/components/schemas/SystemCommandGetSubsystemNames'
|
||||
responses:
|
||||
200:
|
||||
description: Successfull command execution
|
||||
description: Successful command execution
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
oneOf:
|
||||
- $ref: '#/components/schemas/SystemGetLogLevelsResult'
|
||||
- $ref: '#/components/schemas/SystemCommandGetLogLevelNamesResult'
|
||||
- $ref: '#/components/schemas/SystemGetSubSystemNemesResult'
|
||||
- $ref: '#/components/schemas/SystemGetSubSystemNamesResult'
|
||||
403:
|
||||
$ref: '#/components/responses/Unauthorized'
|
||||
404:
|
||||
@@ -2295,7 +2401,7 @@ paths:
|
||||
|
||||
responses:
|
||||
200:
|
||||
description: Successfull command execution
|
||||
description: Successful command execution
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
@@ -2304,4 +2410,4 @@ paths:
|
||||
403:
|
||||
$ref: '#/components/responses/Unauthorized'
|
||||
404:
|
||||
$ref: '#/components/responses/NotFound'
|
||||
$ref: '#/components/responses/NotFound'
|
||||
@@ -161,7 +161,7 @@ logging.channels.c1.formatter = f1
|
||||
|
||||
# This is where the logs will be written. This path MUST exist
|
||||
logging.channels.c2.class = FileChannel
|
||||
logging.channels.c2.path = $UCENTRALGW_ROOT/logs/log
|
||||
logging.channels.c2.path = $OWGW_ROOT/logs/log
|
||||
logging.channels.c2.formatter.class = PatternFormatter
|
||||
logging.channels.c2.formatter.pattern = %Y-%m-%d %H:%M:%S %s: [%p] %t
|
||||
logging.channels.c2.rotation = 20 M
|
||||
|
||||
65
readiness_check
Executable file
65
readiness_check
Executable file
@@ -0,0 +1,65 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
if [[ "$(which jq)" == "" ]]
|
||||
then
|
||||
echo "You need the package jq installed to use this script."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ "$(which curl)" == "" ]]
|
||||
then
|
||||
echo "You need the package curl installed to use this script."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ "${OWSEC}" == "" ]]
|
||||
then
|
||||
echo "You must set the variable OWSEC in order to use this script. Something like"
|
||||
echo "OWSEC=security.isp.com:16001"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ "${OWSEC_USERNAME}" == "" ]]
|
||||
then
|
||||
echo "You must set the variable OWSEC_USERNAME in order to use this script. Something like"
|
||||
echo "OWSEC_USERNAME=tip@ucentral.com"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ "${OWSEC_PASSWORD}" == "" ]]
|
||||
then
|
||||
echo "You must set the variable OWSEC_PASSWORD in order to use this script. Something like"
|
||||
echo "OWSEC_PASSWORD=openwifi"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ "${READINESS_METHOD}" == "systeminfo" ]]
|
||||
then
|
||||
# Get OAuth token from OWSEC and cache it or use cached one
|
||||
payload="{ \"userId\" : \"$OWSEC_USERNAME\" , \"password\" : \"$OWSEC_PASSWORD\" }"
|
||||
if [[ -f "/tmp/token" ]]
|
||||
then
|
||||
token=$(cat /tmp/token)
|
||||
else
|
||||
token=$(curl ${FLAGS} -X POST -H "Content-Type: application/json" -d "$payload" "https://${OWSEC}/api/v1/oauth2" | jq -r '.access_token')
|
||||
fi
|
||||
if [[ "${token}" == "" ]]
|
||||
then
|
||||
echo "Could not login. Please verify the host and username/password."
|
||||
exit 13
|
||||
fi
|
||||
echo -n $token > /tmp/token
|
||||
|
||||
# Make systeminfo request to the local owgw instance
|
||||
export RESTAPI_PORT=$(grep 'openwifi.restapi.host.0.port' $OWGW_CONFIG/owgw.properties | awk -F '=' '{print $2}' | xargs | envsubst)
|
||||
curl ${FLAGS} -k -X GET "https://localhost:$RESTAPI_PORT/api/v1/system?command=info" \
|
||||
-H "accept: application/json" \
|
||||
-H "Authorization: Bearer ${token}" > /tmp/result.json
|
||||
exit_code=$?
|
||||
jq < /tmp/result.json
|
||||
exit $exit_code
|
||||
else
|
||||
export ALB_PORT=$(grep 'alb.port' $OWGW_CONFIG/owgw.properties | awk -F '=' '{print $2}' | xargs | envsubst)
|
||||
curl localhost:$ALB_PORT
|
||||
fi
|
||||
@@ -1,118 +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_ALBHEALTHCHECKSERVER_H
|
||||
#define UCENTRALGW_ALBHEALTHCHECKSERVER_H
|
||||
|
||||
#include <memory>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
|
||||
#include "Poco/Thread.h"
|
||||
#include "Poco/Net/HTTPServer.h"
|
||||
#include "Poco/Net/HTTPServerRequest.h"
|
||||
#include "Poco/Net/HTTPServerResponse.h"
|
||||
#include "Poco/Net/HTTPRequestHandler.h"
|
||||
#include "Poco/Logger.h"
|
||||
|
||||
#include "Daemon.h"
|
||||
#include "SubSystemServer.h"
|
||||
|
||||
namespace OpenWifi {
|
||||
|
||||
class ALBRequestHandler: public Poco::Net::HTTPRequestHandler
|
||||
/// Return a HTML document with the current date and time.
|
||||
{
|
||||
public:
|
||||
explicit ALBRequestHandler(Poco::Logger & L)
|
||||
: Logger_(L)
|
||||
{
|
||||
}
|
||||
|
||||
void handleRequest(Poco::Net::HTTPServerRequest& Request, Poco::Net::HTTPServerResponse& Response) override
|
||||
{
|
||||
Logger_.information(Poco::format("ALB-REQUEST(%s): New ALB request.",Request.clientAddress().toString()));
|
||||
Response.setChunkedTransferEncoding(true);
|
||||
Response.setContentType("text/html");
|
||||
Response.setDate(Poco::Timestamp());
|
||||
Response.setStatus(Poco::Net::HTTPResponse::HTTP_OK);
|
||||
Response.setKeepAlive(true);
|
||||
Response.set("Connection","keep-alive");
|
||||
Response.setVersion(Poco::Net::HTTPMessage::HTTP_1_1);
|
||||
std::ostream &Answer = Response.send();
|
||||
Answer << "uCentralGW Alive and kicking!" ;
|
||||
}
|
||||
|
||||
private:
|
||||
Poco::Logger & Logger_;
|
||||
};
|
||||
|
||||
class ALBRequestHandlerFactory: public Poco::Net::HTTPRequestHandlerFactory
|
||||
{
|
||||
public:
|
||||
explicit ALBRequestHandlerFactory(Poco::Logger & L):
|
||||
Logger_(L)
|
||||
{
|
||||
}
|
||||
|
||||
ALBRequestHandler* createRequestHandler(const Poco::Net::HTTPServerRequest& request) override
|
||||
{
|
||||
if (request.getURI() == "/")
|
||||
return new ALBRequestHandler(Logger_);
|
||||
else
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
private:
|
||||
Poco::Logger &Logger_;
|
||||
};
|
||||
|
||||
class ALBHealthCheckServer : public SubSystemServer {
|
||||
public:
|
||||
ALBHealthCheckServer() noexcept:
|
||||
SubSystemServer("ALBHealthCheckServer", "ALB-SVR", "alb")
|
||||
{
|
||||
}
|
||||
|
||||
static ALBHealthCheckServer *instance() {
|
||||
if (instance_ == nullptr) {
|
||||
instance_ = new ALBHealthCheckServer;
|
||||
}
|
||||
return instance_;
|
||||
}
|
||||
|
||||
int Start() override {
|
||||
if(Daemon()->ConfigGetBool("alb.enable",false)) {
|
||||
Port_ = (int)Daemon()->ConfigGetInt("alb.port",15015);
|
||||
Socket_ = std::make_unique<Poco::Net::ServerSocket>(Port_);
|
||||
auto Params = new Poco::Net::HTTPServerParams;
|
||||
Server_ = std::make_unique<Poco::Net::HTTPServer>(new ALBRequestHandlerFactory(Logger_), *Socket_, Params);
|
||||
Server_->start();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Stop() override {
|
||||
if(Server_)
|
||||
Server_->stop();
|
||||
}
|
||||
|
||||
private:
|
||||
static ALBHealthCheckServer *instance_;
|
||||
std::unique_ptr<Poco::Net::HTTPServer> Server_;
|
||||
std::unique_ptr<Poco::Net::ServerSocket> Socket_;
|
||||
int Port_ = 0;
|
||||
};
|
||||
|
||||
inline ALBHealthCheckServer * ALBHealthCheckServer() { return ALBHealthCheckServer::instance(); }
|
||||
inline class ALBHealthCheckServer * ALBHealthCheckServer::instance_ = nullptr;
|
||||
}
|
||||
|
||||
#endif // UCENTRALGW_ALBHEALTHCHECKSERVER_H
|
||||
61
src/APIServers.cpp
Normal file
61
src/APIServers.cpp
Normal file
@@ -0,0 +1,61 @@
|
||||
//
|
||||
// Created by stephane bourque on 2021-10-23.
|
||||
//
|
||||
|
||||
#include "framework/MicroService.h"
|
||||
|
||||
#include "RESTAPI/RESTAPI_blacklist.h"
|
||||
#include "RESTAPI/RESTAPI_blacklist_list.h"
|
||||
#include "RESTAPI/RESTAPI_command.h"
|
||||
#include "RESTAPI/RESTAPI_commands.h"
|
||||
#include "RESTAPI/RESTAPI_default_configuration.h"
|
||||
#include "RESTAPI/RESTAPI_default_configurations.h"
|
||||
#include "RESTAPI/RESTAPI_deviceDashboardHandler.h"
|
||||
#include "RESTAPI/RESTAPI_device_commandHandler.h"
|
||||
#include "RESTAPI/RESTAPI_device_handler.h"
|
||||
#include "RESTAPI/RESTAPI_devices_handler.h"
|
||||
#include "RESTAPI/RESTAPI_file.h"
|
||||
#include "RESTAPI/RESTAPI_ouis.h"
|
||||
|
||||
#include "RESTAPI/RESTAPI_capabilities_handler.h"
|
||||
#include "RESTAPI/RESTAPI_TelemetryWebSocket.h"
|
||||
#include "RESTAPI/RESTAPI_webSocketServer.h"
|
||||
|
||||
namespace OpenWifi {
|
||||
|
||||
Poco::Net::HTTPRequestHandler * RESTAPI_external_server(const char *Path, RESTAPIHandler::BindingMap &Bindings,
|
||||
Poco::Logger & L, RESTAPI_GenericServer & S) {
|
||||
return RESTAPI_Router<
|
||||
RESTAPI_devices_handler,
|
||||
RESTAPI_device_handler,
|
||||
RESTAPI_device_commandHandler,
|
||||
RESTAPI_default_configurations,
|
||||
RESTAPI_default_configuration,
|
||||
RESTAPI_command,
|
||||
RESTAPI_commands,
|
||||
RESTAPI_ouis,
|
||||
RESTAPI_file,
|
||||
RESTAPI_system_command,
|
||||
RESTAPI_deviceDashboardHandler,
|
||||
RESTAPI_webSocketServer,
|
||||
RESTAPI_blacklist,
|
||||
RESTAPI_blacklist_list,
|
||||
RESTAPI_capabilities_handler,
|
||||
RESTAPI_TelemetryWebSocket>(Path,Bindings,L, S);
|
||||
}
|
||||
|
||||
Poco::Net::HTTPRequestHandler * RESTAPI_internal_server(const char *Path, RESTAPIHandler::BindingMap &Bindings,
|
||||
Poco::Logger & L, RESTAPI_GenericServer & S) {
|
||||
return RESTAPI_Router_I<
|
||||
RESTAPI_devices_handler,
|
||||
RESTAPI_device_handler,
|
||||
RESTAPI_device_commandHandler,
|
||||
RESTAPI_default_configurations,
|
||||
RESTAPI_default_configuration,
|
||||
RESTAPI_command,
|
||||
RESTAPI_commands,
|
||||
RESTAPI_ouis,
|
||||
RESTAPI_file, RESTAPI_blacklist,
|
||||
RESTAPI_blacklist_list>(Path,Bindings,L, S);
|
||||
}
|
||||
}
|
||||
@@ -1,93 +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 <utility>
|
||||
|
||||
#include "AuthClient.h"
|
||||
#include "RESTAPI_SecurityObjects.h"
|
||||
#include "Daemon.h"
|
||||
#include "OpenAPIRequest.h"
|
||||
|
||||
namespace OpenWifi {
|
||||
class AuthClient * AuthClient::instance_ = nullptr;
|
||||
|
||||
int AuthClient::Start() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
void AuthClient::Stop() {
|
||||
|
||||
}
|
||||
|
||||
void AuthClient::RemovedCachedToken(const std::string &Token) {
|
||||
std::lock_guard G(Mutex_);
|
||||
UserCache_.erase(Token);
|
||||
}
|
||||
|
||||
bool IsTokenExpired(const SecurityObjects::WebToken &T) {
|
||||
return ((T.expires_in_+T.created_)<std::time(nullptr));
|
||||
}
|
||||
|
||||
bool AuthClient::IsAuthorized(Poco::Net::HTTPServerRequest & Request, std::string &SessionToken, SecurityObjects::UserInfoAndPolicy & UInfo ) {
|
||||
std::lock_guard 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;
|
||||
}
|
||||
|
||||
bool AuthClient::IsTokenAuthorized(const std::string &SessionToken, SecurityObjects::UserInfoAndPolicy & UInfo) {
|
||||
std::lock_guard 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;
|
||||
}
|
||||
}
|
||||
@@ -1,45 +0,0 @@
|
||||
//
|
||||
// Created by stephane bourque on 2021-06-30.
|
||||
//
|
||||
|
||||
#ifndef UCENTRALGW_AUTHCLIENT_H
|
||||
#define UCENTRALGW_AUTHCLIENT_H
|
||||
|
||||
#include "Poco/JSON/Object.h"
|
||||
#include "Poco/Net/HTTPServerRequest.h"
|
||||
#include "Poco/Net/HTTPServerResponse.h"
|
||||
#include "Poco/JWT/Signer.h"
|
||||
#include "Poco/SHA2Engine.h"
|
||||
#include "RESTAPI_SecurityObjects.h"
|
||||
#include "SubSystemServer.h"
|
||||
|
||||
namespace OpenWifi {
|
||||
|
||||
class AuthClient : public SubSystemServer {
|
||||
public:
|
||||
explicit AuthClient() noexcept:
|
||||
SubSystemServer("Authentication", "AUTH-CLNT", "authentication")
|
||||
{
|
||||
}
|
||||
|
||||
static AuthClient *instance() {
|
||||
if (instance_ == nullptr) {
|
||||
instance_ = new AuthClient;
|
||||
}
|
||||
return instance_;
|
||||
}
|
||||
|
||||
int Start() override;
|
||||
void Stop() override;
|
||||
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_;
|
||||
OpenWifi::SecurityObjects::UserInfoCache UserCache_;
|
||||
};
|
||||
|
||||
inline AuthClient * AuthClient() { return AuthClient::instance(); }
|
||||
}
|
||||
|
||||
#endif // UCENTRALGW_AUTHCLIENT_H
|
||||
@@ -7,13 +7,14 @@
|
||||
//
|
||||
#include <fstream>
|
||||
|
||||
#include "CentralConfig.h"
|
||||
#include "Daemon.h"
|
||||
|
||||
#include "Poco/JSON/Object.h"
|
||||
#include "Poco/JSON/Parser.h"
|
||||
#include "Poco/File.h"
|
||||
|
||||
#include "CentralConfig.h"
|
||||
#include "framework/MicroService.h"
|
||||
#include "Daemon.h"
|
||||
|
||||
namespace OpenWifi::Config {
|
||||
|
||||
static std::string DefaultConfiguration;
|
||||
@@ -119,7 +120,7 @@ namespace OpenWifi::Config {
|
||||
})lit"};
|
||||
|
||||
void SetBasicConfigFile() {
|
||||
Poco::File DefaultConfigFileName{Daemon()->DataDir()+"/default_config.json"};
|
||||
Poco::File DefaultConfigFileName{MicroService::instance().DataDir()+"/default_config.json"};
|
||||
DefaultConfiguration = BasicConfig;
|
||||
std::ofstream F;
|
||||
F.open(DefaultConfigFileName.path(),std::ios::binary);
|
||||
@@ -134,7 +135,7 @@ namespace OpenWifi::Config {
|
||||
void Config::Init() {
|
||||
if(DefaultConfiguration.empty()) {
|
||||
// open the file
|
||||
Poco::File DefaultConfigFileName{Daemon()->DataDir()+"/default_config.json"};
|
||||
Poco::File DefaultConfigFileName{MicroService::instance().DataDir()+"/default_config.json"};
|
||||
try {
|
||||
if (!DefaultConfigFileName.exists()) {
|
||||
SetBasicConfigFile();
|
||||
@@ -232,7 +233,7 @@ namespace OpenWifi::Config {
|
||||
}
|
||||
catch ( const Poco::Exception & E )
|
||||
{
|
||||
Daemon::instance()->logger().warning(Poco::format("%s: Failed with: %s", std::string(__func__) , E.displayText()));
|
||||
Daemon()->logger().log(E);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -6,21 +6,19 @@
|
||||
// Arilia Wireless Inc.
|
||||
//
|
||||
|
||||
#include "CommandManager.h"
|
||||
#include <algorithm>
|
||||
|
||||
#include "CommandManager.h"
|
||||
#include "DeviceRegistry.h"
|
||||
#include "RESTAPI_GWobjects.h"
|
||||
#include "RESTAPI_handler.h"
|
||||
#include "StorageService.h"
|
||||
#include "uCentralProtocol.h"
|
||||
|
||||
#include "Poco/JSON/Parser.h"
|
||||
|
||||
namespace OpenWifi {
|
||||
#include "CommandManager.h"
|
||||
#include "DeviceRegistry.h"
|
||||
#include "RESTObjects//RESTAPI_GWobjects.h"
|
||||
#include "StorageService.h"
|
||||
#include "framework/MicroService.h"
|
||||
#include "framework/uCentral_Protocol.h"
|
||||
|
||||
class CommandManager * CommandManager::instance_ = nullptr;
|
||||
|
||||
namespace OpenWifi {
|
||||
|
||||
void CommandManager::run() {
|
||||
Running_ = true;
|
||||
@@ -31,7 +29,7 @@ namespace OpenWifi {
|
||||
break;
|
||||
|
||||
std::vector<GWObjects::CommandDetails> Commands;
|
||||
if(Storage()->GetReadyToExecuteCommands(1,200,Commands))
|
||||
if(StorageService()->GetReadyToExecuteCommands(1,200,Commands))
|
||||
{
|
||||
for(auto & Cmd: Commands)
|
||||
{
|
||||
@@ -47,7 +45,7 @@ namespace OpenWifi {
|
||||
*Params,
|
||||
Cmd.UUID,
|
||||
RPC_Id)) {
|
||||
Storage()->SetCommandExecuted(Cmd.UUID);
|
||||
StorageService()->SetCommandExecuted(Cmd.UUID);
|
||||
Logger_.information(Poco::format("Sent command '%s' to '%s'",Cmd.Command,Cmd.SerialNumber));
|
||||
} else {
|
||||
Logger_.information(Poco::format("Failed to send command '%s' to %s",Cmd.Command,Cmd.SerialNumber));
|
||||
@@ -155,7 +153,7 @@ namespace OpenWifi {
|
||||
RPC->second.Result = Obj;
|
||||
Logger_.information(Poco::format("(%s): Received RPC answer %lu", SerialNumber, ID));
|
||||
G.unlock();
|
||||
Storage()->CommandCompleted(RPC->second.UUID, Obj, true);
|
||||
StorageService()->CommandCompleted(RPC->second.UUID, Obj, true);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
@@ -19,8 +19,8 @@
|
||||
#include "Poco/Net/HTTPServerRequest.h"
|
||||
#include "Poco/Net/HTTPServerResponse.h"
|
||||
|
||||
#include "RESTAPI_GWobjects.h"
|
||||
#include "SubSystemServer.h"
|
||||
#include "RESTObjects//RESTAPI_GWobjects.h"
|
||||
#include "framework/MicroService.h"
|
||||
|
||||
namespace OpenWifi {
|
||||
|
||||
@@ -68,15 +68,12 @@ namespace OpenWifi {
|
||||
bool GetCommand(uint64_t Id, const std::string & SerialNumber, CommandTag &T);
|
||||
|
||||
static CommandManager *instance() {
|
||||
if (instance_ == nullptr) {
|
||||
instance_ = new CommandManager;
|
||||
}
|
||||
static CommandManager *instance_ = new CommandManager;
|
||||
return instance_;
|
||||
}
|
||||
inline bool Running() const { return Running_; }
|
||||
|
||||
private:
|
||||
static CommandManager * instance_;
|
||||
std::atomic_bool Running_ = false;
|
||||
Poco::Thread ManagerThread;
|
||||
uint64_t Id_=2; // do not start @1. We ignore ID=1 & 0 is illegal..
|
||||
|
||||
@@ -5,5 +5,4 @@
|
||||
#include "ConfigurationCache.h"
|
||||
|
||||
namespace OpenWifi {
|
||||
class ConfigurationCache * ConfigurationCache::instance_ = nullptr;
|
||||
}
|
||||
@@ -13,10 +13,9 @@ namespace OpenWifi {
|
||||
class ConfigurationCache {
|
||||
public:
|
||||
|
||||
static ConfigurationCache &instance() {
|
||||
if(instance_== nullptr)
|
||||
instance_ = new ConfigurationCache;
|
||||
return *instance_;
|
||||
static ConfigurationCache & instance() {
|
||||
static ConfigurationCache instance;
|
||||
return instance;
|
||||
}
|
||||
|
||||
inline uint64_t CurrentConfig(const std::string &SerialNumber) {
|
||||
@@ -27,13 +26,12 @@ namespace OpenWifi {
|
||||
return Hint->second;
|
||||
}
|
||||
|
||||
void Add(const std::string &SerialNumber, uint64_t Id) {
|
||||
inline void Add(const std::string &SerialNumber, uint64_t Id) {
|
||||
std::lock_guard G(Mutex_);
|
||||
Cache_[SerialNumber]=Id;
|
||||
}
|
||||
|
||||
private:
|
||||
static ConfigurationCache *instance_;
|
||||
std::mutex Mutex_;
|
||||
std::map<std::string,uint64_t> Cache_;
|
||||
};
|
||||
|
||||
@@ -10,45 +10,33 @@
|
||||
#include "Poco/Util/Application.h"
|
||||
#include "Poco/Util/Option.h"
|
||||
#include "Poco/Environment.h"
|
||||
#include "Poco/Net/HTTPStreamFactory.h"
|
||||
|
||||
#include "Daemon.h"
|
||||
|
||||
#include "CentralConfig.h"
|
||||
#include "CommandManager.h"
|
||||
#include "Daemon.h"
|
||||
#include "DeviceRegistry.h"
|
||||
#include "FileUploader.h"
|
||||
#include "RESTAPI_server.h"
|
||||
#include "StorageService.h"
|
||||
#include "WebSocketServer.h"
|
||||
#include "CentralConfig.h"
|
||||
#include "OUIServer.h"
|
||||
#include "StateProcessor.h"
|
||||
#include "Utils.h"
|
||||
#include "RESTAPI_InternalServer.h"
|
||||
#include "AuthClient.h"
|
||||
#include "StorageArchiver.h"
|
||||
#include "SerialNumberCache.h"
|
||||
#include "StorageArchiver.h"
|
||||
#include "StorageService.h"
|
||||
#include "TelemetryStream.h"
|
||||
#include "ConfigurationValidator.h"
|
||||
#include "WebSocketServer.h"
|
||||
#include "framework/ConfigurationValidator.h"
|
||||
#include "framework/MicroService.h"
|
||||
|
||||
namespace OpenWifi {
|
||||
class Daemon *Daemon::instance_ = nullptr;
|
||||
|
||||
class Daemon *Daemon::instance() {
|
||||
if (instance_ == nullptr) {
|
||||
instance_ = new Daemon(vDAEMON_PROPERTIES_FILENAME,
|
||||
static Daemon instance(vDAEMON_PROPERTIES_FILENAME,
|
||||
vDAEMON_ROOT_ENV_VAR,
|
||||
vDAEMON_CONFIG_ENV_VAR,
|
||||
vDAEMON_APP_NAME,
|
||||
vDAEMON_BUS_TIMER,
|
||||
Types::SubSystemVec{
|
||||
Storage(),
|
||||
SubSystemVec{
|
||||
StorageService(),
|
||||
SerialNumberCache(),
|
||||
ConfigurationValidator(),
|
||||
AuthClient(),
|
||||
DeviceRegistry(),
|
||||
RESTAPI_server(),
|
||||
RESTAPI_InternalServer(),
|
||||
WebSocketServer(),
|
||||
CommandManager(),
|
||||
FileUploader(),
|
||||
@@ -56,12 +44,10 @@ namespace OpenWifi {
|
||||
StorageArchiver(),
|
||||
TelemetryStream()
|
||||
});
|
||||
}
|
||||
return instance_;
|
||||
return &instance;
|
||||
}
|
||||
|
||||
void Daemon::initialize(Poco::Util::Application &self) {
|
||||
MicroService::initialize(*this);
|
||||
void Daemon::initialize() {
|
||||
Config::Config::Init();
|
||||
AutoProvisioning_ = config().getBool("openwifi.autoprovisioning",false);
|
||||
|
||||
@@ -88,6 +74,10 @@ namespace OpenWifi {
|
||||
}
|
||||
}
|
||||
|
||||
void MicroServicePostInitialization() {
|
||||
Daemon()->initialize();
|
||||
}
|
||||
|
||||
[[nodiscard]] std::string Daemon::IdentifyDevice(const std::string & Id ) const {
|
||||
for(const auto &[Type,List]:DeviceTypeIdentifications_)
|
||||
{
|
||||
@@ -98,12 +88,12 @@ namespace OpenWifi {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
try {
|
||||
|
||||
auto App = OpenWifi::Daemon::instance();
|
||||
auto ExitCode = App->run(argc, argv);
|
||||
delete App;
|
||||
|
||||
return ExitCode;
|
||||
|
||||
} catch (Poco::Exception &exc) {
|
||||
|
||||
@@ -26,8 +26,8 @@
|
||||
#include "Poco/Crypto/Cipher.h"
|
||||
|
||||
#include "Dashboard.h"
|
||||
#include "MicroService.h"
|
||||
#include "OpenWifiTypes.h"
|
||||
#include "framework/MicroService.h"
|
||||
#include "framework/OpenWifiTypes.h"
|
||||
|
||||
namespace OpenWifi {
|
||||
|
||||
@@ -44,17 +44,16 @@ namespace OpenWifi {
|
||||
const std::string & ConfigEnv,
|
||||
const std::string & AppName,
|
||||
uint64_t BusTimer,
|
||||
const Types::SubSystemVec & SubSystems) :
|
||||
const SubSystemVec & SubSystems) :
|
||||
MicroService( PropFile, RootEnv, ConfigEnv, AppName, BusTimer, SubSystems) {};
|
||||
|
||||
bool AutoProvisioning() const { return AutoProvisioning_ ; }
|
||||
[[nodiscard]] std::string IdentifyDevice(const std::string & Compatible) const;
|
||||
void initialize(Poco::Util::Application &self) override;
|
||||
void initialize();
|
||||
static Daemon *instance();
|
||||
inline DeviceDashboard & GetDashboard() { return DB_; }
|
||||
Poco::Logger & Log() { return Poco::Logger::get(AppName()); }
|
||||
private:
|
||||
static Daemon *instance_;
|
||||
bool AutoProvisioning_ = false;
|
||||
Types::StringMapStringSet DeviceTypeIdentifications_;
|
||||
DeviceDashboard DB_;
|
||||
|
||||
@@ -12,8 +12,8 @@ namespace OpenWifi {
|
||||
|
||||
if(LastRun_==0 || (Now-LastRun_)>120) {
|
||||
DB_.reset();
|
||||
Storage()->AnalyzeCommands(DB_.commands);
|
||||
Storage()->AnalyzeDevices(DB_);
|
||||
StorageService()->AnalyzeCommands(DB_.commands);
|
||||
StorageService()->AnalyzeDevices(DB_);
|
||||
LastRun_ = Now;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
#ifndef UCENTRALGW_DASHBOARD_H
|
||||
#define UCENTRALGW_DASHBOARD_H
|
||||
|
||||
#include "OpenWifiTypes.h"
|
||||
#include "RESTAPI_GWobjects.h"
|
||||
#include "RESTObjects//RESTAPI_GWobjects.h"
|
||||
#include "framework/OpenWifiTypes.h"
|
||||
|
||||
namespace OpenWifi {
|
||||
class DeviceDashboard {
|
||||
|
||||
@@ -6,22 +6,14 @@
|
||||
// Arilia Wireless Inc.
|
||||
//
|
||||
|
||||
#include "DeviceRegistry.h"
|
||||
|
||||
#include "RESTAPI_handler.h"
|
||||
#include "WebSocketServer.h"
|
||||
|
||||
#include "DeviceRegistry.h"
|
||||
#include "OUIServer.h"
|
||||
#include "Poco/JSON/Object.h"
|
||||
#include "Poco/JSON/Parser.h"
|
||||
|
||||
namespace OpenWifi {
|
||||
class DeviceRegistry *DeviceRegistry::instance_ = nullptr;
|
||||
#include "DeviceRegistry.h"
|
||||
#include "WebSocketServer.h"
|
||||
#include "OUIServer.h"
|
||||
|
||||
DeviceRegistry::DeviceRegistry() noexcept:
|
||||
SubSystemServer("DeviceRegistry", "DevStatus", "devicestatus") {
|
||||
}
|
||||
namespace OpenWifi {
|
||||
|
||||
int DeviceRegistry::Start() {
|
||||
std::lock_guard Guard(Mutex_);
|
||||
@@ -49,7 +41,6 @@ namespace OpenWifi {
|
||||
std::lock_guard Guard(Mutex_);
|
||||
|
||||
auto Device = Devices_.find(SerialNumber);
|
||||
|
||||
if(Device != Devices_.end())
|
||||
{
|
||||
Device->second->Conn_.LastContact = time(nullptr);
|
||||
@@ -92,74 +83,61 @@ namespace OpenWifi {
|
||||
std::lock_guard Guard(Mutex_);
|
||||
|
||||
auto Device = Devices_.find(SerialNumber);
|
||||
|
||||
if(Device != Devices_.end())
|
||||
{
|
||||
Device->second->LastHealthcheck = CheckData;
|
||||
}
|
||||
}
|
||||
|
||||
GWObjects::ConnectionState * DeviceRegistry::Register(const std::string & SerialNumber, WSConnection *Ptr)
|
||||
std::shared_ptr<DeviceRegistry::ConnectionEntry> DeviceRegistry::Register(const std::string & SerialNumber, WSConnection *Ptr, uint64_t & ConnectionId )
|
||||
{
|
||||
std::lock_guard Guard(Mutex_);
|
||||
|
||||
auto Device = Devices_.find(SerialNumber);
|
||||
if( Device == Devices_.end()) {
|
||||
auto E = std::make_unique<ConnectionEntry>();
|
||||
|
||||
E->WSConn_ = Ptr;
|
||||
E->Conn_.SerialNumber = SerialNumber;
|
||||
E->Conn_.LastContact = std::time(nullptr);
|
||||
E->Conn_.Connected = true ;
|
||||
E->Conn_.UUID = 0 ;
|
||||
E->Conn_.MessageCount = 0 ;
|
||||
E->Conn_.Address = "";
|
||||
E->Conn_.TX = 0 ;
|
||||
E->Conn_.RX = 0;
|
||||
E->Conn_.VerifiedCertificate = GWObjects::CertificateValidation::NO_CERTIFICATE;
|
||||
auto R=&E->Conn_;
|
||||
Devices_[SerialNumber] = std::move(E);
|
||||
return R;
|
||||
}
|
||||
else
|
||||
{
|
||||
Device->second->WSConn_ = Ptr;
|
||||
Device->second->Conn_.Connected = true;
|
||||
Device->second->Conn_.LastContact = std::time(nullptr);
|
||||
Device->second->Conn_.VerifiedCertificate = GWObjects::CertificateValidation::NO_CERTIFICATE;
|
||||
return &Device->second->Conn_;
|
||||
}
|
||||
const auto & E = Devices_[SerialNumber] = std::make_shared<ConnectionEntry>();
|
||||
E->WSConn_ = Ptr;
|
||||
E->Conn_.SerialNumber = SerialNumber;
|
||||
E->Conn_.LastContact = std::time(nullptr);
|
||||
E->Conn_.Connected = true ;
|
||||
E->Conn_.UUID = 0 ;
|
||||
E->Conn_.MessageCount = 0 ;
|
||||
E->Conn_.Address = "";
|
||||
E->Conn_.TX = 0 ;
|
||||
E->Conn_.RX = 0;
|
||||
E->Conn_.VerifiedCertificate = GWObjects::CertificateValidation::NO_CERTIFICATE;
|
||||
ConnectionId = E->ConnectionId = ++Id_;
|
||||
return E;
|
||||
}
|
||||
|
||||
bool DeviceRegistry::Connected(const std::string & SerialNumber) {
|
||||
std::lock_guard Guard(Mutex_);
|
||||
|
||||
auto Device = Devices_.find(SerialNumber);
|
||||
|
||||
if(Device == Devices_.end())
|
||||
return false;
|
||||
|
||||
return Device->second->Conn_.Connected;
|
||||
}
|
||||
|
||||
void DeviceRegistry::UnRegister(const std::string & SerialNumber, WSConnection *Ptr) {
|
||||
void DeviceRegistry::UnRegister(const std::string & SerialNumber, uint64_t ConnectionId) {
|
||||
std::lock_guard Guard(Mutex_);
|
||||
|
||||
auto Device = Devices_.find(SerialNumber);
|
||||
|
||||
if( Device != Devices_.end() && Device->second->WSConn_==Ptr) {
|
||||
Device->second->Conn_.Address = "";
|
||||
Device->second->WSConn_ = nullptr;
|
||||
Device->second->Conn_.Connected = false;
|
||||
Device->second->Conn_.VerifiedCertificate = GWObjects::NO_CERTIFICATE;
|
||||
}
|
||||
}
|
||||
auto It = Devices_.find(SerialNumber);
|
||||
if(It!=Devices_.end()) {
|
||||
if(It->second->ConnectionId == ConnectionId)
|
||||
Devices_.erase(SerialNumber);
|
||||
}
|
||||
}
|
||||
|
||||
bool DeviceRegistry::SendFrame(const std::string & SerialNumber, const std::string & Payload) {
|
||||
std::lock_guard Guard(Mutex_);
|
||||
auto Device = Devices_.find(SerialNumber);
|
||||
if(Device!=Devices_.end() && Device->second->WSConn_!= nullptr) {
|
||||
return Device->second->WSConn_->Send(Payload);
|
||||
try {
|
||||
return Device->second->WSConn_->Send(Payload);
|
||||
} catch (...) {
|
||||
Logger_.debug(Poco::format("Could not send data to device '%s'", SerialNumber));
|
||||
Device->second->Conn_.Address = "";
|
||||
Device->second->WSConn_ = nullptr;
|
||||
Device->second->Conn_.Connected = false;
|
||||
Device->second->Conn_.VerifiedCertificate = GWObjects::NO_CERTIFICATE;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -6,13 +6,12 @@
|
||||
// Arilia Wireless Inc.
|
||||
//
|
||||
|
||||
#ifndef UCENTRAL_UDEVICEREGISTRY_H
|
||||
#define UCENTRAL_UDEVICEREGISTRY_H
|
||||
#pragma once
|
||||
|
||||
#include "Poco/JSON/Object.h"
|
||||
|
||||
#include "RESTAPI_GWobjects.h"
|
||||
#include "SubSystemServer.h"
|
||||
#include "RESTObjects//RESTAPI_GWobjects.h"
|
||||
#include "framework/MicroService.h"
|
||||
|
||||
// class uCentral::WebSocket::WSConnection;
|
||||
|
||||
@@ -26,12 +25,11 @@ namespace OpenWifi {
|
||||
GWObjects::ConnectionState Conn_;
|
||||
std::string LastStats;
|
||||
GWObjects::HealthCheck LastHealthcheck;
|
||||
uint64_t ConnectionId=0;
|
||||
};
|
||||
|
||||
static DeviceRegistry *instance() {
|
||||
if (instance_ == nullptr) {
|
||||
instance_ = new DeviceRegistry;
|
||||
}
|
||||
static DeviceRegistry *instance_ = new DeviceRegistry;
|
||||
return instance_;
|
||||
}
|
||||
|
||||
@@ -43,24 +41,24 @@ namespace OpenWifi {
|
||||
void SetState(const std::string & SerialNumber, GWObjects::ConnectionState & State);
|
||||
bool GetHealthcheck(const std::string &SerialNumber, GWObjects::HealthCheck & CheckData);
|
||||
void SetHealthcheck(const std::string &SerialNumber, const GWObjects::HealthCheck &H);
|
||||
GWObjects::ConnectionState * Register(const std::string & SerialNumber, WSConnection *);
|
||||
void UnRegister(const std::string & SerialNumber, WSConnection *);
|
||||
std::shared_ptr<ConnectionEntry> Register(const std::string & SerialNumber, WSConnection *, uint64_t & ConnectionId);
|
||||
void UnRegister(const std::string & SerialNumber, uint64_t ConnectionId);
|
||||
bool SendCommand(GWObjects::CommandDetails & Command);
|
||||
bool Connected(const std::string & SerialNumber);
|
||||
bool SendFrame(const std::string & SerialNumber, const std::string & Payload);
|
||||
void SetPendingUUID(const std::string & SerialNumber, uint64_t PendingUUID);
|
||||
|
||||
bool AnalyzeRegistry(GWObjects::Dashboard &D);
|
||||
|
||||
private:
|
||||
static DeviceRegistry *instance_;
|
||||
std::map<std::string,std::unique_ptr<ConnectionEntry>> Devices_;
|
||||
inline static std::atomic_uint64_t Id_=1;
|
||||
std::map<std::string,std::shared_ptr<ConnectionEntry>> Devices_;
|
||||
|
||||
DeviceRegistry() noexcept;
|
||||
DeviceRegistry() noexcept:
|
||||
SubSystemServer("DeviceRegistry", "DevStatus", "devicestatus") {
|
||||
}
|
||||
};
|
||||
|
||||
inline DeviceRegistry * DeviceRegistry() { return DeviceRegistry::instance(); }
|
||||
|
||||
} // namespace
|
||||
|
||||
#endif //UCENTRAL_UDEVICEREGISTRY_H
|
||||
|
||||
@@ -10,10 +10,6 @@
|
||||
#include <fstream>
|
||||
#include <cstdio>
|
||||
|
||||
#include "Daemon.h"
|
||||
#include "FileUploader.h"
|
||||
#include "StorageService.h"
|
||||
|
||||
#include "Poco/Net/HTTPServerParams.h"
|
||||
#include "Poco/Net/HTTPServerResponse.h"
|
||||
#include "Poco/DynamicAny.h"
|
||||
@@ -24,17 +20,18 @@
|
||||
#include "Poco/StreamCopier.h"
|
||||
#include "Poco/Exception.h"
|
||||
|
||||
#include "Utils.h"
|
||||
#include "FileUploader.h"
|
||||
#include "StorageService.h"
|
||||
#include "framework/MicroService.h"
|
||||
|
||||
namespace OpenWifi {
|
||||
class FileUploader *FileUploader::instance_ = nullptr;
|
||||
|
||||
static const std::string URI_BASE{"/v1/upload/"};
|
||||
|
||||
int FileUploader::Start() {
|
||||
Logger_.notice("Starting.");
|
||||
|
||||
Poco::File UploadsDir(Daemon()->ConfigPath("openwifi.fileuploader.path","/tmp"));
|
||||
Poco::File UploadsDir(MicroService::instance().ConfigPath("openwifi.fileuploader.path","/tmp"));
|
||||
Path_ = UploadsDir.path();
|
||||
if(!UploadsDir.exists()) {
|
||||
try {
|
||||
@@ -62,7 +59,7 @@ namespace OpenWifi {
|
||||
Params->setMaxQueued(100);
|
||||
|
||||
if(FullName_.empty()) {
|
||||
std::string TmpName = Daemon()->ConfigGetString("openwifi.fileuploader.uri","");
|
||||
std::string TmpName = MicroService::instance().ConfigGetString("openwifi.fileuploader.uri","");
|
||||
if(TmpName.empty()) {
|
||||
FullName_ =
|
||||
"https://" + Svr.Name() + ":" + std::to_string(Svr.Port()) + URI_BASE;
|
||||
@@ -77,13 +74,13 @@ namespace OpenWifi {
|
||||
Servers_.push_back(std::move(NewServer));
|
||||
}
|
||||
|
||||
MaxSize_ = 1000 * Daemon()->ConfigGetInt("openwifi.fileuploader.maxsize", 10000);
|
||||
MaxSize_ = 1000 * MicroService::instance().ConfigGetInt("openwifi.fileuploader.maxsize", 10000);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void FileUploader::reinitialize(Poco::Util::Application &self) {
|
||||
Daemon()->LoadConfigurationFile();
|
||||
MicroService::instance().LoadConfigurationFile();
|
||||
Logger_.information("Reinitializing.");
|
||||
Stop();
|
||||
Start();
|
||||
@@ -205,12 +202,12 @@ namespace OpenWifi {
|
||||
if (partHandler.Good()) {
|
||||
Answer.set("filename", UUID_);
|
||||
Answer.set("error", 0);
|
||||
Storage()->AttachFileToCommand(UUID_);
|
||||
StorageService()->AttachFileToCommand(UUID_);
|
||||
} else {
|
||||
Answer.set("filename", UUID_);
|
||||
Answer.set("error", 13);
|
||||
Answer.set("errorText", partHandler.Error() );
|
||||
Storage()->CancelWaitFile(UUID_, partHandler.Error() );
|
||||
StorageService()->CancelWaitFile(UUID_, partHandler.Error() );
|
||||
}
|
||||
std::ostream &ResponseStream = Response.send();
|
||||
Poco::JSON::Stringifier::stringify(Answer, ResponseStream);
|
||||
|
||||
@@ -9,13 +9,12 @@
|
||||
#ifndef UCENTRAL_UFILEUPLOADER_H
|
||||
#define UCENTRAL_UFILEUPLOADER_H
|
||||
|
||||
#include "SubSystemServer.h"
|
||||
|
||||
#include "Poco/Net/HTTPServer.h"
|
||||
#include "Poco/Net/HTTPRequestHandler.h"
|
||||
#include "Poco/Net/HTTPRequestHandlerFactory.h"
|
||||
#include "Poco/Net/HTTPServer.h"
|
||||
#include "Poco/Net/HTTPServerRequest.h"
|
||||
#include "RESTAPI_handler.h"
|
||||
|
||||
#include "framework/MicroService.h"
|
||||
|
||||
namespace OpenWifi {
|
||||
|
||||
@@ -31,16 +30,13 @@ namespace OpenWifi {
|
||||
const std::string & Path() { return Path_; };
|
||||
|
||||
static FileUploader *instance() {
|
||||
if (instance_ == nullptr) {
|
||||
instance_ = new FileUploader;
|
||||
}
|
||||
return instance_;
|
||||
static FileUploader * instance_ = new FileUploader;
|
||||
return instance_;
|
||||
}
|
||||
|
||||
[[nodiscard]] inline uint64_t MaxSize() const { return MaxSize_; }
|
||||
|
||||
private:
|
||||
static FileUploader *instance_;
|
||||
std::vector<std::unique_ptr<Poco::Net::HTTPServer>> Servers_;
|
||||
Poco::ThreadPool Pool_;
|
||||
std::string FullName_;
|
||||
|
||||
@@ -1,221 +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 <thread>
|
||||
|
||||
#include "KafkaManager.h"
|
||||
|
||||
#include "Daemon.h"
|
||||
#include "Utils.h"
|
||||
|
||||
namespace OpenWifi {
|
||||
|
||||
class KafkaManager *KafkaManager::instance_ = nullptr;
|
||||
|
||||
KafkaManager::KafkaManager() noexcept:
|
||||
SubSystemServer("KafkaManager", "KAFKA-SVR", "openwifi.kafka")
|
||||
{
|
||||
}
|
||||
|
||||
void KafkaManager::initialize(Poco::Util::Application & self) {
|
||||
SubSystemServer::initialize(self);
|
||||
KafkaEnabled_ = Daemon()->ConfigGetBool("openwifi.kafka.enable",false);
|
||||
}
|
||||
|
||||
#ifdef SMALL_BUILD
|
||||
|
||||
int KafkaManager::Start() {
|
||||
return 0;
|
||||
}
|
||||
void KafkaManager::Stop() {
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
int KafkaManager::Start() {
|
||||
if(!KafkaEnabled_)
|
||||
return 0;
|
||||
ProducerThr_ = std::make_unique<std::thread>([this]() { this->ProducerThr(); });
|
||||
ConsumerThr_ = std::make_unique<std::thread>([this]() { this->ConsumerThr(); });
|
||||
return 0;
|
||||
}
|
||||
|
||||
void KafkaManager::Stop() {
|
||||
if(KafkaEnabled_) {
|
||||
ProducerRunning_ = ConsumerRunning_ = false;
|
||||
ProducerThr_->join();
|
||||
ConsumerThr_->join();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void KafkaManager::ProducerThr() {
|
||||
cppkafka::Configuration Config({
|
||||
{ "client.id", Daemon()->ConfigGetString("openwifi.kafka.client.id") },
|
||||
{ "metadata.broker.list", Daemon()->ConfigGetString("openwifi.kafka.brokerlist") }
|
||||
});
|
||||
SystemInfoWrapper_ = R"lit({ "system" : { "id" : )lit" +
|
||||
std::to_string(Daemon()->ID()) +
|
||||
R"lit( , "host" : ")lit" + Daemon()->PrivateEndPoint() +
|
||||
R"lit(" } , "payload" : )lit" ;
|
||||
cppkafka::Producer Producer(Config);
|
||||
ProducerRunning_ = true;
|
||||
while(ProducerRunning_) {
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(200));
|
||||
try
|
||||
{
|
||||
std::lock_guard G(ProducerMutex_);
|
||||
auto Num=0;
|
||||
while (!Queue_.empty()) {
|
||||
const auto M = Queue_.front();
|
||||
Producer.produce(
|
||||
cppkafka::MessageBuilder(M.Topic).key(M.Key).payload(M.PayLoad));
|
||||
Queue_.pop();
|
||||
Num++;
|
||||
}
|
||||
if(Num)
|
||||
Producer.flush();
|
||||
} catch (const cppkafka::HandleException &E ) {
|
||||
Logger_.warning(Poco::format("Caught a Kafka exception (producer): %s",std::string{E.what()}));
|
||||
} catch (const Poco::Exception &E) {
|
||||
Logger_.log(E);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void KafkaManager::PartitionAssignment(const cppkafka::TopicPartitionList& partitions) {
|
||||
Logger_.information(Poco::format("Partition assigned: %Lu...",(uint64_t )partitions.front().get_partition()));
|
||||
}
|
||||
void KafkaManager::PartitionRevocation(const cppkafka::TopicPartitionList& partitions) {
|
||||
Logger_.information(Poco::format("Partition revocation: %Lu...",(uint64_t )partitions.front().get_partition()));
|
||||
}
|
||||
|
||||
void KafkaManager::ConsumerThr() {
|
||||
cppkafka::Configuration Config({
|
||||
{ "client.id", Daemon()->ConfigGetString("openwifi.kafka.client.id") },
|
||||
{ "metadata.broker.list", Daemon()->ConfigGetString("openwifi.kafka.brokerlist") },
|
||||
{ "group.id", Daemon()->ConfigGetString("openwifi.kafka.group.id") },
|
||||
{ "enable.auto.commit", Daemon()->ConfigGetBool("openwifi.kafka.auto.commit",false) },
|
||||
{ "auto.offset.reset", "latest" } ,
|
||||
{ "enable.partition.eof", false }
|
||||
});
|
||||
|
||||
cppkafka::TopicConfiguration topic_config = {
|
||||
{ "auto.offset.reset", "smallest" }
|
||||
};
|
||||
|
||||
// Now configure it to be the default topic config
|
||||
Config.set_default_topic_configuration(topic_config);
|
||||
|
||||
cppkafka::Consumer Consumer(Config);
|
||||
Consumer.set_assignment_callback([this](cppkafka::TopicPartitionList& partitions) {
|
||||
if(!partitions.empty()) {
|
||||
Logger_.information(Poco::format("Partition assigned: %Lu...",
|
||||
(uint64_t)partitions.front().get_partition()));
|
||||
}
|
||||
});
|
||||
Consumer.set_revocation_callback([this](const cppkafka::TopicPartitionList& partitions) {
|
||||
if(!partitions.empty()) {
|
||||
Logger_.information(Poco::format("Partition revocation: %Lu...",
|
||||
(uint64_t)partitions.front().get_partition()));
|
||||
}
|
||||
});
|
||||
|
||||
bool AutoCommit = Daemon()->ConfigGetBool("openwifi.kafka.auto.commit",false);
|
||||
auto BatchSize = Daemon()->ConfigGetInt("openwifi.kafka.consumer.batchsize",20);
|
||||
|
||||
Types::StringVec Topics;
|
||||
for(const auto &i:Notifiers_)
|
||||
Topics.push_back(i.first);
|
||||
|
||||
Consumer.subscribe(Topics);
|
||||
|
||||
ConsumerRunning_ = true;
|
||||
while(ConsumerRunning_) {
|
||||
try {
|
||||
std::vector<cppkafka::Message> MsgVec = Consumer.poll_batch(BatchSize, std::chrono::milliseconds(200));
|
||||
for(auto const &Msg:MsgVec) {
|
||||
if (!Msg)
|
||||
continue;
|
||||
if (Msg.get_error()) {
|
||||
if (!Msg.is_eof()) {
|
||||
Logger_.error(Poco::format("Error: %s", Msg.get_error().to_string()));
|
||||
}if(!AutoCommit)
|
||||
Consumer.async_commit(Msg);
|
||||
continue;
|
||||
}
|
||||
std::lock_guard G(ConsumerMutex_);
|
||||
auto It = Notifiers_.find(Msg.get_topic());
|
||||
if (It != Notifiers_.end()) {
|
||||
Types::TopicNotifyFunctionList &FL = It->second;
|
||||
std::string Key{Msg.get_key()};
|
||||
std::string Payload{Msg.get_payload()};
|
||||
for (auto &F : FL) {
|
||||
std::thread T(F.first, Key, Payload);
|
||||
T.detach();
|
||||
}
|
||||
}
|
||||
if (!AutoCommit)
|
||||
Consumer.async_commit(Msg);
|
||||
}
|
||||
} catch (const cppkafka::HandleException &E) {
|
||||
Logger_.warning(Poco::format("Caught a Kafka exception (consumer): %s",std::string{E.what()}));
|
||||
} catch (const Poco::Exception &E) {
|
||||
Logger_.log(E);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::string KafkaManager::WrapSystemId(const std::string & PayLoad) {
|
||||
return std::move( SystemInfoWrapper_ + PayLoad + "}");
|
||||
}
|
||||
|
||||
void KafkaManager::PostMessage(const std::string &topic, const std::string & key, const std::string &PayLoad, bool WrapMessage ) {
|
||||
if(KafkaEnabled_) {
|
||||
std::lock_guard G(Mutex_);
|
||||
KMessage M{
|
||||
.Topic = topic,
|
||||
.Key = key,
|
||||
.PayLoad = WrapMessage ? WrapSystemId(PayLoad) : PayLoad };
|
||||
Queue_.push(M);
|
||||
}
|
||||
}
|
||||
|
||||
int KafkaManager::RegisterTopicWatcher(const std::string &Topic, Types::TopicNotifyFunction &F) {
|
||||
if(KafkaEnabled_) {
|
||||
std::lock_guard G(Mutex_);
|
||||
auto It = Notifiers_.find(Topic);
|
||||
if(It == Notifiers_.end()) {
|
||||
Types::TopicNotifyFunctionList L;
|
||||
L.emplace(L.end(),std::make_pair(F,FunctionId_));
|
||||
Notifiers_[Topic] = std::move(L);
|
||||
} else {
|
||||
It->second.emplace(It->second.end(),std::make_pair(F,FunctionId_));
|
||||
}
|
||||
return FunctionId_++;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void KafkaManager::UnregisterTopicWatcher(const std::string &Topic, int Id) {
|
||||
if(KafkaEnabled_) {
|
||||
std::lock_guard G(Mutex_);
|
||||
auto It = Notifiers_.find(Topic);
|
||||
if(It != Notifiers_.end()) {
|
||||
Types::TopicNotifyFunctionList & L = It->second;
|
||||
for(auto it=L.begin(); it!=L.end(); it++)
|
||||
if(it->second == Id) {
|
||||
L.erase(it);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
} // namespace
|
||||
@@ -1,74 +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_KAFKAMANAGER_H
|
||||
#define UCENTRALGW_KAFKAMANAGER_H
|
||||
|
||||
#include <queue>
|
||||
#include <thread>
|
||||
|
||||
#include "SubSystemServer.h"
|
||||
#include "OpenWifiTypes.h"
|
||||
|
||||
#include "cppkafka/cppkafka.h"
|
||||
|
||||
namespace OpenWifi {
|
||||
|
||||
class KafkaManager : public SubSystemServer {
|
||||
public:
|
||||
|
||||
struct KMessage {
|
||||
std::string Topic,
|
||||
Key,
|
||||
PayLoad;
|
||||
};
|
||||
|
||||
void initialize(Poco::Util::Application & self) override;
|
||||
static KafkaManager *instance() {
|
||||
if(instance_== nullptr)
|
||||
instance_ = new KafkaManager;
|
||||
return instance_;
|
||||
}
|
||||
|
||||
void ProducerThr();
|
||||
void ConsumerThr();
|
||||
|
||||
int Start() override;
|
||||
void Stop() override;
|
||||
|
||||
void PostMessage(const std::string &topic, const std::string & key, const std::string &payload, bool WrapMessage = true);
|
||||
[[nodiscard]] std::string WrapSystemId(const std::string & PayLoad);
|
||||
[[nodiscard]] bool Enabled() { return KafkaEnabled_; }
|
||||
int RegisterTopicWatcher(const std::string &Topic, Types::TopicNotifyFunction & F);
|
||||
void UnregisterTopicWatcher(const std::string &Topic, int FunctionId);
|
||||
void WakeUp();
|
||||
void PartitionAssignment(const cppkafka::TopicPartitionList& partitions);
|
||||
void PartitionRevocation(const cppkafka::TopicPartitionList& partitions);
|
||||
|
||||
private:
|
||||
static KafkaManager *instance_;
|
||||
std::mutex ProducerMutex_;
|
||||
std::mutex ConsumerMutex_;
|
||||
bool KafkaEnabled_ = false;
|
||||
std::atomic_bool ProducerRunning_ = false;
|
||||
std::atomic_bool ConsumerRunning_ = false;
|
||||
std::queue<KMessage> Queue_;
|
||||
std::string SystemInfoWrapper_;
|
||||
std::unique_ptr<std::thread> ConsumerThr_;
|
||||
std::unique_ptr<std::thread> ProducerThr_;
|
||||
int FunctionId_=1;
|
||||
Types::NotifyTable Notifiers_;
|
||||
std::unique_ptr<cppkafka::Configuration> Config_;
|
||||
|
||||
KafkaManager() noexcept;
|
||||
};
|
||||
|
||||
inline KafkaManager * KafkaManager() { return KafkaManager::instance(); }
|
||||
} // NameSpace
|
||||
|
||||
#endif // UCENTRALGW_KAFKAMANAGER_H
|
||||
@@ -1,532 +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 <cstdlib>
|
||||
#include <boost/algorithm/string.hpp>
|
||||
|
||||
#include "Poco/Util/Application.h"
|
||||
#include "Poco/Util/ServerApplication.h"
|
||||
#include "Poco/Util/Option.h"
|
||||
#include "Poco/Util/OptionSet.h"
|
||||
#include "Poco/Util/HelpFormatter.h"
|
||||
#include "Poco/Environment.h"
|
||||
#include "Poco/Net/HTTPSStreamFactory.h"
|
||||
#include "Poco/Net/HTTPStreamFactory.h"
|
||||
#include "Poco/Net/FTPSStreamFactory.h"
|
||||
#include "Poco/Net/FTPStreamFactory.h"
|
||||
#include "Poco/Path.h"
|
||||
#include "Poco/File.h"
|
||||
#include "Poco/String.h"
|
||||
#include "Poco/JSON/Object.h"
|
||||
#include "Poco/JSON/Parser.h"
|
||||
#include "Poco/JSON/Stringifier.h"
|
||||
|
||||
#include "ALBHealthCheckServer.h"
|
||||
#ifndef SMALL_BUILD
|
||||
#include "KafkaManager.h"
|
||||
#endif
|
||||
#include "Kafka_topics.h"
|
||||
|
||||
#include "MicroService.h"
|
||||
#include "Utils.h"
|
||||
|
||||
#ifndef TIP_SECURITY_SERVICE
|
||||
#include "AuthClient.h"
|
||||
#endif
|
||||
|
||||
namespace OpenWifi {
|
||||
|
||||
void MyErrorHandler::exception(const Poco::Exception & E) {
|
||||
Poco::Thread * CurrentThread = Poco::Thread::current();
|
||||
App_.logger().log(E);
|
||||
App_.logger().error(Poco::format("Exception occurred in %s",CurrentThread->getName()));
|
||||
}
|
||||
|
||||
void MyErrorHandler::exception(const std::exception & E) {
|
||||
Poco::Thread * CurrentThread = Poco::Thread::current();
|
||||
App_.logger().warning(Poco::format("std::exception on %s",CurrentThread->getName()));
|
||||
}
|
||||
|
||||
void MyErrorHandler::exception() {
|
||||
Poco::Thread * CurrentThread = Poco::Thread::current();
|
||||
App_.logger().warning(Poco::format("exception on %s",CurrentThread->getName()));
|
||||
}
|
||||
|
||||
void MicroService::Exit(int Reason) {
|
||||
std::exit(Reason);
|
||||
}
|
||||
|
||||
void MicroService::BusMessageReceived(const std::string &Key, const std::string & Message) {
|
||||
std::lock_guard G(InfraMutex_);
|
||||
try {
|
||||
Poco::JSON::Parser P;
|
||||
auto Object = P.parse(Message).extract<Poco::JSON::Object::Ptr>();
|
||||
if (Object->has(KafkaTopics::ServiceEvents::Fields::ID) &&
|
||||
Object->has(KafkaTopics::ServiceEvents::Fields::EVENT)) {
|
||||
uint64_t ID = Object->get(KafkaTopics::ServiceEvents::Fields::ID);
|
||||
auto Event = Object->get(KafkaTopics::ServiceEvents::Fields::EVENT).toString();
|
||||
if (ID != ID_) {
|
||||
if( Event==KafkaTopics::ServiceEvents::EVENT_JOIN ||
|
||||
Event==KafkaTopics::ServiceEvents::EVENT_KEEP_ALIVE ||
|
||||
Event==KafkaTopics::ServiceEvents::EVENT_LEAVE ) {
|
||||
if( Object->has(KafkaTopics::ServiceEvents::Fields::TYPE) &&
|
||||
Object->has(KafkaTopics::ServiceEvents::Fields::PUBLIC) &&
|
||||
Object->has(KafkaTopics::ServiceEvents::Fields::PRIVATE) &&
|
||||
Object->has(KafkaTopics::ServiceEvents::Fields::VRSN) &&
|
||||
Object->has(KafkaTopics::ServiceEvents::Fields::KEY)) {
|
||||
|
||||
if (Event == KafkaTopics::ServiceEvents::EVENT_KEEP_ALIVE && Services_.find(ID) != Services_.end()) {
|
||||
Services_[ID].LastUpdate = std::time(nullptr);
|
||||
} else if (Event == KafkaTopics::ServiceEvents::EVENT_LEAVE) {
|
||||
Services_.erase(ID);
|
||||
logger().information(Poco::format("Service %s ID=%Lu leaving system.",Object->get(KafkaTopics::ServiceEvents::Fields::PRIVATE).toString(),ID));
|
||||
} else if (Event == KafkaTopics::ServiceEvents::EVENT_JOIN || Event == KafkaTopics::ServiceEvents::EVENT_KEEP_ALIVE) {
|
||||
logger().information(Poco::format("Service %s ID=%Lu joining system.",Object->get(KafkaTopics::ServiceEvents::Fields::PRIVATE).toString(),ID));
|
||||
Services_[ID] = MicroServiceMeta{
|
||||
.Id = ID,
|
||||
.Type = Poco::toLower(Object->get(KafkaTopics::ServiceEvents::Fields::TYPE).toString()),
|
||||
.PrivateEndPoint = Object->get(KafkaTopics::ServiceEvents::Fields::PRIVATE).toString(),
|
||||
.PublicEndPoint = Object->get(KafkaTopics::ServiceEvents::Fields::PUBLIC).toString(),
|
||||
.AccessKey = Object->get(KafkaTopics::ServiceEvents::Fields::KEY).toString(),
|
||||
.Version = Object->get(KafkaTopics::ServiceEvents::Fields::VRSN).toString(),
|
||||
.LastUpdate = (uint64_t)std::time(nullptr)};
|
||||
for (const auto &[Id, Svc] : Services_) {
|
||||
logger().information(Poco::format("ID: %Lu Type: %s EndPoint: %s",Id,Svc.Type,Svc.PrivateEndPoint));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
logger().error(Poco::format("KAFKA-MSG: invalid event '%s', missing a field.",Event));
|
||||
}
|
||||
} else if (Event==KafkaTopics::ServiceEvents::EVENT_REMOVE_TOKEN) {
|
||||
if(Object->has(KafkaTopics::ServiceEvents::Fields::TOKEN)) {
|
||||
#ifndef TIP_SECURITY_SERVICE
|
||||
AuthClient()->RemovedCachedToken(Object->get(KafkaTopics::ServiceEvents::Fields::TOKEN).toString());
|
||||
#endif
|
||||
} else {
|
||||
logger().error(Poco::format("KAFKA-MSG: invalid event '%s', missing token",Event));
|
||||
}
|
||||
} else {
|
||||
logger().error(Poco::format("Unknown Event: %s Source: %Lu", Event, ID));
|
||||
}
|
||||
}
|
||||
} 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);
|
||||
}
|
||||
}
|
||||
|
||||
MicroServiceMetaVec MicroService::GetServices(const std::string & Type) {
|
||||
std::lock_guard G(InfraMutex_);
|
||||
|
||||
auto T = Poco::toLower(Type);
|
||||
MicroServiceMetaVec Res;
|
||||
for(const auto &[Id,ServiceRec]:Services_) {
|
||||
if(ServiceRec.Type==T)
|
||||
Res.push_back(ServiceRec);
|
||||
}
|
||||
return Res;
|
||||
}
|
||||
|
||||
MicroServiceMetaVec MicroService::GetServices() {
|
||||
std::lock_guard G(InfraMutex_);
|
||||
|
||||
MicroServiceMetaVec Res;
|
||||
for(const auto &[Id,ServiceRec]:Services_) {
|
||||
Res.push_back(ServiceRec);
|
||||
}
|
||||
return Res;
|
||||
}
|
||||
|
||||
void MicroService::LoadConfigurationFile() {
|
||||
std::string Location = Poco::Environment::get(DAEMON_CONFIG_ENV_VAR,".");
|
||||
Poco::Path ConfigFile;
|
||||
|
||||
ConfigFile = ConfigFileName_.empty() ? Location + "/" + DAEMON_PROPERTIES_FILENAME : ConfigFileName_;
|
||||
|
||||
if(!ConfigFile.isFile())
|
||||
{
|
||||
std::cerr << DAEMON_APP_NAME << ": Configuration "
|
||||
<< ConfigFile.toString() << " does not seem to exist. Please set " + DAEMON_CONFIG_ENV_VAR
|
||||
+ " env variable the path of the " + DAEMON_PROPERTIES_FILENAME + " file." << std::endl;
|
||||
std::exit(Poco::Util::Application::EXIT_CONFIG);
|
||||
}
|
||||
|
||||
loadConfiguration(ConfigFile.toString());
|
||||
}
|
||||
|
||||
void MicroService::Reload() {
|
||||
LoadConfigurationFile();
|
||||
LoadMyConfig();
|
||||
}
|
||||
|
||||
void MicroService::LoadMyConfig() {
|
||||
std::string KeyFile = ConfigPath("openwifi.service.key");
|
||||
std::string KeyFilePassword = ConfigPath("openwifi.service.key.password" , "" );
|
||||
AppKey_ = Poco::SharedPtr<Poco::Crypto::RSAKey>(new Poco::Crypto::RSAKey("", KeyFile, KeyFilePassword));
|
||||
Cipher_ = CipherFactory_.createCipher(*AppKey_);
|
||||
ID_ = Utils::GetSystemId();
|
||||
if(!DebugMode_)
|
||||
DebugMode_ = ConfigGetBool("openwifi.system.debug",false);
|
||||
MyPrivateEndPoint_ = ConfigGetString("openwifi.system.uri.private");
|
||||
MyPublicEndPoint_ = ConfigGetString("openwifi.system.uri.public");
|
||||
UIURI_ = ConfigGetString("openwifi.system.uri.ui");
|
||||
MyHash_ = CreateHash(MyPublicEndPoint_);
|
||||
}
|
||||
|
||||
void MicroService::initialize(Poco::Util::Application &self) {
|
||||
// add the default services
|
||||
SubSystems_.push_back(KafkaManager());
|
||||
SubSystems_.push_back(ALBHealthCheckServer());
|
||||
|
||||
Poco::Net::initializeSSL();
|
||||
Poco::Net::HTTPStreamFactory::registerFactory();
|
||||
Poco::Net::HTTPSStreamFactory::registerFactory();
|
||||
Poco::Net::FTPStreamFactory::registerFactory();
|
||||
Poco::Net::FTPSStreamFactory::registerFactory();
|
||||
|
||||
LoadConfigurationFile();
|
||||
|
||||
static const char * LogFilePathKey = "logging.channels.c2.path";
|
||||
|
||||
if(LogDir_.empty()) {
|
||||
std::string OriginalLogFileValue = ConfigPath(LogFilePathKey);
|
||||
config().setString(LogFilePathKey, OriginalLogFileValue);
|
||||
} else {
|
||||
config().setString(LogFilePathKey, LogDir_);
|
||||
}
|
||||
|
||||
Poco::File DataDir(ConfigPath("openwifi.system.data"));
|
||||
DataDir_ = DataDir.path();
|
||||
if(!DataDir.exists()) {
|
||||
try {
|
||||
DataDir.createDirectory();
|
||||
} catch (const Poco::Exception &E) {
|
||||
logger().log(E);
|
||||
}
|
||||
}
|
||||
|
||||
LoadMyConfig();
|
||||
|
||||
InitializeSubSystemServers();
|
||||
ServerApplication::initialize(self);
|
||||
|
||||
Types::TopicNotifyFunction F = [this](std::string s1,std::string s2) { this->BusMessageReceived(s1,s2); };
|
||||
KafkaManager()->RegisterTopicWatcher(KafkaTopics::SERVICE_EVENTS, F);
|
||||
}
|
||||
|
||||
void MicroService::uninitialize() {
|
||||
// add your own uninitialization code here
|
||||
ServerApplication::uninitialize();
|
||||
}
|
||||
|
||||
void MicroService::reinitialize(Poco::Util::Application &self) {
|
||||
ServerApplication::reinitialize(self);
|
||||
// add your own reinitialization code here
|
||||
}
|
||||
|
||||
void MicroService::defineOptions(Poco::Util::OptionSet &options) {
|
||||
ServerApplication::defineOptions(options);
|
||||
|
||||
options.addOption(
|
||||
Poco::Util::Option("help", "", "display help information on command line arguments")
|
||||
.required(false)
|
||||
.repeatable(false)
|
||||
.callback(Poco::Util::OptionCallback<MicroService>(this, &MicroService::handleHelp)));
|
||||
|
||||
options.addOption(
|
||||
Poco::Util::Option("file", "", "specify the configuration file")
|
||||
.required(false)
|
||||
.repeatable(false)
|
||||
.argument("file")
|
||||
.callback(Poco::Util::OptionCallback<MicroService>(this, &MicroService::handleConfig)));
|
||||
|
||||
options.addOption(
|
||||
Poco::Util::Option("debug", "", "to run in debug, set to true")
|
||||
.required(false)
|
||||
.repeatable(false)
|
||||
.callback(Poco::Util::OptionCallback<MicroService>(this, &MicroService::handleDebug)));
|
||||
|
||||
options.addOption(
|
||||
Poco::Util::Option("logs", "", "specify the log directory and file (i.e. dir/file.log)")
|
||||
.required(false)
|
||||
.repeatable(false)
|
||||
.argument("dir")
|
||||
.callback(Poco::Util::OptionCallback<MicroService>(this, &MicroService::handleLogs)));
|
||||
|
||||
options.addOption(
|
||||
Poco::Util::Option("version", "", "get the version and quit.")
|
||||
.required(false)
|
||||
.repeatable(false)
|
||||
.callback(Poco::Util::OptionCallback<MicroService>(this, &MicroService::handleVersion)));
|
||||
|
||||
}
|
||||
|
||||
void MicroService::handleHelp(const std::string &name, const std::string &value) {
|
||||
HelpRequested_ = true;
|
||||
displayHelp();
|
||||
stopOptionsProcessing();
|
||||
}
|
||||
|
||||
void MicroService::handleVersion(const std::string &name, const std::string &value) {
|
||||
HelpRequested_ = true;
|
||||
std::cout << Version() << std::endl;
|
||||
stopOptionsProcessing();
|
||||
}
|
||||
|
||||
void MicroService::handleDebug(const std::string &name, const std::string &value) {
|
||||
if(value == "true")
|
||||
DebugMode_ = true ;
|
||||
}
|
||||
|
||||
void MicroService::handleLogs(const std::string &name, const std::string &value) {
|
||||
LogDir_ = value;
|
||||
}
|
||||
|
||||
void MicroService::handleConfig(const std::string &name, const std::string &value) {
|
||||
ConfigFileName_ = value;
|
||||
}
|
||||
|
||||
void MicroService::displayHelp() {
|
||||
Poco::Util::HelpFormatter helpFormatter(options());
|
||||
helpFormatter.setCommand(commandName());
|
||||
helpFormatter.setUsage("OPTIONS");
|
||||
helpFormatter.setHeader("A " + DAEMON_APP_NAME + " implementation for TIP.");
|
||||
helpFormatter.format(std::cout);
|
||||
}
|
||||
|
||||
void MicroService::InitializeSubSystemServers() {
|
||||
for(auto i:SubSystems_)
|
||||
addSubsystem(i);
|
||||
}
|
||||
|
||||
void MicroService::StartSubSystemServers() {
|
||||
for(auto i:SubSystems_) {
|
||||
i->Start();
|
||||
}
|
||||
BusEventManager_.Start();
|
||||
}
|
||||
|
||||
void MicroService::StopSubSystemServers() {
|
||||
BusEventManager_.Stop();
|
||||
for(auto i=SubSystems_.rbegin(); i!=SubSystems_.rend(); ++i)
|
||||
(*i)->Stop();
|
||||
}
|
||||
|
||||
std::string MicroService::CreateUUID() {
|
||||
return UUIDGenerator_.create().toString();
|
||||
}
|
||||
|
||||
bool MicroService::SetSubsystemLogLevel(const std::string &SubSystem, const std::string &Level) {
|
||||
try {
|
||||
auto P = Poco::Logger::parseLevel(Level);
|
||||
auto Sub = Poco::toLower(SubSystem);
|
||||
|
||||
if (Sub == "all") {
|
||||
for (auto i : SubSystems_) {
|
||||
i->Logger().setLevel(P);
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
// std::cout << "Sub:" << SubSystem << " Level:" << Level << std::endl;
|
||||
for (auto i : SubSystems_) {
|
||||
if (Sub == Poco::toLower(i->Name())) {
|
||||
i->Logger().setLevel(P);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (const Poco::Exception & E) {
|
||||
std::cout << "Exception" << std::endl;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void MicroService::Reload(const std::string &Sub) {
|
||||
for (auto i : SubSystems_) {
|
||||
if (Poco::toLower(Sub) == Poco::toLower(i->Name())) {
|
||||
i->reinitialize(Poco::Util::Application::instance());
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Types::StringVec MicroService::GetSubSystems() const {
|
||||
Types::StringVec Result;
|
||||
for(auto i:SubSystems_)
|
||||
Result.push_back(Poco::toLower(i->Name()));
|
||||
return Result;
|
||||
}
|
||||
|
||||
Types::StringPairVec MicroService::GetLogLevels() {
|
||||
Types::StringPairVec Result;
|
||||
|
||||
for(auto &i:SubSystems_) {
|
||||
auto P = std::make_pair( i->Name(), Utils::LogLevelToString(i->GetLoggingLevel()));
|
||||
Result.push_back(P);
|
||||
}
|
||||
return Result;
|
||||
}
|
||||
|
||||
const Types::StringVec & MicroService::GetLogLevelNames() {
|
||||
static Types::StringVec LevelNames{"none", "fatal", "critical", "error", "warning", "notice", "information", "debug", "trace" };
|
||||
return LevelNames;
|
||||
}
|
||||
|
||||
uint64_t MicroService::ConfigGetInt(const std::string &Key,uint64_t Default) {
|
||||
return (uint64_t) config().getInt64(Key,Default);
|
||||
}
|
||||
|
||||
uint64_t MicroService::ConfigGetInt(const std::string &Key) {
|
||||
return config().getInt(Key);
|
||||
}
|
||||
|
||||
uint64_t MicroService::ConfigGetBool(const std::string &Key,bool Default) {
|
||||
return config().getBool(Key,Default);
|
||||
}
|
||||
|
||||
uint64_t MicroService::ConfigGetBool(const std::string &Key) {
|
||||
return config().getBool(Key);
|
||||
}
|
||||
|
||||
std::string MicroService::ConfigGetString(const std::string &Key,const std::string & Default) {
|
||||
return config().getString(Key, Default);
|
||||
}
|
||||
|
||||
std::string MicroService::ConfigGetString(const std::string &Key) {
|
||||
return config().getString(Key);
|
||||
}
|
||||
|
||||
std::string MicroService::ConfigPath(const std::string &Key,const std::string & Default) {
|
||||
std::string R = config().getString(Key, Default);
|
||||
return Poco::Path::expand(R);
|
||||
}
|
||||
|
||||
std::string MicroService::ConfigPath(const std::string &Key) {
|
||||
std::string R = config().getString(Key);
|
||||
return Poco::Path::expand(R);
|
||||
}
|
||||
|
||||
std::string MicroService::Encrypt(const std::string &S) {
|
||||
return Cipher_->encryptString(S, Poco::Crypto::Cipher::Cipher::ENC_BASE64);;
|
||||
}
|
||||
|
||||
std::string MicroService::Decrypt(const std::string &S) {
|
||||
return Cipher_->decryptString(S, Poco::Crypto::Cipher::Cipher::ENC_BASE64);;
|
||||
}
|
||||
|
||||
std::string MicroService::CreateHash(const std::string &S) {
|
||||
SHA2_.update(S);
|
||||
return Utils::ToHex(SHA2_.digest());
|
||||
}
|
||||
|
||||
std::string MicroService::MakeSystemEventMessage( const std::string & Type ) const {
|
||||
Poco::JSON::Object Obj;
|
||||
Obj.set(KafkaTopics::ServiceEvents::Fields::EVENT,Type);
|
||||
Obj.set(KafkaTopics::ServiceEvents::Fields::ID,ID_);
|
||||
Obj.set(KafkaTopics::ServiceEvents::Fields::TYPE,Poco::toLower(DAEMON_APP_NAME));
|
||||
Obj.set(KafkaTopics::ServiceEvents::Fields::PUBLIC,MyPublicEndPoint_);
|
||||
Obj.set(KafkaTopics::ServiceEvents::Fields::PRIVATE,MyPrivateEndPoint_);
|
||||
Obj.set(KafkaTopics::ServiceEvents::Fields::KEY,MyHash_);
|
||||
Obj.set(KafkaTopics::ServiceEvents::Fields::VRSN,Version_);
|
||||
std::stringstream ResultText;
|
||||
Poco::JSON::Stringifier::stringify(Obj, ResultText);
|
||||
return ResultText.str();
|
||||
}
|
||||
|
||||
void BusEventManager::run() {
|
||||
Running_ = true;
|
||||
auto Msg = Daemon()->MakeSystemEventMessage(KafkaTopics::ServiceEvents::EVENT_JOIN);
|
||||
KafkaManager()->PostMessage(KafkaTopics::SERVICE_EVENTS,Daemon()->PrivateEndPoint(),Msg, false);
|
||||
while(Running_) {
|
||||
Poco::Thread::trySleep((unsigned long)Daemon()->DaemonBusTimer());
|
||||
if(!Running_)
|
||||
break;
|
||||
Msg = Daemon()->MakeSystemEventMessage(KafkaTopics::ServiceEvents::EVENT_KEEP_ALIVE);
|
||||
KafkaManager()->PostMessage(KafkaTopics::SERVICE_EVENTS,Daemon()->PrivateEndPoint(),Msg, false);
|
||||
}
|
||||
Msg = Daemon()->MakeSystemEventMessage(KafkaTopics::ServiceEvents::EVENT_LEAVE);
|
||||
KafkaManager()->PostMessage(KafkaTopics::SERVICE_EVENTS,Daemon()->PrivateEndPoint(),Msg, false);
|
||||
};
|
||||
|
||||
void BusEventManager::Start() {
|
||||
if(KafkaManager()->Enabled()) {
|
||||
Thread_.start(*this);
|
||||
}
|
||||
}
|
||||
|
||||
void BusEventManager::Stop() {
|
||||
if(KafkaManager()->Enabled()) {
|
||||
Running_ = false;
|
||||
Thread_.wakeUp();
|
||||
Thread_.join();
|
||||
}
|
||||
}
|
||||
|
||||
[[nodiscard]] bool MicroService::IsValidAPIKEY(const Poco::Net::HTTPServerRequest &Request) {
|
||||
try {
|
||||
auto APIKEY = Request.get("X-API-KEY");
|
||||
return APIKEY == MyHash_;
|
||||
} catch (const Poco::Exception &E) {
|
||||
logger().log(E);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void MicroService::SavePID() {
|
||||
try {
|
||||
std::ofstream O;
|
||||
O.open(Daemon()->DataDir() + "/pidfile",std::ios::binary | std::ios::trunc);
|
||||
O << Poco::Process::id();
|
||||
O.close();
|
||||
} catch (...)
|
||||
{
|
||||
std::cout << "Could not save system ID" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
int MicroService::main(const ArgVec &args) {
|
||||
|
||||
MyErrorHandler ErrorHandler(*this);
|
||||
Poco::ErrorHandler::set(&ErrorHandler);
|
||||
|
||||
if (!HelpRequested_) {
|
||||
SavePID();
|
||||
Poco::Logger &logger = Poco::Logger::get(DAEMON_APP_NAME);
|
||||
logger.notice(Poco::format("Starting %s version %s.",DAEMON_APP_NAME, Version()));
|
||||
|
||||
if(Poco::Net::Socket::supportsIPv6())
|
||||
logger.information("System supports IPv6.");
|
||||
else
|
||||
logger.information("System does NOT support IPv6.");
|
||||
|
||||
if (config().getBool("application.runAsDaemon", false)) {
|
||||
logger.information("Starting as a daemon.");
|
||||
}
|
||||
logger.information(Poco::format("System ID set to %Lu",ID_));
|
||||
StartSubSystemServers();
|
||||
waitForTerminationRequest();
|
||||
StopSubSystemServers();
|
||||
|
||||
logger.notice(Poco::format("Stopped %s...",DAEMON_APP_NAME));
|
||||
}
|
||||
|
||||
return Application::EXIT_OK;
|
||||
}
|
||||
}
|
||||
@@ -1,184 +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_MICROSERVICE_H
|
||||
#define UCENTRALGW_MICROSERVICE_H
|
||||
|
||||
#include <array>
|
||||
#include <iostream>
|
||||
#include <cstdlib>
|
||||
#include <vector>
|
||||
#include <set>
|
||||
|
||||
#include "Poco/Util/Application.h"
|
||||
#include "Poco/Util/ServerApplication.h"
|
||||
#include "Poco/Util/Option.h"
|
||||
#include "Poco/Util/OptionSet.h"
|
||||
#include "Poco/UUIDGenerator.h"
|
||||
#include "Poco/ErrorHandler.h"
|
||||
#include "Poco/Crypto/RSAKey.h"
|
||||
#include "Poco/Crypto/CipherFactory.h"
|
||||
#include "Poco/Crypto/Cipher.h"
|
||||
#include "Poco/SHA2Engine.h"
|
||||
#include "Poco/Net/HTTPServerRequest.h"
|
||||
#include "Poco/Process.h"
|
||||
|
||||
#include "OpenWifiTypes.h"
|
||||
#include "SubSystemServer.h"
|
||||
|
||||
namespace OpenWifi {
|
||||
|
||||
static const std::string uSERVICE_SECURITY{"owsec"};
|
||||
static const std::string uSERVICE_GATEWAY{"owgw"};
|
||||
static const std::string uSERVICE_FIRMWARE{ "owfms"};
|
||||
static const std::string uSERVICE_TOPOLOGY{ "owtopo"};
|
||||
static const std::string uSERVICE_PROVISIONING{ "owprov"};
|
||||
static const std::string uSERVICE_OWLS{ "owls"};
|
||||
|
||||
class MyErrorHandler : public Poco::ErrorHandler {
|
||||
public:
|
||||
explicit MyErrorHandler(Poco::Util::Application &App) : App_(App) {}
|
||||
void exception(const Poco::Exception & E) override;
|
||||
void exception(const std::exception & E) override;
|
||||
void exception() override;
|
||||
private:
|
||||
Poco::Util::Application &App_;
|
||||
};
|
||||
|
||||
class BusEventManager : public Poco::Runnable {
|
||||
public:
|
||||
void run() override;
|
||||
void Start();
|
||||
void Stop();
|
||||
private:
|
||||
std::atomic_bool Running_ = false;
|
||||
Poco::Thread Thread_;
|
||||
};
|
||||
|
||||
struct MicroServiceMeta {
|
||||
uint64_t Id=0;
|
||||
std::string Type;
|
||||
std::string PrivateEndPoint;
|
||||
std::string PublicEndPoint;
|
||||
std::string AccessKey;
|
||||
std::string Version;
|
||||
uint64_t LastUpdate=0;
|
||||
};
|
||||
|
||||
typedef std::map<uint64_t, MicroServiceMeta> MicroServiceMetaMap;
|
||||
typedef std::vector<MicroServiceMeta> MicroServiceMetaVec;
|
||||
|
||||
class MicroService : public Poco::Util::ServerApplication {
|
||||
public:
|
||||
explicit MicroService( std::string PropFile,
|
||||
std::string RootEnv,
|
||||
std::string ConfigVar,
|
||||
std::string AppName,
|
||||
uint64_t BusTimer,
|
||||
Types::SubSystemVec Subsystems) :
|
||||
DAEMON_PROPERTIES_FILENAME(std::move(PropFile)),
|
||||
DAEMON_ROOT_ENV_VAR(std::move(RootEnv)),
|
||||
DAEMON_CONFIG_ENV_VAR(std::move(ConfigVar)),
|
||||
DAEMON_APP_NAME(std::move(AppName)),
|
||||
DAEMON_BUS_TIMER(BusTimer),
|
||||
SubSystems_(std::move(Subsystems)) {
|
||||
}
|
||||
|
||||
int main(const ArgVec &args) override;
|
||||
void initialize(Application &self) override;
|
||||
void uninitialize() override;
|
||||
void reinitialize(Application &self) override;
|
||||
void defineOptions(Poco::Util::OptionSet &options) override;
|
||||
void handleHelp(const std::string &name, const std::string &value);
|
||||
void handleVersion(const std::string &name, const std::string &value);
|
||||
void handleDebug(const std::string &name, const std::string &value);
|
||||
void handleLogs(const std::string &name, const std::string &value);
|
||||
void handleConfig(const std::string &name, const std::string &value);
|
||||
void displayHelp();
|
||||
|
||||
void InitializeSubSystemServers();
|
||||
void StartSubSystemServers();
|
||||
void StopSubSystemServers();
|
||||
void Exit(int Reason);
|
||||
bool SetSubsystemLogLevel(const std::string & SubSystem, const std::string & Level);
|
||||
[[nodiscard]] std::string Version() { return Version_; }
|
||||
[[nodiscard]] const Poco::SharedPtr<Poco::Crypto::RSAKey> & Key() { return AppKey_; }
|
||||
[[nodiscard]] inline const std::string & DataDir() { return DataDir_; }
|
||||
[[nodiscard]] std::string CreateUUID();
|
||||
[[nodiscard]] bool Debug() const { return DebugMode_; }
|
||||
[[nodiscard]] uint64_t ID() const { return ID_; }
|
||||
[[nodiscard]] Types::StringVec GetSubSystems() const;
|
||||
[[nodiscard]] Types::StringPairVec GetLogLevels() ;
|
||||
[[nodiscard]] static const Types::StringVec & GetLogLevelNames();
|
||||
[[nodiscard]] std::string ConfigGetString(const std::string &Key,const std::string & Default);
|
||||
[[nodiscard]] std::string ConfigGetString(const std::string &Key);
|
||||
[[nodiscard]] std::string ConfigPath(const std::string &Key,const std::string & Default);
|
||||
[[nodiscard]] std::string ConfigPath(const std::string &Key);
|
||||
[[nodiscard]] uint64_t ConfigGetInt(const std::string &Key,uint64_t Default);
|
||||
[[nodiscard]] uint64_t ConfigGetInt(const std::string &Key);
|
||||
[[nodiscard]] uint64_t ConfigGetBool(const std::string &Key,bool Default);
|
||||
[[nodiscard]] uint64_t ConfigGetBool(const std::string &Key);
|
||||
[[nodiscard]] std::string Encrypt(const std::string &S);
|
||||
[[nodiscard]] std::string Decrypt(const std::string &S);
|
||||
[[nodiscard]] std::string CreateHash(const std::string &S);
|
||||
[[nodiscard]] std::string Hash() const { return MyHash_; };
|
||||
[[nodiscard]] std::string ServiceType() const { return DAEMON_APP_NAME; };
|
||||
[[nodiscard]] std::string PrivateEndPoint() const { return MyPrivateEndPoint_; };
|
||||
[[nodiscard]] std::string PublicEndPoint() const { return MyPublicEndPoint_; };
|
||||
[[nodiscard]] std::string MakeSystemEventMessage( const std::string & Type ) const ;
|
||||
[[nodiscard]] const Types::SubSystemVec & GetFullSubSystems() { return SubSystems_; }
|
||||
inline uint64_t DaemonBusTimer() const { return DAEMON_BUS_TIMER; };
|
||||
|
||||
void BusMessageReceived( const std::string & Key, const std::string & Message);
|
||||
[[nodiscard]] MicroServiceMetaVec GetServices(const std::string & type);
|
||||
[[nodiscard]] MicroServiceMetaVec GetServices();
|
||||
[[nodiscard]] bool IsValidAPIKEY(const Poco::Net::HTTPServerRequest &Request);
|
||||
[[nodiscard]] const std::string & AppName() { return DAEMON_APP_NAME; }
|
||||
|
||||
static void SavePID();
|
||||
static inline uint64_t GetPID() { return Poco::Process::id(); };
|
||||
[[nodiscard]] inline const std::string GetPublicAPIEndPoint() { return MyPublicEndPoint_ + "/api/v1"; };
|
||||
[[nodiscard]] inline const std::string & GetUIURI() const { return UIURI_;};
|
||||
|
||||
void Reload(const std::string &Name); // reload a subsystem
|
||||
void Reload(); // reload the daemon itself
|
||||
void LoadMyConfig();
|
||||
|
||||
void LoadConfigurationFile();
|
||||
|
||||
private:
|
||||
bool HelpRequested_ = false;
|
||||
std::string LogDir_;
|
||||
std::string ConfigFileName_;
|
||||
Poco::UUIDGenerator UUIDGenerator_;
|
||||
uint64_t ID_ = 1;
|
||||
Poco::SharedPtr<Poco::Crypto::RSAKey> AppKey_ = nullptr;
|
||||
bool DebugMode_ = false;
|
||||
std::string DataDir_;
|
||||
Types::SubSystemVec SubSystems_;
|
||||
Poco::Crypto::CipherFactory & CipherFactory_ = Poco::Crypto::CipherFactory::defaultFactory();
|
||||
Poco::Crypto::Cipher * Cipher_ = nullptr;
|
||||
Poco::SHA2Engine SHA2_;
|
||||
MicroServiceMetaMap Services_;
|
||||
std::string MyHash_;
|
||||
std::string MyPrivateEndPoint_;
|
||||
std::string MyPublicEndPoint_;
|
||||
std::string UIURI_;
|
||||
std::string Version_{std::string(APP_VERSION) + "("+ BUILD_NUMBER + ")"};
|
||||
BusEventManager BusEventManager_;
|
||||
std::mutex InfraMutex_;
|
||||
|
||||
std::string DAEMON_PROPERTIES_FILENAME;
|
||||
std::string DAEMON_ROOT_ENV_VAR;
|
||||
std::string DAEMON_CONFIG_ENV_VAR;
|
||||
std::string DAEMON_APP_NAME;
|
||||
uint64_t DAEMON_BUS_TIMER;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // UCENTRALGW_MICROSERVICE_H
|
||||
@@ -1,819 +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 <cerrno>
|
||||
|
||||
#include "Poco/Net/IPAddress.h"
|
||||
#include "Poco/Net/SSLException.h"
|
||||
#include "Poco/Net/HTTPServerSession.h"
|
||||
#include "Poco/Net/HTTPHeaderStream.h"
|
||||
#include "Poco/Net/HTTPServerRequestImpl.h"
|
||||
#include "Poco/JSON/Array.h"
|
||||
#include "Poco/zlib.h"
|
||||
|
||||
#include "CommandManager.h"
|
||||
#include "Daemon.h"
|
||||
#include "KafkaManager.h"
|
||||
#include "Kafka_topics.h"
|
||||
#include "StorageService.h"
|
||||
#include "Utils.h"
|
||||
#include "WebSocketServer.h"
|
||||
#include "uCentralProtocol.h"
|
||||
#include "TelemetryStream.h"
|
||||
|
||||
namespace OpenWifi {
|
||||
|
||||
class WebSocketServer *WebSocketServer::instance_ = nullptr;
|
||||
|
||||
bool WebSocketServer::ValidateCertificate(const std::string & ConnectionId, const Poco::Crypto::X509Certificate & Certificate) {
|
||||
if(IsCertOk()) {
|
||||
Logger_.debug(Poco::format("CERTIFICATE(%s): issuer='%s' cn='%s'", ConnectionId, Certificate.issuerName(),Certificate.commonName()));
|
||||
if(!Certificate.issuedBy(*IssuerCert_)) {
|
||||
Logger_.debug(Poco::format("CERTIFICATE(%s): issuer mismatch. Local='%s' Incoming='%s'", ConnectionId, IssuerCert_->issuerName(), Certificate.issuerName()));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
int WebSocketServer::Start() {
|
||||
|
||||
std::cout << __LINE__ << std::endl;
|
||||
ReactorPool_.Start();
|
||||
std::cout << __LINE__ << std::endl;
|
||||
Poco::Net::Context::Params P;
|
||||
P.verificationMode = Poco::Net::Context::VERIFY_STRICT;
|
||||
P.certificateFile = Daemon()->ConfigPath("ucentral.websocket.host.0.cert");
|
||||
P.privateKeyFile = Daemon()->ConfigPath("ucentral.websocket.host.0.key");
|
||||
P.loadDefaultCAs = true ;
|
||||
P.caLocation = Daemon()->ConfigPath("ucentral.websocket.host.0.cas");
|
||||
P.verificationDepth = 9 ;
|
||||
P.cipherList = "ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH";
|
||||
P.dhUse2048Bits = true;
|
||||
|
||||
std::cout << __LINE__ << std::endl;
|
||||
Poco::Net::IPAddress Addr(Poco::Net::IPAddress::wildcard(Poco::Net::Socket::supportsIPv6() ? Poco::Net::AddressFamily::IPv6 : Poco::Net::AddressFamily::IPv4));
|
||||
std::cout << __LINE__ << std::endl;
|
||||
Poco::Net::SocketAddress SockAddr(Addr, 15002);
|
||||
std::cout << __LINE__ << std::endl;
|
||||
|
||||
auto Context = Poco::AutoPtr<Poco::Net::Context>(new Poco::Net::Context(Poco::Net::Context::TLS_SERVER_USE, P));
|
||||
std::cout << __LINE__ << std::endl;
|
||||
auto Params = new Poco::Net::HTTPServerParams;
|
||||
std::cout << __LINE__ << std::endl;
|
||||
|
||||
Params->setMaxThreads(50);
|
||||
Params->setMaxQueued(200);
|
||||
Params->setKeepAlive(true);
|
||||
|
||||
std::cout << __LINE__ << std::endl;
|
||||
auto Sock = Poco::Net::SecureServerSocket(SockAddr, 200, Context);
|
||||
std::cout << __LINE__ << std::endl;
|
||||
|
||||
auto NewServer = std::make_unique<Poco::Net::HTTPServer>(new WebSocketRequestHandlerFactory(ReactorPool_,Logger_), Pool_, Sock, Params);
|
||||
std::cout << __LINE__ << std::endl;
|
||||
NewServer->start();
|
||||
std::cout << __LINE__ << std::endl;
|
||||
WebServers_.push_back(std::move(NewServer));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void WebSocketServer::Stop() {
|
||||
Logger_.notice("Stopping reactors...");
|
||||
Logger_.information("Stopping ");
|
||||
for( const auto & svr : WebServers_ )
|
||||
svr->stop();
|
||||
ReactorPool_.Stop();
|
||||
}
|
||||
|
||||
void WSConnection::LogException(const Poco::Exception &E) {
|
||||
Logger_.information(Poco::format("EXCEPTION(%s): %s",CId_,E.displayText()));
|
||||
}
|
||||
|
||||
void WSConnection::CompleteStartup() {
|
||||
std::lock_guard Guard(Mutex_);
|
||||
try {
|
||||
Socket_ = *WS_;
|
||||
std::cout << __LINE__ << std::endl;
|
||||
|
||||
auto SS = dynamic_cast<Poco::Net::SecureStreamSocketImpl *>(WS_->impl());
|
||||
std::cout << __LINE__ << std::endl;
|
||||
SS->completeHandshake();
|
||||
std::cout << __LINE__ << std::endl;
|
||||
CId_ = Utils::FormatIPv6(SS->peerAddress().toString());
|
||||
std::cout << __LINE__ << std::endl;
|
||||
if (!SS->secure()) {
|
||||
Logger_.error(Poco::format("%s: Connection is NOT secure.", CId_));
|
||||
} else {
|
||||
Logger_.debug(Poco::format("%s: Connection is secure.", CId_));
|
||||
}
|
||||
std::cout << __LINE__ << std::endl;
|
||||
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);
|
||||
}
|
||||
std::cout << __LINE__ << std::endl;
|
||||
} else {
|
||||
Logger_.error(Poco::format("%s: No certificates available..", CId_));
|
||||
}
|
||||
std::cout << __LINE__ << std::endl;
|
||||
|
||||
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;
|
||||
Logger_.information(Poco::format("CONNECTION(%s): completed.",CId_));
|
||||
std::cout << __LINE__ << std::endl;
|
||||
return;
|
||||
} catch (const Poco::Exception &E ) {
|
||||
Logger_.error("Exception caught during device connection. Device will have to retry.");
|
||||
}
|
||||
delete this;
|
||||
}
|
||||
|
||||
WSConnection::WSConnection(Poco::SharedPtr<Poco::Net::WebSocket> WS, Poco::Net::SocketReactor& Reactor, Poco::Logger &Logger):
|
||||
WS_(WS), Reactor_(Reactor), Logger_(WebSocketServer()->Logger())
|
||||
{
|
||||
std::cout << __LINE__ << std::endl;
|
||||
|
||||
std::thread T([this](){ this->CompleteStartup();});
|
||||
std::cout << __LINE__ << std::endl;
|
||||
T.detach();
|
||||
std::cout << __LINE__ << std::endl;
|
||||
}
|
||||
|
||||
WSConnection::~WSConnection() {
|
||||
DeviceRegistry()->UnRegister(SerialNumber_,this);
|
||||
if(Registered_ && WS_)
|
||||
{
|
||||
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) {
|
||||
|
||||
|
||||
// A UUID of zero means ignore updates for that connection.
|
||||
if(UUID==0)
|
||||
return false;
|
||||
|
||||
std::string NewConfig;
|
||||
uint64_t NewConfigUUID = 0 ;
|
||||
|
||||
if (Storage()->ExistingConfiguration(SerialNumber_,UUID, NewConfig, NewConfigUUID)) {
|
||||
|
||||
// Device is already using the latest configuration.
|
||||
if(UUID == NewConfigUUID)
|
||||
return false;
|
||||
|
||||
// if the new config is already pending,
|
||||
if(NewConfigUUID == Conn_->PendingUUID)
|
||||
return false;
|
||||
|
||||
Conn_->PendingUUID = NewConfigUUID;
|
||||
|
||||
Poco::JSON::Parser Parser( new Poco::JSON::ParseHandler);
|
||||
auto ParsedConfig = Parser.parse(NewConfig).extract<Poco::JSON::Object::Ptr>();
|
||||
ParsedConfig->set(uCentralProtocol::UUID,NewConfigUUID);
|
||||
|
||||
// create the command stub...
|
||||
GWObjects::CommandDetails Cmd;
|
||||
Cmd.SerialNumber = SerialNumber_;
|
||||
Cmd.UUID = Daemon()->CreateUUID();
|
||||
Cmd.SubmittedBy = uCentralProtocol::SUBMITTED_BY_SYSTEM;
|
||||
Cmd.Status = uCentralProtocol::PENDING;
|
||||
Cmd.Command = uCentralProtocol::CONFIGURE;
|
||||
|
||||
Poco::JSON::Object Params;
|
||||
Params.set(uCentralProtocol::SERIAL, SerialNumber_);
|
||||
Params.set(uCentralProtocol::UUID, NewConfigUUID);
|
||||
Params.set(uCentralProtocol::WHEN, 0);
|
||||
Params.set(uCentralProtocol::CONFIG, ParsedConfig);
|
||||
|
||||
std::string Log = Poco::format("CFG-UPGRADE(%s):, Current ID: %Lu, newer configuration %Lu.", SerialNumber_, UUID, NewConfigUUID);
|
||||
Storage()->AddLog(SerialNumber_, Conn_->UUID, Log);
|
||||
Logger_.debug(Log);
|
||||
|
||||
uint64_t RPC_Id;
|
||||
CommandManager()->SendCommand(SerialNumber_ , Cmd.Command, Params, Cmd.UUID, RPC_Id);
|
||||
Storage()->AddCommand(SerialNumber_, Cmd, Storage::COMMAND_EXECUTED);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool WSConnection::ExtractCompressedData(const std::string & CompressedData, std::string & UnCompressedData)
|
||||
{
|
||||
std::vector<uint8_t> OB = Utils::base64decode(CompressedData);
|
||||
|
||||
unsigned long MaxSize=OB.size()*10;
|
||||
std::vector<char> UncompressedBuffer(MaxSize);
|
||||
unsigned long FinalSize = MaxSize;
|
||||
if(uncompress((Bytef *)&UncompressedBuffer[0], & FinalSize, (Bytef *)&OB[0],OB.size())==Z_OK) {
|
||||
UncompressedBuffer[FinalSize] = 0;
|
||||
UnCompressedData = &UncompressedBuffer[0];
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void WSConnection::ProcessJSONRPCResult(Poco::JSON::Object::Ptr & Doc) {
|
||||
CommandManager()->PostCommandResult(SerialNumber_, Doc);
|
||||
}
|
||||
|
||||
void WSConnection::ProcessJSONRPCEvent(Poco::JSON::Object::Ptr & Doc) {
|
||||
|
||||
auto Method = Doc->get(uCentralProtocol::METHOD).toString();
|
||||
auto EventType = uCentralProtocol::EventFromString(Method);
|
||||
if(EventType == uCentralProtocol::ET_UNKNOWN) {
|
||||
Logger_.error(Poco::format("ILLEGAL-PROTOCOL(%s): Unknown message type '%s'",Method));
|
||||
Errors_++;
|
||||
return;
|
||||
}
|
||||
|
||||
if(!Doc->isObject(uCentralProtocol::PARAMS))
|
||||
{
|
||||
Logger_.warning(Poco::format("MISSING-PARAMS(%s): params must be an object.",CId_));
|
||||
Errors_++;
|
||||
return;
|
||||
}
|
||||
|
||||
// expand params if necessary
|
||||
auto ParamsObj = Doc->get(uCentralProtocol::PARAMS).extract<Poco::JSON::Object::Ptr>();
|
||||
if(ParamsObj->has(uCentralProtocol::COMPRESS_64))
|
||||
{
|
||||
std::string UncompressedData;
|
||||
if(ExtractCompressedData(ParamsObj->get(uCentralProtocol::COMPRESS_64).toString(),UncompressedData)) {
|
||||
Logger_.debug(Poco::format("EVENT(%s): Found compressed payload expanded to '%s'.",CId_, UncompressedData));
|
||||
Poco::JSON::Parser Parser;
|
||||
ParamsObj = Parser.parse(UncompressedData).extract<Poco::JSON::Object::Ptr>();
|
||||
} else {
|
||||
Logger_.warning(Poco::format("INVALID-COMPRESSED-DATA(%s): Compressed cannot be uncompressed - content must be corrupt..",CId_));
|
||||
Errors_++;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if(!ParamsObj->has(uCentralProtocol::SERIAL))
|
||||
{
|
||||
Logger_.warning(Poco::format("MISSING-PARAMS(%s): Serial number is missing in message.",CId_));
|
||||
return;
|
||||
}
|
||||
|
||||
auto Serial = Poco::trim(Poco::toLower(ParamsObj->get(uCentralProtocol::SERIAL).toString()));
|
||||
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();
|
||||
}
|
||||
|
||||
if(Storage()->IsBlackListed(Serial)) {
|
||||
Poco::Exception E(Poco::format("BLACKLIST(%s): device is blacklisted and not allowed to connect.",Serial), EACCES);
|
||||
E.rethrow();
|
||||
}
|
||||
|
||||
if(Conn_!= nullptr)
|
||||
Conn_->LastContact = std::time(nullptr);
|
||||
|
||||
switch(EventType) {
|
||||
case uCentralProtocol::ET_CONNECT: {
|
||||
if( ParamsObj->has(uCentralProtocol::UUID) &&
|
||||
ParamsObj->has(uCentralProtocol::FIRMWARE) &&
|
||||
ParamsObj->has(uCentralProtocol::CAPABILITIES)) {
|
||||
uint64_t UUID = ParamsObj->get(uCentralProtocol::UUID);
|
||||
auto Firmware = ParamsObj->get(uCentralProtocol::FIRMWARE).toString();
|
||||
auto Capabilities = ParamsObj->get(uCentralProtocol::CAPABILITIES).toString();
|
||||
|
||||
Conn_ = DeviceRegistry()->Register(Serial, this);
|
||||
SerialNumber_ = Serial;
|
||||
Conn_->SerialNumber = Serial;
|
||||
Conn_->UUID = UUID;
|
||||
Conn_->Firmware = Firmware;
|
||||
Conn_->PendingUUID = 0;
|
||||
Conn_->LastContact = std::time(nullptr);
|
||||
Conn_->Address = Utils::FormatIPv6(WS_->peerAddress().toString());
|
||||
CId_ = SerialNumber_ + "@" + CId_ ;
|
||||
|
||||
// We need to verify the certificate if we have one
|
||||
if(!CN_.empty() && Utils::SerialNumberMatch(CN_,SerialNumber_)) {
|
||||
CertValidation_ = GWObjects::VERIFIED;
|
||||
Logger_.information(Poco::format("CONNECT(%s): Fully validated and authenticated device..", CId_));
|
||||
} else {
|
||||
if(CN_.empty())
|
||||
Logger_.information(Poco::format("CONNECT(%s): Not authenticated or validated.", CId_));
|
||||
else
|
||||
Logger_.information(Poco::format("CONNECT(%s): Authenticated but not validated. Serial='%s' CN='%s'", CId_, Serial, CN_));
|
||||
}
|
||||
Conn_->VerifiedCertificate = CertValidation_;
|
||||
|
||||
if (Daemon()->AutoProvisioning() && !Storage()->DeviceExists(SerialNumber_)) {
|
||||
Storage()->CreateDefaultDevice(SerialNumber_, Capabilities, Firmware, Compatible_);
|
||||
} else if (Storage()->DeviceExists(SerialNumber_)) {
|
||||
Storage()->UpdateDeviceCapabilities(SerialNumber_, Capabilities, Compatible_);
|
||||
if(!Firmware.empty()) {
|
||||
Storage()->SetConnectInfo(SerialNumber_, Firmware );
|
||||
}
|
||||
}
|
||||
Conn_->Compatible = Compatible_;
|
||||
|
||||
StatsProcessor_ = std::make_unique<StateProcessor>(Conn_);
|
||||
StatsProcessor_->Initialize(Serial);
|
||||
LookForUpgrade(UUID);
|
||||
|
||||
if(KafkaManager()->Enabled()) {
|
||||
Poco::JSON::Stringifier Stringify;
|
||||
std::ostringstream OS;
|
||||
Stringify.condense(ParamsObj,OS);
|
||||
KafkaManager()->PostMessage(KafkaTopics::CONNECTION, SerialNumber_, OS.str());
|
||||
}
|
||||
|
||||
} else {
|
||||
Logger_.warning(Poco::format("CONNECT(%s): Missing one of uuid, firmware, or capabilities",CId_));
|
||||
return;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case uCentralProtocol::ET_STATE: {
|
||||
if (ParamsObj->has(uCentralProtocol::UUID) && ParamsObj->has(uCentralProtocol::STATE)) {
|
||||
uint64_t UUID = ParamsObj->get(uCentralProtocol::UUID);
|
||||
auto State = ParamsObj->get(uCentralProtocol::STATE).toString();
|
||||
|
||||
std::string request_uuid;
|
||||
if (ParamsObj->has(uCentralProtocol::REQUEST_UUID))
|
||||
request_uuid = ParamsObj->get(uCentralProtocol::REQUEST_UUID).toString();
|
||||
|
||||
if (request_uuid.empty())
|
||||
Logger_.debug(Poco::format("STATE(%s): UUID=%Lu Updating.", CId_, UUID));
|
||||
else
|
||||
Logger_.debug(Poco::format("STATE(%s): UUID=%Lu Updating for CMD=%s.", CId_,
|
||||
UUID, request_uuid));
|
||||
|
||||
Conn_->UUID = UUID;
|
||||
Storage()->AddStatisticsData(Serial, UUID, State);
|
||||
DeviceRegistry()->SetStatistics(Serial, State);
|
||||
|
||||
if (!request_uuid.empty()) {
|
||||
Storage()->SetCommandResult(request_uuid, State);
|
||||
}
|
||||
|
||||
if (StatsProcessor_)
|
||||
StatsProcessor_->Add(State);
|
||||
|
||||
if(KafkaManager()->Enabled()) {
|
||||
Poco::JSON::Stringifier Stringify;
|
||||
std::ostringstream OS;
|
||||
Stringify.condense(ParamsObj,OS);
|
||||
KafkaManager()->PostMessage(KafkaTopics::STATE, SerialNumber_, OS.str());
|
||||
}
|
||||
} else {
|
||||
Logger_.warning(Poco::format(
|
||||
"STATE(%s): Invalid request. Missing serial, uuid, or state", CId_));
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case uCentralProtocol::ET_HEALTHCHECK: {
|
||||
if (ParamsObj->has(uCentralProtocol::UUID) && ParamsObj->has(uCentralProtocol::SANITY) && ParamsObj->has(uCentralProtocol::DATA)) {
|
||||
uint64_t UUID = ParamsObj->get(uCentralProtocol::UUID);
|
||||
auto Sanity = ParamsObj->get(uCentralProtocol::SANITY);
|
||||
auto CheckData = ParamsObj->get(uCentralProtocol::DATA).toString();
|
||||
if (CheckData.empty())
|
||||
CheckData = uCentralProtocol::EMPTY_JSON_DOC;
|
||||
|
||||
std::string request_uuid;
|
||||
if (ParamsObj->has(uCentralProtocol::REQUEST_UUID))
|
||||
request_uuid = ParamsObj->get(uCentralProtocol::REQUEST_UUID).toString();
|
||||
|
||||
if (request_uuid.empty())
|
||||
Logger_.debug(
|
||||
Poco::format("HEALTHCHECK(%s): UUID=%Lu Updating.", CId_, UUID));
|
||||
else
|
||||
Logger_.debug(Poco::format("HEALTHCHECK(%s): UUID=%Lu Updating for CMD=%s.",
|
||||
CId_, UUID, request_uuid));
|
||||
|
||||
Conn_->UUID = UUID;
|
||||
|
||||
GWObjects::HealthCheck Check;
|
||||
|
||||
Check.Recorded = std::time(nullptr);
|
||||
Check.UUID = UUID;
|
||||
Check.Data = CheckData;
|
||||
Check.Sanity = Sanity;
|
||||
|
||||
Storage()->AddHealthCheckData(Serial, Check);
|
||||
|
||||
if (!request_uuid.empty()) {
|
||||
Storage()->SetCommandResult(request_uuid, CheckData);
|
||||
}
|
||||
|
||||
DeviceRegistry()->SetHealthcheck(Serial, Check);
|
||||
if(KafkaManager()->Enabled()) {
|
||||
Poco::JSON::Stringifier Stringify;
|
||||
std::ostringstream OS;
|
||||
ParamsObj->set("timestamp",std::time(nullptr));
|
||||
Stringify.condense(ParamsObj,OS);
|
||||
KafkaManager()->PostMessage(KafkaTopics::HEALTHCHECK, SerialNumber_, OS.str());
|
||||
}
|
||||
} else {
|
||||
Logger_.warning(Poco::format("HEALTHCHECK(%s): Missing parameter", CId_));
|
||||
return;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case uCentralProtocol::ET_LOG: {
|
||||
if (ParamsObj->has(uCentralProtocol::LOG) && ParamsObj->has(uCentralProtocol::SEVERITY)) {
|
||||
Logger_.debug(Poco::format("LOG(%s): new entry.", CId_));
|
||||
auto Log = ParamsObj->get(uCentralProtocol::LOG).toString();
|
||||
auto Severity = ParamsObj->get(uCentralProtocol::SEVERITY);
|
||||
std::string DataStr = uCentralProtocol::EMPTY_JSON_DOC;
|
||||
if (ParamsObj->has(uCentralProtocol::DATA)) {
|
||||
auto DataObj = ParamsObj->get(uCentralProtocol::DATA);
|
||||
if (DataObj.isStruct())
|
||||
DataStr = DataObj.toString();
|
||||
}
|
||||
|
||||
GWObjects::DeviceLog DeviceLog{.Log = Log,
|
||||
.Data = DataStr,
|
||||
.Severity = Severity,
|
||||
.Recorded = (uint64_t)time(nullptr),
|
||||
.LogType = 0,
|
||||
.UUID = Conn_->UUID};
|
||||
|
||||
Storage()->AddLog(Serial, DeviceLog);
|
||||
} else {
|
||||
Logger_.warning(Poco::format("LOG(%s): Missing parameters.", CId_));
|
||||
return;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case uCentralProtocol::ET_CRASHLOG: {
|
||||
if (ParamsObj->has(uCentralProtocol::UUID) && ParamsObj->has(uCentralProtocol::LOGLINES)) {
|
||||
|
||||
Logger_.debug(Poco::format("CRASH-LOG(%s): new entry.", CId_));
|
||||
auto LogLines = ParamsObj->get(uCentralProtocol::LOGLINES);
|
||||
std::string LogText;
|
||||
if (LogLines.isArray()) {
|
||||
auto LogLinesArray = LogLines.extract<Poco::JSON::Array::Ptr>();
|
||||
for (const auto &i : *LogLinesArray)
|
||||
LogText += i.toString() + "\r\n";
|
||||
}
|
||||
|
||||
GWObjects::DeviceLog DeviceLog{
|
||||
.Log = LogText,
|
||||
.Data = "",
|
||||
.Severity = GWObjects::DeviceLog::LOG_EMERG,
|
||||
.Recorded = (uint64_t)time(nullptr),
|
||||
.LogType = 1,
|
||||
.UUID = Conn_->UUID};
|
||||
|
||||
Storage()->AddLog(Serial, DeviceLog, true);
|
||||
} else {
|
||||
Logger_.warning(Poco::format("LOG(%s): Missing parameters.", CId_));
|
||||
return;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case uCentralProtocol::ET_PING: {
|
||||
if (ParamsObj->has(uCentralProtocol::UUID)) {
|
||||
uint64_t UUID = ParamsObj->get(uCentralProtocol::UUID);
|
||||
Logger_.debug(Poco::format("PING(%s): Current config is %Lu", CId_, UUID));
|
||||
} else {
|
||||
Logger_.warning(Poco::format("PING(%s): Missing parameter.", CId_));
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case uCentralProtocol::ET_CFGPENDING: {
|
||||
if (ParamsObj->has(uCentralProtocol::UUID) && ParamsObj->has(uCentralProtocol::ACTIVE)) {
|
||||
|
||||
uint64_t UUID = ParamsObj->get(uCentralProtocol::UUID);
|
||||
uint64_t Active = ParamsObj->get(uCentralProtocol::ACTIVE);
|
||||
|
||||
Logger_.debug(Poco::format("CFG-PENDING(%s): Active: %Lu Target: %Lu", CId_,
|
||||
Active, UUID));
|
||||
} else {
|
||||
Logger_.warning(Poco::format("CFG-PENDING(%s): Missing some parameters", CId_));
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case uCentralProtocol::ET_RECOVERY: {
|
||||
if (ParamsObj->has(uCentralProtocol::SERIAL) && ParamsObj->has(uCentralProtocol::FIRMWARE) &&
|
||||
ParamsObj->has(uCentralProtocol::UUID) && ParamsObj->has(uCentralProtocol::REBOOT) &&
|
||||
ParamsObj->has(uCentralProtocol::LOGLINES)) {
|
||||
|
||||
auto LogLines = ParamsObj->get(uCentralProtocol::LOGLINES);
|
||||
std::string LogText;
|
||||
if (LogLines.isArray()) {
|
||||
auto LogLinesArray = LogLines.extract<Poco::JSON::Array::Ptr>();
|
||||
for (const auto &i : *LogLinesArray)
|
||||
LogText += i.toString() + "\r\n";
|
||||
}
|
||||
|
||||
} else {
|
||||
Logger_.error(Poco::format(
|
||||
"RECOVERY(%s): Recovery missing one of firmware, uuid, loglines, reboot",
|
||||
Serial));
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case uCentralProtocol::ET_DEVICEUPDATE: {
|
||||
if (ParamsObj->has("currentPassword")) {
|
||||
auto Password = ParamsObj->get("currentPassword").toString();
|
||||
|
||||
Storage()->SetDevicePassword(Serial, Password);
|
||||
Logger_.error(Poco::format(
|
||||
"DEVICEUPDATE(%s): Device is updating its login password.", Serial));
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case uCentralProtocol::ET_TELEMETRY: {
|
||||
std::cout << "Telemetry date..." << std::endl;
|
||||
if(ParamsObj->has("data")) {
|
||||
auto Payload = ParamsObj->get("data").toString();
|
||||
TelemetryStream()->UpdateEndPoint(SerialNumber_, Payload);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
// this will never be called but some compilers will complain if we do not have a case for
|
||||
// every single values of an enum
|
||||
case uCentralProtocol::ET_UNKNOWN: {
|
||||
Logger_.error(Poco::format("ILLEGAL-EVENT(%s): Event '%s' unknown", CId_, Method));
|
||||
Errors_++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void WSConnection::OnSocketShutdown(const Poco::AutoPtr<Poco::Net::ShutdownNotification>& pNf) {
|
||||
std::lock_guard Guard(Mutex_);
|
||||
Logger_.information(Poco::format("SOCKET-SHUTDOWN(%s): Closing.",CId_));
|
||||
delete this;
|
||||
}
|
||||
|
||||
void WSConnection::OnSocketError(const Poco::AutoPtr<Poco::Net::ErrorNotification>& pNf) {
|
||||
std::lock_guard Guard(Mutex_);
|
||||
Logger_.information(Poco::format("SOCKET-ERROR(%s): Closing.",CId_));
|
||||
delete this;
|
||||
}
|
||||
|
||||
void WSConnection::OnSocketReadable(const Poco::AutoPtr<Poco::Net::ReadableNotification>& pNf) {
|
||||
std::lock_guard Guard(Mutex_);
|
||||
try
|
||||
{
|
||||
ProcessIncomingFrame();
|
||||
}
|
||||
catch (const Poco::Exception & E)
|
||||
{
|
||||
Logger_.log(E);
|
||||
delete this;
|
||||
}
|
||||
catch (const std::exception & E) {
|
||||
std::string W = E.what();
|
||||
Logger_.information(Poco::format("std::exception caught: %s. Connection terminated with %s",W,CId_));
|
||||
delete this;
|
||||
}
|
||||
catch ( ... ) {
|
||||
Logger_.information(Poco::format("Unknown exception for %s. Connection terminated.",CId_));
|
||||
delete this;
|
||||
}
|
||||
}
|
||||
|
||||
std::string asString(Poco::Buffer<char> & buf ) {
|
||||
if(buf.sizeBytes()>0) {
|
||||
buf.append(0);
|
||||
return buf.begin();
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
void WSConnection::ProcessIncomingFrame() {
|
||||
|
||||
bool MustDisconnect=false;
|
||||
Poco::Buffer<char> IncomingFrame(0);
|
||||
|
||||
try {
|
||||
int Op,flags;
|
||||
int IncomingSize;
|
||||
IncomingSize = WS_->receiveFrame(IncomingFrame,flags);
|
||||
Op = flags & Poco::Net::WebSocket::FRAME_OP_BITMASK;
|
||||
|
||||
// std::cout << "ID:" << CId_ << " Size=" << IncomingSize << " Flags=" << flags << " Op=" << Op << std::endl;
|
||||
|
||||
if (IncomingSize == 0 && flags == 0 && Op == 0) {
|
||||
Logger_.information(Poco::format("DISCONNECT(%s): device has disconnected.", CId_));
|
||||
MustDisconnect = true;
|
||||
} else {
|
||||
switch (Op) {
|
||||
case Poco::Net::WebSocket::FRAME_OP_PING: {
|
||||
Logger_.debug(Poco::format("WS-PING(%s): received. PONG sent back.", CId_));
|
||||
WS_->sendFrame("", 0,
|
||||
(int)Poco::Net::WebSocket::FRAME_OP_PONG |
|
||||
(int)Poco::Net::WebSocket::FRAME_FLAG_FIN);
|
||||
if (KafkaManager()->Enabled() && Conn_) {
|
||||
Poco::JSON::Object PingObject;
|
||||
Poco::JSON::Object PingDetails;
|
||||
PingDetails.set(uCentralProtocol::FIRMWARE, Conn_->Firmware);
|
||||
PingDetails.set(uCentralProtocol::SERIALNUMBER, SerialNumber_);
|
||||
PingDetails.set(uCentralProtocol::COMPATIBLE, Compatible_);
|
||||
PingObject.set(uCentralProtocol::PING,PingDetails);
|
||||
Poco::JSON::Stringifier Stringify;
|
||||
std::ostringstream OS;
|
||||
Stringify.condense(PingObject, OS);
|
||||
KafkaManager()->PostMessage(KafkaTopics::CONNECTION, SerialNumber_,
|
||||
OS.str());
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case Poco::Net::WebSocket::FRAME_OP_PONG: {
|
||||
Logger_.debug(Poco::format("PONG(%s): received and ignored.",CId_));
|
||||
}
|
||||
break;
|
||||
|
||||
case Poco::Net::WebSocket::FRAME_OP_TEXT: {
|
||||
std::string IncomingMessageStr = asString(IncomingFrame);
|
||||
Logger_.debug(Poco::format("FRAME(%s): Frame received (length=%d, flags=0x%x). Msg=%s",
|
||||
CId_, IncomingSize, unsigned(flags),IncomingMessageStr));
|
||||
|
||||
Poco::JSON::Parser parser;
|
||||
auto ParsedMessage = parser.parse(IncomingMessageStr);
|
||||
auto IncomingJSON = ParsedMessage.extract<Poco::JSON::Object::Ptr>();
|
||||
|
||||
if (IncomingJSON->has(uCentralProtocol::JSONRPC)) {
|
||||
if(IncomingJSON->has(uCentralProtocol::METHOD) &&
|
||||
IncomingJSON->has(uCentralProtocol::PARAMS)) {
|
||||
ProcessJSONRPCEvent(IncomingJSON);
|
||||
} else if (IncomingJSON->has(uCentralProtocol::RESULT) &&
|
||||
IncomingJSON->has(uCentralProtocol::ID)) {
|
||||
Logger_.debug(Poco::format("RPC-RESULT(%s): payload: %s",CId_,IncomingMessageStr));
|
||||
ProcessJSONRPCResult(IncomingJSON);
|
||||
} else {
|
||||
Logger_.warning(Poco::format(
|
||||
"INVALID-PAYLOAD(%s): Payload is not JSON-RPC 2.0: %s", CId_,
|
||||
IncomingMessageStr));
|
||||
}
|
||||
} else {
|
||||
Logger_.error(Poco::format("FRAME(%s): illegal transaction header, missing 'jsonrpc'",CId_));
|
||||
Errors_++;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case Poco::Net::WebSocket::FRAME_OP_CLOSE: {
|
||||
Logger_.warning(Poco::format("CLOSE(%s): Device is closing its connection.",CId_));
|
||||
MustDisconnect = true;
|
||||
}
|
||||
break;
|
||||
|
||||
default: {
|
||||
Logger_.warning(Poco::format("UNKNOWN(%s): unknownWS Frame operation: %s",CId_, std::to_string(Op)));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (Conn_ != nullptr) {
|
||||
Conn_->RX += IncomingSize;
|
||||
Conn_->MessageCount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (const Poco::Net::ConnectionResetException & E)
|
||||
{
|
||||
std::string IncomingMessageStr = asString(IncomingFrame);
|
||||
Logger_.warning(Poco::format("%s(%s): Caught a ConnectionResetException: %s, Message: %s",
|
||||
std::string(__func__), CId_, E.displayText(),IncomingMessageStr));
|
||||
MustDisconnect= true;
|
||||
}
|
||||
catch (const Poco::JSON::JSONException & E)
|
||||
{
|
||||
std::string IncomingMessageStr = asString(IncomingFrame);
|
||||
Logger_.warning(Poco::format("%s(%s): Caught a JSONException: %s. Message: %s",
|
||||
std::string(__func__), CId_, E.displayText(), IncomingMessageStr ));
|
||||
}
|
||||
catch (const Poco::Net::WebSocketException & E)
|
||||
{
|
||||
std::string IncomingMessageStr = asString(IncomingFrame);
|
||||
Logger_.warning(Poco::format("%s(%s): Caught a websocket exception: %s. Message: %s",
|
||||
std::string(__func__), CId_, E.displayText(), IncomingMessageStr ));
|
||||
MustDisconnect = true ;
|
||||
}
|
||||
catch (const Poco::Net::SSLConnectionUnexpectedlyClosedException & E)
|
||||
{
|
||||
std::string IncomingMessageStr = asString(IncomingFrame);
|
||||
Logger_.warning(Poco::format("%s(%s): Caught a SSLConnectionUnexpectedlyClosedException: %s. Message: %s",
|
||||
std::string(__func__), CId_, E.displayText(), IncomingMessageStr ));
|
||||
MustDisconnect = true ;
|
||||
}
|
||||
catch (const Poco::Net::SSLException & E)
|
||||
{
|
||||
std::string IncomingMessageStr = asString(IncomingFrame);
|
||||
Logger_.warning(Poco::format("%s(%s): Caught a SSL exception: %s. Message: %s",
|
||||
std::string(__func__), CId_, E.displayText(), IncomingMessageStr ));
|
||||
MustDisconnect = true ;
|
||||
}
|
||||
catch (const Poco::Net::NetException & E) {
|
||||
std::string IncomingMessageStr = asString(IncomingFrame);
|
||||
Logger_.warning( Poco::format("%s(%s): Caught a NetException: %s. Message: %s",
|
||||
std::string(__func__), CId_, E.displayText(), IncomingMessageStr ));
|
||||
MustDisconnect = true ;
|
||||
}
|
||||
catch (const Poco::IOException & E) {
|
||||
std::string IncomingMessageStr = asString(IncomingFrame);
|
||||
Logger_.warning( Poco::format("%s(%s): Caught a IOException: %s. Message: %s",
|
||||
std::string(__func__), CId_, E.displayText(), IncomingMessageStr ));
|
||||
MustDisconnect = true ;
|
||||
}
|
||||
catch (const Poco::Exception &E) {
|
||||
std::string IncomingMessageStr = asString(IncomingFrame);
|
||||
Logger_.warning( Poco::format("%s(%s): Caught a more generic Poco exception: %s. Message: %s",
|
||||
std::string(__func__), CId_, E.displayText(), IncomingMessageStr ));
|
||||
MustDisconnect = true ;
|
||||
}
|
||||
catch (const std::exception & E) {
|
||||
std::string IncomingMessageStr = asString(IncomingFrame);
|
||||
Logger_.warning( Poco::format("%s(%s): Caught a std::exception: %s. Message: %s",
|
||||
std::string{__func__}, CId_, std::string{E.what()}, IncomingMessageStr) );
|
||||
MustDisconnect = true ;
|
||||
}
|
||||
|
||||
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) {
|
||||
std::lock_guard Guard(Mutex_);
|
||||
|
||||
auto BytesSent = WS_->sendFrame(Payload.c_str(),(int)Payload.size());
|
||||
if(Conn_)
|
||||
Conn_->TX += BytesSent;
|
||||
return BytesSent == Payload.size();
|
||||
}
|
||||
|
||||
} //namespace
|
||||
@@ -1,192 +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 UCENTRAL_UCENTRALWEBSOCKETSERVER_H
|
||||
#define UCENTRAL_UCENTRALWEBSOCKETSERVER_H
|
||||
|
||||
#include <mutex>
|
||||
#include <thread>
|
||||
#include <array>
|
||||
#include <ctime>
|
||||
|
||||
#include "DeviceRegistry.h"
|
||||
#include "RESTAPI_GWobjects.h"
|
||||
#include "StateProcessor.h"
|
||||
#include "SubSystemServer.h"
|
||||
|
||||
#include "Poco/AutoPtr.h"
|
||||
#include "Poco/Net/WebSocket.h"
|
||||
#include "Poco/Net/NetException.h"
|
||||
#include "Poco/JSON/Parser.h"
|
||||
#include "Poco/DynamicAny.h"
|
||||
#include "Poco/Net/SocketReactor.h"
|
||||
#include "Poco/Net/SocketNotification.h"
|
||||
#include "Poco/NObserver.h"
|
||||
#include "Poco/Net/SocketAcceptor.h"
|
||||
#include "Poco/Net/SocketNotification.h"
|
||||
#include "Poco/Net/StreamSocket.h"
|
||||
#include "Poco/Net/SecureStreamSocket.h"
|
||||
#include "Poco/Net/SecureStreamSocketImpl.h"
|
||||
#include "Poco/Net/ParallelSocketAcceptor.h"
|
||||
#include "Poco/Environment.h"
|
||||
#include "Poco/Net/HTTPRequestHandlerFactory.h"
|
||||
#include "Poco/Net/HTTPRequestHandler.h"
|
||||
#include "Poco/Net/HTTPServer.h"
|
||||
|
||||
namespace OpenWifi {
|
||||
|
||||
class ReactorPool {
|
||||
public:
|
||||
ReactorPool( unsigned int NumberOfThreads = Poco::Environment::processorCount() )
|
||||
: NumberOfThreads_(NumberOfThreads)
|
||||
{
|
||||
}
|
||||
|
||||
void Start() {
|
||||
for(auto i=0;i<NumberOfThreads_;++i) {
|
||||
auto NewReactor = std::make_unique<Poco::Net::SocketReactor>();
|
||||
auto NewThread = std::make_unique<Poco::Thread>();
|
||||
NewThread->start(*NewReactor);
|
||||
Reactors_.emplace_back( std::move(NewReactor));
|
||||
Threads_.emplace_back( std::move(NewThread));
|
||||
}
|
||||
}
|
||||
|
||||
void Stop() {
|
||||
for(auto &i:Reactors_)
|
||||
i->stop();
|
||||
for(auto &i:Threads_) {
|
||||
i->join();
|
||||
}
|
||||
}
|
||||
|
||||
Poco::Net::SocketReactor & NextReactor() {
|
||||
NextReactor_ ++;
|
||||
NextReactor_ %= NumberOfThreads_;
|
||||
return *Reactors_[NextReactor_];
|
||||
}
|
||||
|
||||
private:
|
||||
unsigned int NumberOfThreads_;
|
||||
unsigned int NextReactor_=0;
|
||||
std::vector<std::unique_ptr<Poco::Net::SocketReactor>> Reactors_;
|
||||
std::vector<std::unique_ptr<Poco::Thread>> Threads_;
|
||||
};
|
||||
|
||||
class WSConnection {
|
||||
static constexpr int BufSize = 64000;
|
||||
public:
|
||||
WSConnection(Poco::SharedPtr<Poco::Net::WebSocket> WS, Poco::Net::SocketReactor& Reactor, Poco::Logger &Logger);
|
||||
~WSConnection();
|
||||
|
||||
void ProcessJSONRPCEvent(Poco::JSON::Object::Ptr & Doc);
|
||||
void ProcessJSONRPCResult(Poco::JSON::Object::Ptr & Doc);
|
||||
void ProcessIncomingFrame();
|
||||
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 LogException(const Poco::Exception &E);
|
||||
[[nodiscard]] GWObjects::CertificateValidation CertificateValidation() const { return CertValidation_; };
|
||||
private:
|
||||
std::recursive_mutex Mutex_;
|
||||
Poco::SharedPtr<Poco::Net::WebSocket> WS_;
|
||||
Poco::Net::SocketReactor & Reactor_;
|
||||
Poco::Logger &Logger_;
|
||||
Poco::Net::StreamSocket Socket_;
|
||||
std::string SerialNumber_;
|
||||
std::string Compatible_;
|
||||
GWObjects::ConnectionState * Conn_ = nullptr;
|
||||
bool Registered_ = false ;
|
||||
std::string CId_;
|
||||
std::string CN_;
|
||||
GWObjects::CertificateValidation CertValidation_ = GWObjects::CertificateValidation::NO_CERTIFICATE;
|
||||
uint64_t Errors_=0;
|
||||
std::unique_ptr<StateProcessor> StatsProcessor_;
|
||||
|
||||
void CompleteStartup();
|
||||
};
|
||||
|
||||
class WebSocketRequestHandler : public Poco::Net::HTTPRequestHandler {
|
||||
public:
|
||||
explicit WebSocketRequestHandler(ReactorPool &Pool, Poco::Logger &Logger) :
|
||||
Pool_(Pool), Logger_(Logger) {}
|
||||
|
||||
void handleRequest(Poco::Net::HTTPServerRequest & Request, Poco::Net::HTTPServerResponse & Response) final {
|
||||
try {
|
||||
std::cout << __LINE__ << std::endl;
|
||||
auto WS = Poco::SharedPtr<Poco::Net::WebSocket>(new Poco::Net::WebSocket(Request, Response));
|
||||
std::cout << __LINE__ << std::endl;
|
||||
new WSConnection(WS, Pool_.NextReactor(), Logger_);
|
||||
std::cout << __LINE__ << std::endl;
|
||||
|
||||
} catch (const Poco::Exception &E) {
|
||||
std::cout << E.what() << " " << E.name() << " " << E.displayText() << std::endl;
|
||||
} catch (...) {
|
||||
std::cout << __LINE__ << std::endl;
|
||||
}
|
||||
}
|
||||
private:
|
||||
ReactorPool &Pool_;
|
||||
Poco::Logger &Logger_;
|
||||
};
|
||||
|
||||
|
||||
class WebSocketRequestHandlerFactory : public Poco::Net::HTTPRequestHandlerFactory {
|
||||
public:
|
||||
explicit WebSocketRequestHandlerFactory(ReactorPool & Pool, Poco::Logger & Logger) :
|
||||
Pool_(Pool),
|
||||
Logger_(Logger)
|
||||
{}
|
||||
|
||||
inline Poco::Net::HTTPRequestHandler *createRequestHandler(const Poco::Net::HTTPServerRequest & Request) final {
|
||||
std::cout << __LINE__ << std::endl;
|
||||
return new WebSocketRequestHandler(Pool_,Logger_);
|
||||
}
|
||||
|
||||
private:
|
||||
Poco::Logger & Logger_;
|
||||
ReactorPool & Pool_;
|
||||
};
|
||||
|
||||
|
||||
class WebSocketServer : public SubSystemServer {
|
||||
public:
|
||||
static WebSocketServer *instance() {
|
||||
if (instance_ == nullptr) {
|
||||
instance_ = new WebSocketServer;
|
||||
}
|
||||
return instance_;
|
||||
}
|
||||
|
||||
int Start() override;
|
||||
void Stop() override;
|
||||
bool IsCertOk() { return IssuerCert_!= nullptr; }
|
||||
const Poco::Crypto::X509Certificate & Certificate() const { return *IssuerCert_; }
|
||||
bool ValidateCertificate(const std::string & ConnectionId, const Poco::Crypto::X509Certificate & Certificate);
|
||||
|
||||
private:
|
||||
static WebSocketServer *instance_;
|
||||
std::unique_ptr<Poco::Crypto::X509Certificate> IssuerCert_;
|
||||
ReactorPool ReactorPool_;
|
||||
std::vector<std::unique_ptr<Poco::Net::HTTPServer>> WebServers_;
|
||||
Poco::ThreadPool Pool_;
|
||||
|
||||
WebSocketServer() noexcept: SubSystemServer("WebSocketServer", "WS-SVR", "nano")
|
||||
{
|
||||
std::cout << __LINE__ << std::endl;
|
||||
}
|
||||
};
|
||||
|
||||
inline WebSocketServer * WebSocketServer() { return WebSocketServer::instance(); }
|
||||
|
||||
} //namespace
|
||||
|
||||
#endif //UCENTRAL_UCENTRALWEBSOCKETSERVER_H
|
||||
@@ -6,7 +6,6 @@
|
||||
#include <vector>
|
||||
|
||||
#include "OUIServer.h"
|
||||
#include "Daemon.h"
|
||||
|
||||
#include "Poco/String.h"
|
||||
#include "Poco/StringTokenizer.h"
|
||||
@@ -15,10 +14,10 @@
|
||||
#include "Poco/URI.h"
|
||||
#include "Poco/File.h"
|
||||
|
||||
#include "Utils.h"
|
||||
#include "OUIServer.h"
|
||||
#include "framework/MicroService.h"
|
||||
|
||||
namespace OpenWifi {
|
||||
class OUIServer * OUIServer::instance_;
|
||||
|
||||
int OUIServer::Start() {
|
||||
Running_=true;
|
||||
@@ -39,7 +38,7 @@ namespace OpenWifi {
|
||||
}
|
||||
|
||||
void OUIServer::reinitialize(Poco::Util::Application &self) {
|
||||
Daemon()->LoadConfigurationFile();
|
||||
MicroService::instance().LoadConfigurationFile();
|
||||
Logger_.information("Reinitializing.");
|
||||
Stop();
|
||||
Start();
|
||||
@@ -48,7 +47,7 @@ namespace OpenWifi {
|
||||
bool OUIServer::GetFile(const std::string &FileName) {
|
||||
try {
|
||||
std::unique_ptr<std::istream> pStr(
|
||||
Poco::URIStreamOpener::defaultOpener().open(Daemon()->ConfigGetString("oui.download.uri")));
|
||||
Poco::URIStreamOpener::defaultOpener().open(MicroService::instance().ConfigGetString("oui.download.uri")));
|
||||
std::ofstream OS;
|
||||
Poco::File F(FileName);
|
||||
if(F.exists())
|
||||
@@ -104,8 +103,8 @@ namespace OpenWifi {
|
||||
Updating_ = true;
|
||||
|
||||
// fetch data from server, if not available, just use the file we already have.
|
||||
std::string LatestOUIFileName{ Daemon()->DataDir() + "/newOUIFile.txt"};
|
||||
std::string CurrentOUIFileName{ Daemon()->DataDir() + "/current_oui.txt"};
|
||||
std::string LatestOUIFileName{ MicroService::instance().DataDir() + "/newOUIFile.txt"};
|
||||
std::string CurrentOUIFileName{ MicroService::instance().DataDir() + "/current_oui.txt"};
|
||||
|
||||
OUIMap TmpOUIs;
|
||||
if(GetFile(LatestOUIFileName) && ProcessFile(LatestOUIFileName, TmpOUIs)) {
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
#ifndef UCENTRALGW_OUISERVER_H
|
||||
#define UCENTRALGW_OUISERVER_H
|
||||
|
||||
#include "SubSystemServer.h"
|
||||
#include "framework/MicroService.h"
|
||||
|
||||
namespace OpenWifi {
|
||||
|
||||
@@ -15,9 +15,7 @@ namespace OpenWifi {
|
||||
typedef std::map<uint64_t,std::string> OUIMap;
|
||||
|
||||
static OUIServer *instance() {
|
||||
if (instance_ == nullptr) {
|
||||
instance_ = new OUIServer;
|
||||
}
|
||||
static OUIServer *instance_ = new OUIServer;
|
||||
return instance_;
|
||||
}
|
||||
|
||||
@@ -33,7 +31,6 @@ namespace OpenWifi {
|
||||
[[nodiscard]] bool ProcessFile(const std::string &FileName, OUIMap &Map);
|
||||
|
||||
private:
|
||||
static OUIServer * instance_;
|
||||
uint64_t LastUpdate_ = 0 ;
|
||||
bool ValidFile_=false;
|
||||
OUIMap OUIs_;
|
||||
|
||||
@@ -1,71 +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 <iostream>
|
||||
|
||||
#include "OpenAPIRequest.h"
|
||||
|
||||
#include "Poco/Net/HTTPSClientSession.h"
|
||||
#include <Poco/Net/HTTPRequest.h>
|
||||
#include <Poco/Net/HTTPResponse.h>
|
||||
#include <Poco/JSON/Parser.h>
|
||||
#include <Poco/URI.h>
|
||||
#include <Poco/Exception.h>
|
||||
#include "Utils.h"
|
||||
#include "Daemon.h"
|
||||
|
||||
namespace OpenWifi {
|
||||
|
||||
OpenAPIRequestGet::OpenAPIRequestGet( std::string ServiceType,
|
||||
std::string EndPoint,
|
||||
Types::StringPairVec & QueryData,
|
||||
uint64_t msTimeout):
|
||||
Type_(std::move(ServiceType)),
|
||||
EndPoint_(std::move(EndPoint)),
|
||||
QueryData_(QueryData),
|
||||
msTimeout_(msTimeout) {
|
||||
|
||||
}
|
||||
|
||||
int OpenAPIRequestGet::Do(Poco::JSON::Object::Ptr &ResponseObject) {
|
||||
try {
|
||||
auto Services = Daemon()->GetServices(Type_);
|
||||
for(auto const &Svc:Services) {
|
||||
Poco::URI URI(Svc.PrivateEndPoint);
|
||||
Poco::Net::HTTPSClientSession Session(URI.getHost(), URI.getPort());
|
||||
|
||||
URI.setPath(EndPoint_);
|
||||
for (const auto &qp : QueryData_)
|
||||
URI.addQueryParameter(qp.first, qp.second);
|
||||
|
||||
std::string Path(URI.getPathAndQuery());
|
||||
Session.setTimeout(Poco::Timespan(msTimeout_/1000, msTimeout_ % 1000));
|
||||
|
||||
Poco::Net::HTTPRequest Request(Poco::Net::HTTPRequest::HTTP_GET,
|
||||
Path,
|
||||
Poco::Net::HTTPMessage::HTTP_1_1);
|
||||
Request.add("X-API-KEY", Svc.AccessKey);
|
||||
Session.sendRequest(Request);
|
||||
|
||||
Poco::Net::HTTPResponse Response;
|
||||
std::istream &is = Session.receiveResponse(Response);
|
||||
if(Response.getStatus()==Poco::Net::HTTPResponse::HTTP_OK) {
|
||||
Poco::JSON::Parser P;
|
||||
ResponseObject = P.parse(is).extract<Poco::JSON::Object::Ptr>();
|
||||
}
|
||||
return Response.getStatus();
|
||||
}
|
||||
}
|
||||
catch (const Poco::Exception &E)
|
||||
{
|
||||
std::cerr << E.displayText() << std::endl;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
@@ -1,33 +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_OPENAPIREQUEST_H
|
||||
#define UCENTRALGW_OPENAPIREQUEST_H
|
||||
|
||||
#include "Poco/JSON/Object.h"
|
||||
|
||||
#include "OpenWifiTypes.h"
|
||||
|
||||
namespace OpenWifi {
|
||||
|
||||
class OpenAPIRequestGet {
|
||||
public:
|
||||
explicit OpenAPIRequestGet( std::string Type,
|
||||
std::string EndPoint,
|
||||
Types::StringPairVec & QueryData,
|
||||
uint64_t msTimeout);
|
||||
int Do(Poco::JSON::Object::Ptr &ResponseObject);
|
||||
private:
|
||||
std::string Type_;
|
||||
std::string EndPoint_;
|
||||
Types::StringPairVec QueryData_;
|
||||
uint64_t msTimeout_;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // UCENTRALGW_OPENAPIREQUEST_H
|
||||
@@ -10,10 +10,10 @@
|
||||
#include <chrono>
|
||||
#include "RESTAPI_RPC.h"
|
||||
|
||||
#include "StorageService.h"
|
||||
#include "DeviceRegistry.h"
|
||||
#include "CommandManager.h"
|
||||
#include "uCentralProtocol.h"
|
||||
#include "DeviceRegistry.h"
|
||||
#include "StorageService.h"
|
||||
#include "framework/uCentral_Protocol.h"
|
||||
|
||||
namespace OpenWifi::RESTAPI_RPC {
|
||||
void SetCommandStatus(GWObjects::CommandDetails &Cmd,
|
||||
@@ -22,7 +22,7 @@ namespace OpenWifi::RESTAPI_RPC {
|
||||
RESTAPIHandler *Handler,
|
||||
OpenWifi::Storage::CommandExecutionType Status,
|
||||
Poco::Logger &Logger) {
|
||||
if (Storage()->AddCommand(Cmd.SerialNumber, Cmd, Status)) {
|
||||
if (StorageService()->AddCommand(Cmd.SerialNumber, Cmd, Status)) {
|
||||
Poco::JSON::Object RetObj;
|
||||
Cmd.to_json(RetObj);
|
||||
Handler->ReturnObject(RetObj);
|
||||
@@ -80,7 +80,7 @@ namespace OpenWifi::RESTAPI_RPC {
|
||||
}
|
||||
|
||||
// Add the completed command to the database...
|
||||
Storage()->AddCommand(Cmd.SerialNumber, Cmd,
|
||||
StorageService()->AddCommand(Cmd.SerialNumber, Cmd,
|
||||
Storage::COMMAND_COMPLETED);
|
||||
|
||||
if (ObjectToReturn) {
|
||||
@@ -15,9 +15,9 @@
|
||||
#include "Poco/File.h"
|
||||
#include "Poco/JSON/Object.h"
|
||||
|
||||
#include "RESTAPI_GWobjects.h"
|
||||
#include "RESTAPI_handler.h"
|
||||
#include "RESTObjects//RESTAPI_GWobjects.h"
|
||||
#include "StorageService.h"
|
||||
#include "framework/MicroService.h"
|
||||
|
||||
namespace OpenWifi::RESTAPI_RPC {
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
#include "RESTAPI_TelemetryWebSocket.h"
|
||||
#include "Poco/Net/WebSocket.h"
|
||||
#include "Poco/Net/NetException.h"
|
||||
#include "TelemetryStream.h"
|
||||
|
||||
namespace OpenWifi {
|
||||
@@ -5,7 +5,7 @@
|
||||
#ifndef OWGW_RESTAPI_TELEMETRYWEBSOCKET_H
|
||||
#define OWGW_RESTAPI_TELEMETRYWEBSOCKET_H
|
||||
|
||||
#include "RESTAPI_handler.h"
|
||||
#include "framework/MicroService.h"
|
||||
|
||||
namespace OpenWifi {
|
||||
class RESTAPI_TelemetryWebSocket : public RESTAPIHandler {
|
||||
120
src/RESTAPI/RESTAPI_blacklist.cpp
Normal file
120
src/RESTAPI/RESTAPI_blacklist.cpp
Normal file
@@ -0,0 +1,120 @@
|
||||
//
|
||||
// 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 <ctime>
|
||||
|
||||
#include "Poco/JSON/Parser.h"
|
||||
#include "Poco/JSON/Stringifier.h"
|
||||
#include "RESTAPI_blacklist.h"
|
||||
#include "StorageService.h"
|
||||
#include "framework/RESTAPI_errors.h"
|
||||
#include "framework/RESTAPI_protocol.h"
|
||||
|
||||
namespace OpenWifi {
|
||||
void RESTAPI_blacklist::DoDelete() {
|
||||
auto SerialNumber = GetBinding(RESTAPI::Protocol::SERIALNUMBER, "");
|
||||
|
||||
if(SerialNumber.empty()) {
|
||||
return BadRequest(RESTAPI::Errors::MissingSerialNumber);
|
||||
}
|
||||
|
||||
GWObjects::BlackListedDevice D;
|
||||
if(!StorageService()->GetBlackListDevice(SerialNumber, D)) {
|
||||
return NotFound();
|
||||
}
|
||||
|
||||
if (StorageService()->DeleteBlackListDevice(SerialNumber)) {
|
||||
return OK();
|
||||
}
|
||||
BadRequest(RESTAPI::Errors::CouldNotBeDeleted);
|
||||
}
|
||||
|
||||
void RESTAPI_blacklist::DoGet() {
|
||||
auto SerialNumber = GetBinding(RESTAPI::Protocol::SERIALNUMBER, "");
|
||||
|
||||
if(SerialNumber.empty()) {
|
||||
return BadRequest(RESTAPI::Errors::MissingSerialNumber);
|
||||
}
|
||||
|
||||
GWObjects::BlackListedDevice D;
|
||||
if(!StorageService()->GetBlackListDevice(SerialNumber, D)) {
|
||||
return NotFound();
|
||||
}
|
||||
|
||||
Poco::JSON::Object Answer;
|
||||
D.to_json(Answer);
|
||||
return ReturnObject(Answer);
|
||||
}
|
||||
|
||||
void RESTAPI_blacklist::DoPost() {
|
||||
auto Obj = ParseStream();
|
||||
|
||||
GWObjects::BlackListedDevice D;
|
||||
if(!D.from_json(Obj)) {
|
||||
return BadRequest(RESTAPI::Errors::InvalidJSONDocument);
|
||||
}
|
||||
|
||||
if(D.serialNumber.empty()) {
|
||||
return BadRequest(RESTAPI::Errors::MissingSerialNumber);
|
||||
}
|
||||
|
||||
Poco::toLowerInPlace(D.serialNumber);
|
||||
if(StorageService()->IsBlackListed(D.serialNumber)) {
|
||||
return BadRequest(RESTAPI::Errors::SerialNumberExists);
|
||||
}
|
||||
|
||||
D.author = UserInfo_.userinfo.email;
|
||||
D.created = std::time(nullptr);
|
||||
|
||||
if(StorageService()->AddBlackListDevice(D)) {
|
||||
GWObjects::BlackListedDevice CreatedDevice;
|
||||
|
||||
StorageService()->GetBlackListDevice(D.serialNumber,CreatedDevice);
|
||||
Poco::JSON::Object Answer;
|
||||
|
||||
CreatedDevice.to_json(Answer);
|
||||
return ReturnObject(Answer);
|
||||
}
|
||||
return BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
|
||||
}
|
||||
|
||||
void RESTAPI_blacklist::DoPut() {
|
||||
auto SerialNumber = Poco::toLower(GetBinding(RESTAPI::Protocol::SERIALNUMBER, ""));
|
||||
|
||||
if(SerialNumber.empty()) {
|
||||
return BadRequest(RESTAPI::Errors::MissingSerialNumber);
|
||||
}
|
||||
|
||||
auto Obj = ParseStream();
|
||||
|
||||
GWObjects::BlackListedDevice Existing;
|
||||
if(!StorageService()->GetBlackListDevice(SerialNumber, Existing)) {
|
||||
return BadRequest(RESTAPI::Errors::InvalidJSONDocument);
|
||||
}
|
||||
|
||||
GWObjects::BlackListedDevice NewDevice;
|
||||
if(!NewDevice.from_json(Obj)) {
|
||||
return BadRequest(RESTAPI::Errors::InvalidJSONDocument);
|
||||
}
|
||||
|
||||
Existing.reason = NewDevice.reason;
|
||||
Existing.author = UserInfo_.userinfo.email;
|
||||
|
||||
if(StorageService()->UpdateBlackListDevice(SerialNumber, Existing)) {
|
||||
GWObjects::BlackListedDevice CreatedDevice;
|
||||
|
||||
StorageService()->GetBlackListDevice(SerialNumber,CreatedDevice);
|
||||
Poco::JSON::Object Answer;
|
||||
|
||||
CreatedDevice.to_json(Answer);
|
||||
return ReturnObject(Answer);
|
||||
}
|
||||
return BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -9,24 +9,25 @@
|
||||
#ifndef UCENTRALGW_RESTAPI_BLACKLIST_H
|
||||
#define UCENTRALGW_RESTAPI_BLACKLIST_H
|
||||
|
||||
#include "RESTAPI_handler.h"
|
||||
#include "framework/MicroService.h"
|
||||
|
||||
namespace OpenWifi {
|
||||
class RESTAPI_BlackList : public RESTAPIHandler {
|
||||
class RESTAPI_blacklist : public RESTAPIHandler {
|
||||
public:
|
||||
RESTAPI_BlackList(const RESTAPIHandler::BindingMap &bindings, Poco::Logger &L, RESTAPI_GenericServer & Server, bool Internal)
|
||||
RESTAPI_blacklist(const RESTAPIHandler::BindingMap &bindings, Poco::Logger &L, RESTAPI_GenericServer & Server, bool Internal)
|
||||
: RESTAPIHandler(bindings, L,
|
||||
std::vector<std::string>{Poco::Net::HTTPRequest::HTTP_GET,
|
||||
Poco::Net::HTTPRequest::HTTP_POST,
|
||||
Poco::Net::HTTPRequest::HTTP_PUT,
|
||||
Poco::Net::HTTPRequest::HTTP_DELETE,
|
||||
Poco::Net::HTTPRequest::HTTP_OPTIONS},
|
||||
Server,
|
||||
Internal) {}
|
||||
static const std::list<const char *> PathName() { return std::list<const char *>{"/api/v1/blacklist"};}
|
||||
static const std::list<const char *> PathName() { return std::list<const char *>{"/api/v1/blacklist/{serialNumber}"};}
|
||||
void DoGet() final;
|
||||
void DoDelete() final;
|
||||
void DoPost() final;
|
||||
void DoPut() final {};
|
||||
void DoPut() final;
|
||||
};
|
||||
}
|
||||
|
||||
28
src/RESTAPI/RESTAPI_blacklist_list.cpp
Normal file
28
src/RESTAPI/RESTAPI_blacklist_list.cpp
Normal file
@@ -0,0 +1,28 @@
|
||||
//
|
||||
// Created by stephane bourque on 2021-10-14.
|
||||
//
|
||||
|
||||
#include "RESTAPI_blacklist_list.h"
|
||||
#include "Poco/JSON/Parser.h"
|
||||
#include "Poco/JSON/Stringifier.h"
|
||||
#include "StorageService.h"
|
||||
|
||||
namespace OpenWifi {
|
||||
void RESTAPI_blacklist_list::DoGet() {
|
||||
|
||||
std::vector<GWObjects::BlackListedDevice> Devices;
|
||||
|
||||
Poco::JSON::Array Arr;
|
||||
Poco::JSON::Object Answer;
|
||||
|
||||
if(StorageService()->GetBlackListDevices(QB_.Offset, QB_.Limit, Devices)) {
|
||||
for(const auto &i:Devices) {
|
||||
Poco::JSON::Object O;
|
||||
i.to_json(O);
|
||||
Arr.add(O);
|
||||
}
|
||||
}
|
||||
Answer.set("devices", Arr);
|
||||
return ReturnObject(Answer);
|
||||
}
|
||||
}
|
||||
27
src/RESTAPI/RESTAPI_blacklist_list.h
Normal file
27
src/RESTAPI/RESTAPI_blacklist_list.h
Normal file
@@ -0,0 +1,27 @@
|
||||
//
|
||||
// Created by stephane bourque on 2021-10-14.
|
||||
//
|
||||
|
||||
#ifndef UCENTRALGW_RESTAPI_BLACKLIST_LIST_H
|
||||
#define UCENTRALGW_RESTAPI_BLACKLIST_LIST_H
|
||||
|
||||
#include "framework/MicroService.h"
|
||||
|
||||
namespace OpenWifi {
|
||||
class RESTAPI_blacklist_list : public RESTAPIHandler {
|
||||
public:
|
||||
RESTAPI_blacklist_list(const RESTAPIHandler::BindingMap &bindings, Poco::Logger &L, RESTAPI_GenericServer & Server, bool Internal)
|
||||
: RESTAPIHandler(bindings, L,
|
||||
std::vector<std::string>{Poco::Net::HTTPRequest::HTTP_GET,
|
||||
Poco::Net::HTTPRequest::HTTP_OPTIONS},
|
||||
Server,
|
||||
Internal) {}
|
||||
static const std::list<const char *> PathName() { return std::list<const char *>{"/api/v1/blacklist"};}
|
||||
void DoGet() final;
|
||||
void DoDelete() final {};
|
||||
void DoPost() final {};
|
||||
void DoPut() final {};
|
||||
};
|
||||
}
|
||||
|
||||
#endif // UCENTRALGW_RESTAPI_BLACKLIST_LIST_H
|
||||
28
src/RESTAPI/RESTAPI_capabilities_handler.cpp
Normal file
28
src/RESTAPI/RESTAPI_capabilities_handler.cpp
Normal file
@@ -0,0 +1,28 @@
|
||||
//
|
||||
// Created by stephane bourque on 2021-10-17.
|
||||
//
|
||||
|
||||
#include "RESTAPI_capabilities_handler.h"
|
||||
#include "StorageService.h"
|
||||
|
||||
namespace OpenWifi {
|
||||
|
||||
void RESTAPI_capabilities_handler::DoGet() {
|
||||
Storage::DeviceCapabilitiesCache DevCaps;
|
||||
|
||||
StorageService()->GetDeviceCapabilitiesCache(DevCaps);
|
||||
Poco::JSON::Array ObjArr;
|
||||
for(const auto &[deviceType,capabilities]:DevCaps) {
|
||||
Poco::JSON::Object Inner;
|
||||
Inner.set("deviceType",deviceType);
|
||||
Poco::JSON::Parser P;
|
||||
auto R = P.parse(capabilities).extract<Poco::JSON::Object::Ptr>();
|
||||
Inner.set("capabilities", R);
|
||||
ObjArr.add(Inner);
|
||||
}
|
||||
Poco::JSON::Object Answer;
|
||||
|
||||
Answer.set("devices",ObjArr);
|
||||
return ReturnObject(Answer);
|
||||
}
|
||||
}
|
||||
26
src/RESTAPI/RESTAPI_capabilities_handler.h
Normal file
26
src/RESTAPI/RESTAPI_capabilities_handler.h
Normal file
@@ -0,0 +1,26 @@
|
||||
//
|
||||
// Created by stephane bourque on 2021-10-17.
|
||||
//
|
||||
|
||||
#ifndef UCENTRALGW_RESTAPI_CAPABILITIES_HANDLER_H
|
||||
#define UCENTRALGW_RESTAPI_CAPABILITIES_HANDLER_H
|
||||
|
||||
#include "framework/MicroService.h"
|
||||
|
||||
namespace OpenWifi {
|
||||
class RESTAPI_capabilities_handler : public RESTAPIHandler {
|
||||
public:
|
||||
RESTAPI_capabilities_handler(const RESTAPIHandler::BindingMap &bindings, Poco::Logger &L, RESTAPI_GenericServer & Server, bool Internal)
|
||||
: RESTAPIHandler(bindings, L,
|
||||
std::vector<std::string>{Poco::Net::HTTPRequest::HTTP_GET,
|
||||
Poco::Net::HTTPRequest::HTTP_OPTIONS},
|
||||
Server,
|
||||
Internal) {}
|
||||
static const std::list<const char *> PathName() { return std::list<const char *>{"/api/v1/capabilities"};}
|
||||
void DoGet() final;
|
||||
void DoDelete() final {};
|
||||
void DoPost() final {};
|
||||
void DoPut() final {};
|
||||
};
|
||||
}
|
||||
#endif // UCENTRALGW_RESTAPI_CAPABILITIES_HANDLER_H
|
||||
@@ -8,42 +8,37 @@
|
||||
|
||||
#include "RESTAPI_command.h"
|
||||
|
||||
#include "RESTAPI_protocol.h"
|
||||
#include "StorageService.h"
|
||||
#include "RESTAPI_errors.h"
|
||||
#include "framework/RESTAPI_errors.h"
|
||||
#include "framework/RESTAPI_protocol.h"
|
||||
|
||||
namespace OpenWifi {
|
||||
void RESTAPI_command::DoGet() {
|
||||
auto CommandUUID = GetBinding(RESTAPI::Protocol::COMMANDUUID, "");
|
||||
GWObjects::CommandDetails Command;
|
||||
if (Storage()->GetCommand(CommandUUID, Command)) {
|
||||
if (StorageService()->GetCommand(CommandUUID, Command)) {
|
||||
Poco::JSON::Object RetObj;
|
||||
Command.to_json(RetObj);
|
||||
ReturnObject(RetObj);
|
||||
return;
|
||||
return ReturnObject(RetObj);
|
||||
}
|
||||
NotFound();
|
||||
return NotFound();
|
||||
}
|
||||
|
||||
void RESTAPI_command::DoDelete() {
|
||||
auto UUID = GetBinding(RESTAPI::Protocol::COMMANDUUID, "");
|
||||
|
||||
if(UUID.empty()) {
|
||||
BadRequest(RESTAPI::Errors::MissingUUID);
|
||||
return;
|
||||
return BadRequest(RESTAPI::Errors::MissingUUID);
|
||||
}
|
||||
|
||||
GWObjects::CommandDetails C;
|
||||
if(!Storage()->GetCommand(UUID, C)) {
|
||||
NotFound();
|
||||
return;
|
||||
if(!StorageService()->GetCommand(UUID, C)) {
|
||||
return NotFound();
|
||||
}
|
||||
|
||||
if (Storage()->DeleteCommand(UUID)) {
|
||||
OK();
|
||||
return;
|
||||
if (StorageService()->DeleteCommand(UUID)) {
|
||||
return OK();
|
||||
}
|
||||
|
||||
InternalError();
|
||||
return InternalError();
|
||||
}
|
||||
}
|
||||
@@ -9,7 +9,7 @@
|
||||
#ifndef UCENTRAL_RESTAPI_COMMAND_H
|
||||
#define UCENTRAL_RESTAPI_COMMAND_H
|
||||
|
||||
#include "RESTAPI_handler.h"
|
||||
#include "framework/MicroService.h"
|
||||
|
||||
namespace OpenWifi {
|
||||
class RESTAPI_command : public RESTAPIHandler {
|
||||
@@ -7,19 +7,18 @@
|
||||
//
|
||||
|
||||
#include "RESTAPI_commands.h"
|
||||
#include "RESTAPI_protocol.h"
|
||||
#include "StorageService.h"
|
||||
#include "Utils.h"
|
||||
#include "RESTAPI_errors.h"
|
||||
#include "framework/RESTAPI_errors.h"
|
||||
#include "framework/RESTAPI_protocol.h"
|
||||
|
||||
namespace OpenWifi {
|
||||
void RESTAPI_commands::DoGet() {
|
||||
auto SerialNumber = GetParameter(RESTAPI::Protocol::SERIALNUMBER, "");
|
||||
std::vector<GWObjects::CommandDetails> Commands;
|
||||
if (QB_.Newest) {
|
||||
Storage()->GetNewestCommands(SerialNumber, QB_.Limit, Commands);
|
||||
StorageService()->GetNewestCommands(SerialNumber, QB_.Limit, Commands);
|
||||
} else {
|
||||
Storage()->GetCommands(SerialNumber, QB_.StartDate, QB_.EndDate, QB_.Offset, QB_.Limit,
|
||||
StorageService()->GetCommands(SerialNumber, QB_.StartDate, QB_.EndDate, QB_.Offset, QB_.Limit,
|
||||
Commands);
|
||||
}
|
||||
Poco::JSON::Array ArrayObj;
|
||||
@@ -37,15 +36,11 @@ namespace OpenWifi {
|
||||
auto SerialNumber = GetParameter(RESTAPI::Protocol::SERIALNUMBER, "");
|
||||
|
||||
if(SerialNumber.empty()) {
|
||||
BadRequest(RESTAPI::Errors::MissingSerialNumber);
|
||||
return;
|
||||
return BadRequest(RESTAPI::Errors::MissingSerialNumber);
|
||||
}
|
||||
|
||||
if (Storage()->DeleteCommands(SerialNumber, QB_.StartDate, QB_.EndDate)) {
|
||||
OK();
|
||||
return;
|
||||
if (StorageService()->DeleteCommands(SerialNumber, QB_.StartDate, QB_.EndDate)) {
|
||||
return OK();
|
||||
}
|
||||
|
||||
InternalError();
|
||||
}
|
||||
}
|
||||
@@ -9,7 +9,7 @@
|
||||
#ifndef UCENTRAL_RESTAPI_COMMANDS_H
|
||||
#define UCENTRAL_RESTAPI_COMMANDS_H
|
||||
|
||||
#include "RESTAPI_handler.h"
|
||||
#include "framework/MicroService.h"
|
||||
|
||||
namespace OpenWifi {
|
||||
class RESTAPI_commands : public RESTAPIHandler {
|
||||
@@ -10,20 +10,19 @@
|
||||
|
||||
#include "RESTAPI_default_configuration.h"
|
||||
|
||||
#include "RESTAPI_GWobjects.h"
|
||||
#include "RESTAPI_protocol.h"
|
||||
#include "RESTObjects/RESTAPI_GWobjects.h"
|
||||
#include "StorageService.h"
|
||||
#include "RESTAPI_errors.h"
|
||||
#include "framework/RESTAPI_errors.h"
|
||||
#include "framework/RESTAPI_protocol.h"
|
||||
|
||||
namespace OpenWifi {
|
||||
void RESTAPI_default_configuration::DoGet() {
|
||||
std::string Name = GetBinding(RESTAPI::Protocol::NAME, "");
|
||||
GWObjects::DefaultConfiguration DefConfig;
|
||||
if (Storage()->GetDefaultConfiguration(Name, DefConfig)) {
|
||||
if (StorageService()->GetDefaultConfiguration(Name, DefConfig)) {
|
||||
Poco::JSON::Object Obj;
|
||||
DefConfig.to_json(Obj);
|
||||
ReturnObject(Obj);
|
||||
return;
|
||||
return ReturnObject(Obj);
|
||||
}
|
||||
NotFound();
|
||||
}
|
||||
@@ -31,13 +30,11 @@ namespace OpenWifi {
|
||||
void RESTAPI_default_configuration::DoDelete() {
|
||||
std::string Name = GetBinding(RESTAPI::Protocol::NAME, "");
|
||||
if(Name.empty()) {
|
||||
BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
|
||||
return;
|
||||
return BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
|
||||
}
|
||||
|
||||
if (Storage()->DeleteDefaultConfiguration(Name)) {
|
||||
OK();
|
||||
return;
|
||||
if (StorageService()->DeleteDefaultConfiguration(Name)) {
|
||||
return OK();
|
||||
}
|
||||
BadRequest(RESTAPI::Errors::CouldNotBeDeleted);
|
||||
}
|
||||
@@ -46,20 +43,17 @@ namespace OpenWifi {
|
||||
std::string Name = GetBinding(RESTAPI::Protocol::NAME, "");
|
||||
|
||||
if(Name.empty()) {
|
||||
BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
|
||||
return;
|
||||
return BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
|
||||
}
|
||||
|
||||
auto Obj = ParseStream();
|
||||
GWObjects::DefaultConfiguration DefConfig;
|
||||
if (!DefConfig.from_json(Obj)) {
|
||||
BadRequest(RESTAPI::Errors::InvalidJSONDocument);
|
||||
return;
|
||||
return BadRequest(RESTAPI::Errors::InvalidJSONDocument);
|
||||
}
|
||||
|
||||
if (Storage()->CreateDefaultConfiguration(Name, DefConfig)) {
|
||||
OK();
|
||||
return;
|
||||
if (StorageService()->CreateDefaultConfiguration(Name, DefConfig)) {
|
||||
return OK();
|
||||
}
|
||||
BadRequest(RESTAPI::Errors::RecordNotCreated);
|
||||
}
|
||||
@@ -71,13 +65,11 @@ namespace OpenWifi {
|
||||
GWObjects::DefaultConfiguration DefConfig;
|
||||
|
||||
if (!DefConfig.from_json(Obj)) {
|
||||
BadRequest(RESTAPI::Errors::InvalidJSONDocument);
|
||||
return;
|
||||
return BadRequest(RESTAPI::Errors::InvalidJSONDocument);
|
||||
}
|
||||
|
||||
if (Storage()->UpdateDefaultConfiguration(Name, DefConfig)) {
|
||||
OK();
|
||||
return;
|
||||
if (StorageService()->UpdateDefaultConfiguration(Name, DefConfig)) {
|
||||
return OK();
|
||||
}
|
||||
BadRequest(RESTAPI::Errors::RecordNotUpdated);
|
||||
}
|
||||
@@ -9,7 +9,7 @@
|
||||
#ifndef UCENTRAL_RESTAPI_DEFAULT_CONFIGURATION_H
|
||||
#define UCENTRAL_RESTAPI_DEFAULT_CONFIGURATION_H
|
||||
|
||||
#include "RESTAPI_handler.h"
|
||||
#include "framework/MicroService.h"
|
||||
|
||||
namespace OpenWifi {
|
||||
class RESTAPI_default_configuration : public RESTAPIHandler {
|
||||
@@ -10,13 +10,13 @@
|
||||
#include "Poco/JSON/Stringifier.h"
|
||||
|
||||
#include "RESTAPI_default_configurations.h"
|
||||
#include "RESTAPI_protocol.h"
|
||||
#include "StorageService.h"
|
||||
#include "framework/RESTAPI_protocol.h"
|
||||
|
||||
namespace OpenWifi {
|
||||
void RESTAPI_default_configurations::DoGet() {
|
||||
std::vector<GWObjects::DefaultConfiguration> DefConfigs;
|
||||
Storage()->GetDefaultConfigurations(QB_.Offset, QB_.Limit, DefConfigs);
|
||||
StorageService()->GetDefaultConfigurations(QB_.Offset, QB_.Limit, DefConfigs);
|
||||
|
||||
Poco::JSON::Array Objects;
|
||||
for (const auto &i : DefConfigs) {
|
||||
@@ -9,7 +9,7 @@
|
||||
#ifndef UCENTRAL_RESTAPI_DEFAULT_CONFIGURATIONS_H
|
||||
#define UCENTRAL_RESTAPI_DEFAULT_CONFIGURATIONS_H
|
||||
|
||||
#include "RESTAPI_handler.h"
|
||||
#include "framework/MicroService.h"
|
||||
|
||||
namespace OpenWifi {
|
||||
class RESTAPI_default_configurations : public RESTAPIHandler {
|
||||
@@ -5,7 +5,7 @@
|
||||
#ifndef UCENTRALGW_RESTAPI_DEVICEDASHBOARDHANDLER_H
|
||||
#define UCENTRALGW_RESTAPI_DEVICEDASHBOARDHANDLER_H
|
||||
|
||||
#include "RESTAPI_handler.h"
|
||||
#include "framework/MicroService.h"
|
||||
|
||||
namespace OpenWifi {
|
||||
class RESTAPI_deviceDashboardHandler : public RESTAPIHandler {
|
||||
@@ -13,117 +13,124 @@
|
||||
#include "Poco/JSON/Parser.h"
|
||||
|
||||
#include "CentralConfig.h"
|
||||
#include "Daemon.h"
|
||||
#include "DeviceRegistry.h"
|
||||
#include "FileUploader.h"
|
||||
#include "RESTAPI_GWobjects.h"
|
||||
#include "RESTObjects/RESTAPI_GWobjects.h"
|
||||
#include "RESTAPI_device_commandHandler.h"
|
||||
#include "StorageService.h"
|
||||
#include "Utils.h"
|
||||
|
||||
#include "uCentralProtocol.h"
|
||||
#include "RESTAPI_protocol.h"
|
||||
#include "RESTAPI_RPC.h"
|
||||
|
||||
#include "CommandManager.h"
|
||||
#include "KafkaManager.h"
|
||||
#include "Kafka_topics.h"
|
||||
#include "TelemetryStream.h"
|
||||
#include "RESTAPI_errors.h"
|
||||
#include "framework/RESTAPI_protocol.h"
|
||||
#include "framework/uCentral_Protocol.h"
|
||||
#include "framework/KafkaTopics.h"
|
||||
#include "framework/RESTAPI_errors.h"
|
||||
|
||||
namespace OpenWifi {
|
||||
|
||||
void RESTAPI_device_commandHandler::DoGet() {
|
||||
if(!ValidateParameters()) {
|
||||
BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
|
||||
return;
|
||||
return BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
|
||||
}
|
||||
|
||||
GWObjects::Device TheDevice;
|
||||
if(!StorageService()->GetDevice(SerialNumber_,TheDevice)) {
|
||||
return NotFound();
|
||||
}
|
||||
|
||||
if (Command_ == RESTAPI::Protocol::CAPABILITIES){
|
||||
GetCapabilities();
|
||||
return GetCapabilities();
|
||||
} else if (Command_ == RESTAPI::Protocol::LOGS) {
|
||||
GetLogs();
|
||||
return GetLogs();
|
||||
} else if (Command_ == RESTAPI::Protocol::HEALTHCHECKS) {
|
||||
GetChecks();
|
||||
return GetChecks();
|
||||
} else if (Command_ == RESTAPI::Protocol::STATISTICS) {
|
||||
GetStatistics();
|
||||
return GetStatistics();
|
||||
} else if (Command_ == RESTAPI::Protocol::STATUS) {
|
||||
GetStatus();
|
||||
return GetStatus();
|
||||
} else if (Command_ == RESTAPI::Protocol::RTTY) {
|
||||
Rtty();
|
||||
return Rtty();
|
||||
} else {
|
||||
BadRequest(RESTAPI::Errors::InvalidCommand);
|
||||
return BadRequest(RESTAPI::Errors::InvalidCommand);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void RESTAPI_device_commandHandler::DoDelete() {
|
||||
if(!ValidateParameters()) {
|
||||
BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
|
||||
return;
|
||||
return BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
|
||||
}
|
||||
|
||||
GWObjects::Device TheDevice;
|
||||
if(!StorageService()->GetDevice(SerialNumber_,TheDevice)) {
|
||||
return NotFound();
|
||||
}
|
||||
|
||||
if (Command_ == RESTAPI::Protocol::CAPABILITIES) {
|
||||
DeleteCapabilities();
|
||||
return DeleteCapabilities();
|
||||
} else if (Command_ == RESTAPI::Protocol::LOGS){
|
||||
DeleteLogs();
|
||||
return DeleteLogs();
|
||||
} else if (Command_ == RESTAPI::Protocol::HEALTHCHECKS){
|
||||
DeleteChecks();
|
||||
return DeleteChecks();
|
||||
} else if (Command_ == RESTAPI::Protocol::STATISTICS) {
|
||||
DeleteStatistics();
|
||||
return DeleteStatistics();
|
||||
} else {
|
||||
BadRequest(RESTAPI::Errors::InvalidCommand);
|
||||
return BadRequest(RESTAPI::Errors::InvalidCommand);
|
||||
}
|
||||
}
|
||||
|
||||
void RESTAPI_device_commandHandler::DoPost() {
|
||||
if(!ValidateParameters()) {
|
||||
BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
|
||||
return;
|
||||
return BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
|
||||
}
|
||||
|
||||
GWObjects::Device TheDevice;
|
||||
if(!StorageService()->GetDevice(SerialNumber_,TheDevice)) {
|
||||
return NotFound();
|
||||
}
|
||||
|
||||
if (Command_ == RESTAPI::Protocol::PERFORM) {
|
||||
ExecuteCommand();
|
||||
return ExecuteCommand();
|
||||
} else if (Command_ == RESTAPI::Protocol::CONFIGURE) {
|
||||
Configure();
|
||||
return Configure();
|
||||
} else if (Command_ == RESTAPI::Protocol::UPGRADE) {
|
||||
Upgrade();
|
||||
return Upgrade();
|
||||
} else if (Command_ == RESTAPI::Protocol::REBOOT) {
|
||||
Reboot();
|
||||
return Reboot();
|
||||
} else if (Command_ == RESTAPI::Protocol::FACTORY) {
|
||||
Factory();
|
||||
return Factory();
|
||||
} else if (Command_ == RESTAPI::Protocol::LEDS) {
|
||||
LEDs();
|
||||
return LEDs();
|
||||
} else if (Command_ == RESTAPI::Protocol::TRACE) {
|
||||
Trace();
|
||||
return Trace();
|
||||
} else if (Command_ == RESTAPI::Protocol::REQUEST) {
|
||||
MakeRequest();
|
||||
return MakeRequest();
|
||||
} else if (Command_ == RESTAPI::Protocol::WIFISCAN) {
|
||||
WifiScan();
|
||||
return WifiScan();
|
||||
} else if (Command_ == RESTAPI::Protocol::EVENTQUEUE) {
|
||||
EventQueue();
|
||||
return EventQueue();
|
||||
} else if (Command_ == RESTAPI::Protocol::TELEMETRY) {
|
||||
Telemetry();
|
||||
return Telemetry();
|
||||
} else {
|
||||
BadRequest(RESTAPI::Errors::InvalidCommand);
|
||||
return BadRequest(RESTAPI::Errors::InvalidCommand);
|
||||
}
|
||||
}
|
||||
|
||||
void RESTAPI_device_commandHandler::GetCapabilities() {
|
||||
GWObjects::Capabilities Caps;
|
||||
if (Storage()->GetDeviceCapabilities(SerialNumber_, Caps)) {
|
||||
if (StorageService()->GetDeviceCapabilities(SerialNumber_, Caps)) {
|
||||
Poco::JSON::Object RetObj;
|
||||
Caps.to_json(RetObj);
|
||||
RetObj.set(RESTAPI::Protocol::SERIALNUMBER, SerialNumber_);
|
||||
ReturnObject(RetObj);
|
||||
return;
|
||||
return ReturnObject(RetObj);
|
||||
}
|
||||
NotFound();
|
||||
}
|
||||
|
||||
void RESTAPI_device_commandHandler::DeleteCapabilities() {
|
||||
Logger_.information(Poco::format("DELETE-CAPABILITIES: user=%s serial=%s", UserInfo_.userinfo.email,SerialNumber_));
|
||||
if (Storage()->DeleteDeviceCapabilities(SerialNumber_)) {
|
||||
OK();
|
||||
return;
|
||||
if (StorageService()->DeleteDeviceCapabilities(SerialNumber_)) {
|
||||
return OK();
|
||||
}
|
||||
NotFound();
|
||||
}
|
||||
@@ -131,12 +138,12 @@ void RESTAPI_device_commandHandler::DeleteCapabilities() {
|
||||
void RESTAPI_device_commandHandler::GetStatistics() {
|
||||
if (QB_.Lifetime) {
|
||||
std::string Stats;
|
||||
Storage()->GetLifetimeStats(SerialNumber_, Stats);
|
||||
StorageService()->GetLifetimeStats(SerialNumber_, Stats);
|
||||
Poco::JSON::Parser P;
|
||||
if (Stats.empty())
|
||||
Stats = uCentralProtocol::EMPTY_JSON_DOC;
|
||||
auto Obj = P.parse(Stats).extract<Poco::JSON::Object::Ptr>();
|
||||
ReturnObject(*Obj);
|
||||
return ReturnObject(*Obj);
|
||||
} else if (QB_.LastOnly) {
|
||||
std::string Stats;
|
||||
if (DeviceRegistry()->GetStatistics(SerialNumber_, Stats)) {
|
||||
@@ -144,16 +151,16 @@ void RESTAPI_device_commandHandler::GetStatistics() {
|
||||
if (Stats.empty())
|
||||
Stats = uCentralProtocol::EMPTY_JSON_DOC;
|
||||
auto Obj = P.parse(Stats).extract<Poco::JSON::Object::Ptr>();
|
||||
ReturnObject(*Obj);
|
||||
return ReturnObject(*Obj);
|
||||
} else {
|
||||
NotFound();
|
||||
return NotFound();
|
||||
}
|
||||
} else {
|
||||
std::vector<GWObjects::Statistics> Stats;
|
||||
if (QB_.Newest) {
|
||||
Storage()->GetNewestStatisticsData(SerialNumber_, QB_.Limit, Stats);
|
||||
StorageService()->GetNewestStatisticsData(SerialNumber_, QB_.Limit, Stats);
|
||||
} else {
|
||||
Storage()->GetStatisticsData(SerialNumber_, QB_.StartDate, QB_.EndDate,
|
||||
StorageService()->GetStatisticsData(SerialNumber_, QB_.StartDate, QB_.EndDate,
|
||||
QB_.Offset, QB_.Limit, Stats);
|
||||
}
|
||||
Poco::JSON::Array ArrayObj;
|
||||
@@ -165,21 +172,19 @@ void RESTAPI_device_commandHandler::GetStatistics() {
|
||||
Poco::JSON::Object RetObj;
|
||||
RetObj.set(RESTAPI::Protocol::DATA, ArrayObj);
|
||||
RetObj.set(RESTAPI::Protocol::SERIALNUMBER, SerialNumber_);
|
||||
ReturnObject(RetObj);
|
||||
return ReturnObject(RetObj);
|
||||
}
|
||||
}
|
||||
|
||||
void RESTAPI_device_commandHandler::DeleteStatistics() {
|
||||
Logger_.information(Poco::format("DELETE-STATISTICS: user=%s serial=%s", UserInfo_.userinfo.email,SerialNumber_));
|
||||
if (QB_.Lifetime) {
|
||||
if (Storage()->ResetLifetimeStats(SerialNumber_)) {
|
||||
OK();
|
||||
return;
|
||||
if (StorageService()->ResetLifetimeStats(SerialNumber_)) {
|
||||
return OK();
|
||||
}
|
||||
} else {
|
||||
if (Storage()->DeleteStatisticsData(SerialNumber_, QB_.StartDate, QB_.EndDate)) {
|
||||
OK();
|
||||
return;
|
||||
if (StorageService()->DeleteStatisticsData(SerialNumber_, QB_.StartDate, QB_.EndDate)) {
|
||||
return OK();
|
||||
}
|
||||
}
|
||||
NotFound();
|
||||
@@ -191,8 +196,7 @@ void RESTAPI_device_commandHandler::GetStatus() {
|
||||
if (DeviceRegistry()->GetState(SerialNumber_, State)) {
|
||||
Poco::JSON::Object RetObject;
|
||||
State.to_json(RetObject);
|
||||
ReturnObject(RetObject);
|
||||
return;
|
||||
return ReturnObject(RetObject);
|
||||
}
|
||||
NotFound();
|
||||
}
|
||||
@@ -207,18 +211,17 @@ void RESTAPI_device_commandHandler::Configure() {
|
||||
|
||||
auto SNum = Obj->get(RESTAPI::Protocol::SERIALNUMBER).toString();
|
||||
if (SerialNumber_ != SNum) {
|
||||
BadRequest(RESTAPI::Errors::SerialNumberMismatch);
|
||||
return;
|
||||
return BadRequest(RESTAPI::Errors::SerialNumberMismatch);
|
||||
}
|
||||
|
||||
auto Configuration = GetS(RESTAPI::Protocol::CONFIGURATION, Obj,uCentralProtocol::EMPTY_JSON_DOC);
|
||||
auto When = GetWhen(Obj);
|
||||
uint64_t NewUUID;
|
||||
if (Storage()->UpdateDeviceConfiguration(SerialNumber_, Configuration, NewUUID)) {
|
||||
if (StorageService()->UpdateDeviceConfiguration(SerialNumber_, Configuration, NewUUID)) {
|
||||
GWObjects::CommandDetails Cmd;
|
||||
|
||||
Cmd.SerialNumber = SerialNumber_;
|
||||
Cmd.UUID = Daemon()->CreateUUID();
|
||||
Cmd.UUID = MicroService::CreateUUID();
|
||||
Cmd.SubmittedBy = UserInfo_.webtoken.username_;
|
||||
Cmd.Command = uCentralProtocol::CONFIGURE;
|
||||
Cmd.RunAt = When;
|
||||
@@ -235,11 +238,9 @@ void RESTAPI_device_commandHandler::Configure() {
|
||||
Cmd.Details = ParamStream.str();
|
||||
|
||||
DeviceRegistry()->SetPendingUUID(SerialNumber_, NewUUID);
|
||||
RESTAPI_RPC::WaitForCommand(Cmd, Params, *Request, *Response, 60000, nullptr, this, Logger_);
|
||||
return;
|
||||
return RESTAPI_RPC::WaitForCommand(Cmd, Params, *Request, *Response, 60000, nullptr, this, Logger_);
|
||||
}
|
||||
BadRequest(RESTAPI::Errors::RecordNotUpdated);
|
||||
return;
|
||||
return BadRequest(RESTAPI::Errors::RecordNotUpdated);
|
||||
}
|
||||
BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
|
||||
}
|
||||
@@ -253,8 +254,7 @@ void RESTAPI_device_commandHandler::Upgrade() {
|
||||
|
||||
auto SNum = Obj->get(RESTAPI::Protocol::SERIALNUMBER).toString();
|
||||
if (SerialNumber_ != SNum) {
|
||||
BadRequest(RESTAPI::Errors::SerialNumberMismatch);
|
||||
return;
|
||||
return BadRequest(RESTAPI::Errors::SerialNumberMismatch);
|
||||
}
|
||||
|
||||
auto URI = GetS(RESTAPI::Protocol::URI, Obj);
|
||||
@@ -263,7 +263,7 @@ void RESTAPI_device_commandHandler::Upgrade() {
|
||||
GWObjects::CommandDetails Cmd;
|
||||
|
||||
Cmd.SerialNumber = SerialNumber_;
|
||||
Cmd.UUID = Daemon()->CreateUUID();
|
||||
Cmd.UUID = MicroService::CreateUUID();
|
||||
Cmd.SubmittedBy = UserInfo_.webtoken.username_;
|
||||
Cmd.Command = uCentralProtocol::UPGRADE;
|
||||
Cmd.RunAt = When;
|
||||
@@ -278,8 +278,7 @@ void RESTAPI_device_commandHandler::Upgrade() {
|
||||
Params.stringify(ParamStream);
|
||||
Cmd.Details = ParamStream.str();
|
||||
|
||||
RESTAPI_RPC::WaitForCommand(Cmd, Params, *Request, *Response, 60000, nullptr, this, Logger_);
|
||||
return;
|
||||
return RESTAPI_RPC::WaitForCommand(Cmd, Params, *Request, *Response, 60000, nullptr, this, Logger_);
|
||||
}
|
||||
BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
|
||||
}
|
||||
@@ -287,9 +286,9 @@ void RESTAPI_device_commandHandler::Upgrade() {
|
||||
void RESTAPI_device_commandHandler::GetLogs() {
|
||||
std::vector<GWObjects::DeviceLog> Logs;
|
||||
if (QB_.Newest) {
|
||||
Storage()->GetNewestLogData(SerialNumber_, QB_.Limit, Logs, QB_.LogType);
|
||||
StorageService()->GetNewestLogData(SerialNumber_, QB_.Limit, Logs, QB_.LogType);
|
||||
} else {
|
||||
Storage()->GetLogData(SerialNumber_, QB_.StartDate, QB_.EndDate, QB_.Offset,
|
||||
StorageService()->GetLogData(SerialNumber_, QB_.StartDate, QB_.EndDate, QB_.Offset,
|
||||
QB_.Limit, Logs, QB_.LogType);
|
||||
}
|
||||
|
||||
@@ -307,10 +306,9 @@ void RESTAPI_device_commandHandler::GetLogs() {
|
||||
|
||||
void RESTAPI_device_commandHandler::DeleteLogs() {
|
||||
Logger_.information(Poco::format("DELETE-LOGS: user=%s serial=%s", UserInfo_.userinfo.email,SerialNumber_));
|
||||
if (Storage()->DeleteLogData(SerialNumber_, QB_.StartDate, QB_.EndDate,
|
||||
if (StorageService()->DeleteLogData(SerialNumber_, QB_.StartDate, QB_.EndDate,
|
||||
QB_.LogType)) {
|
||||
OK();
|
||||
return;
|
||||
return OK();
|
||||
}
|
||||
BadRequest(RESTAPI::Errors::NoRecordsDeleted);
|
||||
}
|
||||
@@ -323,15 +321,15 @@ void RESTAPI_device_commandHandler::GetChecks() {
|
||||
if (DeviceRegistry()->GetHealthcheck(SerialNumber_, HC)) {
|
||||
Poco::JSON::Object Answer;
|
||||
HC.to_json(Answer);
|
||||
ReturnObject(Answer);
|
||||
return ReturnObject(Answer);
|
||||
} else {
|
||||
NotFound();
|
||||
return NotFound();
|
||||
}
|
||||
} else {
|
||||
if (QB_.Newest) {
|
||||
Storage()->GetNewestHealthCheckData(SerialNumber_, QB_.Limit, Checks);
|
||||
StorageService()->GetNewestHealthCheckData(SerialNumber_, QB_.Limit, Checks);
|
||||
} else {
|
||||
Storage()->GetHealthCheckData(SerialNumber_, QB_.StartDate, QB_.EndDate,
|
||||
StorageService()->GetHealthCheckData(SerialNumber_, QB_.StartDate, QB_.EndDate,
|
||||
QB_.Offset, QB_.Limit, Checks);
|
||||
}
|
||||
|
||||
@@ -351,9 +349,8 @@ void RESTAPI_device_commandHandler::GetChecks() {
|
||||
|
||||
void RESTAPI_device_commandHandler::DeleteChecks() {
|
||||
Logger_.information(Poco::format("DELETE-HEALTHCHECKS: user=%s serial=%s", UserInfo_.userinfo.email,SerialNumber_));
|
||||
if (Storage()->DeleteHealthCheckData(SerialNumber_, QB_.StartDate, QB_.EndDate)) {
|
||||
OK();
|
||||
return;
|
||||
if (StorageService()->DeleteHealthCheckData(SerialNumber_, QB_.StartDate, QB_.EndDate)) {
|
||||
return OK();
|
||||
}
|
||||
BadRequest(RESTAPI::Errors::NoRecordsDeleted);
|
||||
}
|
||||
@@ -367,8 +364,7 @@ void RESTAPI_device_commandHandler::ExecuteCommand() {
|
||||
|
||||
auto SNum = Obj->get(RESTAPI::Protocol::SERIALNUMBER).toString();
|
||||
if (SerialNumber_ != SNum) {
|
||||
BadRequest("Missing serial number.");
|
||||
return;
|
||||
return BadRequest("Missing serial number.");
|
||||
}
|
||||
|
||||
auto Command = GetS(RESTAPI::Protocol::COMMAND, Obj);
|
||||
@@ -378,7 +374,7 @@ void RESTAPI_device_commandHandler::ExecuteCommand() {
|
||||
GWObjects::CommandDetails Cmd;
|
||||
|
||||
Cmd.SerialNumber = SerialNumber_;
|
||||
Cmd.UUID = Daemon()->CreateUUID();
|
||||
Cmd.UUID = MicroService::CreateUUID();
|
||||
Cmd.SubmittedBy = UserInfo_.webtoken.username_;
|
||||
Cmd.Command = Command;
|
||||
Cmd.Custom = 1;
|
||||
@@ -400,8 +396,7 @@ void RESTAPI_device_commandHandler::ExecuteCommand() {
|
||||
Params.stringify(ParamStream);
|
||||
Cmd.Details = ParamStream.str();
|
||||
|
||||
RESTAPI_RPC::WaitForCommand(Cmd, Params, *Request, *Response, 60000, nullptr, this, Logger_);
|
||||
return;
|
||||
return RESTAPI_RPC::WaitForCommand(Cmd, Params, *Request, *Response, 60000, nullptr, this, Logger_);
|
||||
}
|
||||
BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
|
||||
}
|
||||
@@ -413,14 +408,13 @@ void RESTAPI_device_commandHandler::Reboot() {
|
||||
if (Obj->has(RESTAPI::Protocol::SERIALNUMBER)) {
|
||||
auto SNum = Obj->get(RESTAPI::Protocol::SERIALNUMBER).toString();
|
||||
if (SerialNumber_ != SNum) {
|
||||
BadRequest(RESTAPI::Errors::SerialNumberMismatch);
|
||||
return;
|
||||
return BadRequest(RESTAPI::Errors::SerialNumberMismatch);
|
||||
}
|
||||
|
||||
uint64_t When = GetWhen(Obj);
|
||||
GWObjects::CommandDetails Cmd;
|
||||
Cmd.SerialNumber = SerialNumber_;
|
||||
Cmd.UUID = Daemon()->CreateUUID();
|
||||
Cmd.UUID = MicroService::CreateUUID();
|
||||
Cmd.SubmittedBy = UserInfo_.webtoken.username_;
|
||||
Cmd.Command = uCentralProtocol::REBOOT;
|
||||
Cmd.RunAt = When;
|
||||
@@ -434,8 +428,7 @@ void RESTAPI_device_commandHandler::Reboot() {
|
||||
Params.stringify(ParamStream);
|
||||
Cmd.Details = ParamStream.str();
|
||||
|
||||
RESTAPI_RPC::WaitForCommand(Cmd, Params, *Request, *Response, 60000, nullptr, this, Logger_);
|
||||
return;
|
||||
return RESTAPI_RPC::WaitForCommand(Cmd, Params, *Request, *Response, 60000, nullptr, this, Logger_);
|
||||
}
|
||||
BadRequest(RESTAPI::Errors::MissingSerialNumber);
|
||||
}
|
||||
@@ -449,8 +442,7 @@ void RESTAPI_device_commandHandler::Factory() {
|
||||
auto SNum = Obj->get(RESTAPI::Protocol::SERIALNUMBER).toString();
|
||||
|
||||
if (SerialNumber_ != SNum) {
|
||||
BadRequest(RESTAPI::Errors::SerialNumberMismatch);
|
||||
return;
|
||||
return BadRequest(RESTAPI::Errors::SerialNumberMismatch);
|
||||
}
|
||||
|
||||
auto KeepRedirector = GetB(RESTAPI::Protocol::KEEPREDIRECTOR, Obj, true);
|
||||
@@ -459,7 +451,7 @@ void RESTAPI_device_commandHandler::Factory() {
|
||||
GWObjects::CommandDetails Cmd;
|
||||
|
||||
Cmd.SerialNumber = SerialNumber_;
|
||||
Cmd.UUID = Daemon()->CreateUUID();
|
||||
Cmd.UUID = MicroService::CreateUUID();
|
||||
Cmd.SubmittedBy = UserInfo_.webtoken.username_;
|
||||
Cmd.Command = uCentralProtocol::FACTORY;
|
||||
Cmd.RunAt = When;
|
||||
@@ -474,8 +466,7 @@ void RESTAPI_device_commandHandler::Factory() {
|
||||
Params.stringify(ParamStream);
|
||||
Cmd.Details = ParamStream.str();
|
||||
|
||||
RESTAPI_RPC::WaitForCommand(Cmd, Params, *Request, *Response, 60000, nullptr, this, Logger_);
|
||||
return;
|
||||
return RESTAPI_RPC::WaitForCommand(Cmd, Params, *Request, *Response, 60000, nullptr, this, Logger_);
|
||||
}
|
||||
BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
|
||||
}
|
||||
@@ -489,8 +480,7 @@ void RESTAPI_device_commandHandler::LEDs() {
|
||||
|
||||
auto SNum = Obj->get(RESTAPI::Protocol::SERIALNUMBER).toString();
|
||||
if (SerialNumber_ != SNum) {
|
||||
BadRequest(RESTAPI::Errors::SerialNumberMismatch);
|
||||
return;
|
||||
return BadRequest(RESTAPI::Errors::SerialNumberMismatch);
|
||||
}
|
||||
|
||||
auto Pattern =
|
||||
@@ -498,8 +488,7 @@ void RESTAPI_device_commandHandler::LEDs() {
|
||||
if (Pattern != uCentralProtocol::ON &&
|
||||
Pattern != uCentralProtocol::OFF &&
|
||||
Pattern != uCentralProtocol::BLINK) {
|
||||
BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
|
||||
return;
|
||||
return BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
|
||||
}
|
||||
|
||||
auto Duration = Get(uCentralProtocol::DURATION, Obj, 30);
|
||||
@@ -508,7 +497,7 @@ void RESTAPI_device_commandHandler::LEDs() {
|
||||
GWObjects::CommandDetails Cmd;
|
||||
|
||||
Cmd.SerialNumber = SerialNumber_;
|
||||
Cmd.UUID = Daemon()->CreateUUID();
|
||||
Cmd.UUID = MicroService::CreateUUID();
|
||||
Cmd.SubmittedBy = UserInfo_.webtoken.username_;
|
||||
Cmd.Command = uCentralProtocol::LEDS;
|
||||
Cmd.RunAt = When;
|
||||
@@ -523,8 +512,7 @@ void RESTAPI_device_commandHandler::LEDs() {
|
||||
Params.stringify(ParamStream);
|
||||
Cmd.Details = ParamStream.str();
|
||||
|
||||
RESTAPI_RPC::WaitForCommand(Cmd, Params, *Request, *Response, 60000, nullptr, this, Logger_);
|
||||
return;
|
||||
return RESTAPI_RPC::WaitForCommand(Cmd, Params, *Request, *Response, 60000, nullptr, this, Logger_);
|
||||
}
|
||||
BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
|
||||
}
|
||||
@@ -539,8 +527,7 @@ void RESTAPI_device_commandHandler::Trace() {
|
||||
|
||||
auto SNum = Obj->get(RESTAPI::Protocol::SERIALNUMBER).toString();
|
||||
if (SerialNumber_ != SNum) {
|
||||
BadRequest(RESTAPI::Errors::SerialNumberMismatch);
|
||||
return;
|
||||
return BadRequest(RESTAPI::Errors::SerialNumberMismatch);
|
||||
}
|
||||
|
||||
auto Duration = Get(RESTAPI::Protocol::DURATION, Obj, 30);
|
||||
@@ -549,7 +536,7 @@ void RESTAPI_device_commandHandler::Trace() {
|
||||
|
||||
auto Network = GetS(RESTAPI::Protocol::NETWORK, Obj);
|
||||
auto Interface = GetS(RESTAPI::Protocol::INTERFACE, Obj);
|
||||
auto UUID = Daemon()->CreateUUID();
|
||||
auto UUID = MicroService::CreateUUID();
|
||||
auto URI = FileUploader()->FullName() + UUID;
|
||||
|
||||
GWObjects::CommandDetails Cmd;
|
||||
@@ -576,8 +563,7 @@ void RESTAPI_device_commandHandler::Trace() {
|
||||
Cmd.Details = ParamStream.str();
|
||||
|
||||
FileUploader()->AddUUID(UUID);
|
||||
RESTAPI_RPC::WaitForCommand(Cmd, Params, *Request, *Response, 60000, nullptr, this, Logger_);
|
||||
return;
|
||||
return RESTAPI_RPC::WaitForCommand(Cmd, Params, *Request, *Response, 60000, nullptr, this, Logger_);
|
||||
}
|
||||
BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
|
||||
}
|
||||
@@ -588,8 +574,7 @@ void RESTAPI_device_commandHandler::WifiScan() {
|
||||
|
||||
auto SNum = Obj->get(RESTAPI::Protocol::SERIALNUMBER).toString();
|
||||
if (SerialNumber_ != SNum) {
|
||||
BadRequest(RESTAPI::Errors::SerialNumberMismatch);
|
||||
return;
|
||||
return BadRequest(RESTAPI::Errors::SerialNumberMismatch);
|
||||
}
|
||||
|
||||
if ((Obj->has(RESTAPI::Protocol::BANDS) &&
|
||||
@@ -599,7 +584,7 @@ void RESTAPI_device_commandHandler::WifiScan() {
|
||||
(!Obj->has(RESTAPI::Protocol::BANDS) &&
|
||||
!Obj->has(RESTAPI::Protocol::CHANNELS)))) {
|
||||
bool Verbose = GetB(RESTAPI::Protocol::VERBOSE, Obj);
|
||||
auto UUID = Daemon()->CreateUUID();
|
||||
auto UUID = MicroService::CreateUUID();
|
||||
GWObjects::CommandDetails Cmd;
|
||||
|
||||
Cmd.SerialNumber = SerialNumber_;
|
||||
@@ -645,13 +630,12 @@ void RESTAPI_device_commandHandler::EventQueue() {
|
||||
|
||||
auto SNum = Obj->get(RESTAPI::Protocol::SERIALNUMBER).toString();
|
||||
if (SerialNumber_ != SNum) {
|
||||
BadRequest(RESTAPI::Errors::SerialNumberMismatch);
|
||||
return;
|
||||
return BadRequest(RESTAPI::Errors::SerialNumberMismatch);
|
||||
}
|
||||
|
||||
auto Types = Obj->getArray(RESTAPI::Protocol::TYPES);
|
||||
|
||||
auto UUID = Daemon()->CreateUUID();
|
||||
auto UUID = MicroService::CreateUUID();
|
||||
GWObjects::CommandDetails Cmd;
|
||||
|
||||
Cmd.SerialNumber = SerialNumber_;
|
||||
@@ -689,8 +673,7 @@ void RESTAPI_device_commandHandler::MakeRequest() {
|
||||
if ((SerialNumber_ != SNum) ||
|
||||
(MessageType != uCentralProtocol::STATE &&
|
||||
MessageType != uCentralProtocol::HEALTHCHECK)) {
|
||||
BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
|
||||
return;
|
||||
return BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
|
||||
}
|
||||
|
||||
auto When = GetWhen(Obj);
|
||||
@@ -698,7 +681,7 @@ void RESTAPI_device_commandHandler::MakeRequest() {
|
||||
|
||||
Cmd.SerialNumber = SerialNumber_;
|
||||
Cmd.SubmittedBy = UserInfo_.webtoken.username_;
|
||||
Cmd.UUID = Daemon()->CreateUUID();
|
||||
Cmd.UUID = MicroService::CreateUUID();
|
||||
Cmd.Command = uCentralProtocol::REQUEST;
|
||||
Cmd.RunAt = When;
|
||||
|
||||
@@ -713,29 +696,28 @@ void RESTAPI_device_commandHandler::MakeRequest() {
|
||||
Params.stringify(ParamStream);
|
||||
Cmd.Details = ParamStream.str();
|
||||
|
||||
RESTAPI_RPC::WaitForCommand(Cmd, Params, *Request, *Response, 60000, nullptr, this, Logger_ );
|
||||
return;
|
||||
return RESTAPI_RPC::WaitForCommand(Cmd, Params, *Request, *Response, 60000, nullptr, this, Logger_ );
|
||||
}
|
||||
BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
|
||||
}
|
||||
|
||||
void RESTAPI_device_commandHandler::Rtty() {
|
||||
Logger_.information(Poco::format("RTTY: user=%s serial=%s", UserInfo_.userinfo.email,SerialNumber_));
|
||||
if (Daemon()->ConfigGetString("rtty.enabled", "false") == "true") {
|
||||
if (MicroService::instance().ConfigGetString("rtty.enabled", "false") == "true") {
|
||||
GWObjects::Device Device;
|
||||
if (Storage()->GetDevice(SerialNumber_, Device)) {
|
||||
auto CommandUUID = Daemon::instance()->CreateUUID();
|
||||
if (StorageService()->GetDevice(SerialNumber_, Device)) {
|
||||
auto CommandUUID = MicroService::CreateUUID();
|
||||
|
||||
GWObjects::RttySessionDetails Rtty{
|
||||
.SerialNumber = SerialNumber_,
|
||||
.Server = Daemon()->ConfigGetString("rtty.server", "localhost"),
|
||||
.Port = Daemon()->ConfigGetInt("rtty.port", 5912),
|
||||
.Token = Daemon()->ConfigGetString("rtty.token", "nothing"),
|
||||
.TimeOut = Daemon()->ConfigGetInt("rtty.timeout", 60),
|
||||
.Server = MicroService::instance().ConfigGetString("rtty.server", "localhost"),
|
||||
.Port = MicroService::instance().ConfigGetInt("rtty.port", 5912),
|
||||
.Token = MicroService::instance().ConfigGetString("rtty.token", "nothing"),
|
||||
.TimeOut = MicroService::instance().ConfigGetInt("rtty.timeout", 60),
|
||||
.ConnectionId = CommandUUID,
|
||||
.Started = (uint64_t)time(nullptr),
|
||||
.CommandUUID = CommandUUID,
|
||||
.ViewPort = Daemon()->ConfigGetInt("rtty.viewport", 5913),
|
||||
.ViewPort = MicroService::instance().ConfigGetInt("rtty.viewport", 5913),
|
||||
|
||||
};
|
||||
|
||||
@@ -764,11 +746,9 @@ void RESTAPI_device_commandHandler::MakeRequest() {
|
||||
std::stringstream ParamStream;
|
||||
Params.stringify(ParamStream);
|
||||
Cmd.Details = ParamStream.str();
|
||||
RESTAPI_RPC::WaitForCommand(Cmd, Params, *Request, *Response, 60000, &ReturnedObject, this, Logger_);
|
||||
return;
|
||||
return RESTAPI_RPC::WaitForCommand(Cmd, Params, *Request, *Response, 60000, &ReturnedObject, this, Logger_);
|
||||
}
|
||||
NotFound();
|
||||
return;
|
||||
return NotFound();
|
||||
}
|
||||
ReturnStatus(Poco::Net::HTTPResponse::HTTP_SERVICE_UNAVAILABLE);
|
||||
}
|
||||
@@ -782,19 +762,16 @@ void RESTAPI_device_commandHandler::MakeRequest() {
|
||||
|
||||
auto SNum = Obj->get(RESTAPI::Protocol::SERIALNUMBER).toString();
|
||||
if (SerialNumber_ != SNum) {
|
||||
BadRequest(RESTAPI::Errors::SerialNumberMismatch);
|
||||
return;
|
||||
return BadRequest(RESTAPI::Errors::SerialNumberMismatch);
|
||||
}
|
||||
|
||||
GWObjects::Device Device;
|
||||
if (!Storage()->GetDevice(SerialNumber_, Device)) {
|
||||
NotFound();
|
||||
return;
|
||||
if (!StorageService()->GetDevice(SerialNumber_, Device)) {
|
||||
return NotFound();
|
||||
}
|
||||
|
||||
if (!DeviceRegistry()->Connected(SerialNumber_)) {
|
||||
BadRequest(RESTAPI::Errors::DeviceNotConnected);
|
||||
return;
|
||||
return BadRequest(RESTAPI::Errors::DeviceNotConnected);
|
||||
}
|
||||
|
||||
auto Interval = Obj->get(RESTAPI::Protocol::INTERVAL);
|
||||
@@ -823,8 +800,7 @@ void RESTAPI_device_commandHandler::MakeRequest() {
|
||||
Answer.set("uri", Endpoint);
|
||||
}
|
||||
} else {
|
||||
BadRequest(RESTAPI::Errors::CannotCreateWS);
|
||||
return;
|
||||
return BadRequest(RESTAPI::Errors::CannotCreateWS);
|
||||
}
|
||||
|
||||
Cmd.UUID = NewUUID;
|
||||
@@ -832,9 +808,8 @@ void RESTAPI_device_commandHandler::MakeRequest() {
|
||||
Params.stringify(ParamStream);
|
||||
Cmd.Details = ParamStream.str();
|
||||
|
||||
RESTAPI_RPC::WaitForCommand(Cmd, Params, *Request, *Response,
|
||||
return RESTAPI_RPC::WaitForCommand(Cmd, Params, *Request, *Response,
|
||||
60000, &Answer, this, Logger_);
|
||||
return;
|
||||
}
|
||||
BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
|
||||
}
|
||||
@@ -9,8 +9,8 @@
|
||||
#ifndef UCENTRAL_RESTAPI_DEVICECOMMANDHANDLER_H
|
||||
#define UCENTRAL_RESTAPI_DEVICECOMMANDHANDLER_H
|
||||
|
||||
#include "RESTAPI_handler.h"
|
||||
#include "RESTAPI_protocol.h"
|
||||
#include "framework/MicroService.h"
|
||||
#include "framework/RESTAPI_protocol.h"
|
||||
|
||||
namespace OpenWifi {
|
||||
class RESTAPI_device_commandHandler : public RESTAPIHandler {
|
||||
@@ -7,31 +7,29 @@
|
||||
//
|
||||
|
||||
#include "RESTAPI_device_handler.h"
|
||||
#include "Poco/JSON/Parser.h"
|
||||
#include "RESTAPI_protocol.h"
|
||||
#include "StorageService.h"
|
||||
#include "Utils.h"
|
||||
#include "ConfigurationValidator.h"
|
||||
#include "ConfigurationCache.h"
|
||||
#include "CentralConfig.h"
|
||||
#include "RESTAPI_errors.h"
|
||||
#include "ConfigurationCache.h"
|
||||
#include "Poco/JSON/Parser.h"
|
||||
#include "StorageService.h"
|
||||
#include "framework/ConfigurationValidator.h"
|
||||
#include "framework/MicroService.h"
|
||||
#include "framework/RESTAPI_errors.h"
|
||||
#include "framework/RESTAPI_protocol.h"
|
||||
|
||||
namespace OpenWifi {
|
||||
void RESTAPI_device_handler::DoGet() {
|
||||
std::string SerialNumber = GetBinding(RESTAPI::Protocol::SERIALNUMBER, "");
|
||||
|
||||
if(SerialNumber.empty()) {
|
||||
BadRequest(RESTAPI::Errors::MissingSerialNumber);
|
||||
return;
|
||||
return BadRequest(RESTAPI::Errors::MissingSerialNumber);
|
||||
}
|
||||
|
||||
GWObjects::Device Device;
|
||||
|
||||
if (Storage()->GetDevice(SerialNumber, Device)) {
|
||||
if (StorageService()->GetDevice(SerialNumber, Device)) {
|
||||
Poco::JSON::Object Obj;
|
||||
Device.to_json(Obj);
|
||||
ReturnObject(Obj);
|
||||
return;
|
||||
return ReturnObject(Obj);
|
||||
}
|
||||
NotFound();
|
||||
}
|
||||
@@ -40,14 +38,43 @@ namespace OpenWifi {
|
||||
std::string SerialNumber = GetBinding(RESTAPI::Protocol::SERIALNUMBER, "");
|
||||
|
||||
if(SerialNumber.empty()) {
|
||||
BadRequest(RESTAPI::Errors::MissingSerialNumber);
|
||||
return;
|
||||
return BadRequest(RESTAPI::Errors::MissingSerialNumber);
|
||||
}
|
||||
|
||||
if (Storage()->DeleteDevice(SerialNumber)) {
|
||||
OK();
|
||||
return;
|
||||
std::string Arg;
|
||||
if(HasParameter("oui",Arg) && Arg=="true" && SerialNumber.size()==6) {
|
||||
|
||||
std::set<std::string> Set;
|
||||
std::vector<GWObjects::Device> Devices;
|
||||
|
||||
bool Done = false;
|
||||
uint64_t Offset=1;
|
||||
while(!Done) {
|
||||
|
||||
StorageService()->GetDevices(Offset,500,Devices);
|
||||
for(const auto &i:Devices) {
|
||||
if(i.SerialNumber.substr(0,6) == SerialNumber) {
|
||||
Set.insert(i.SerialNumber);
|
||||
}
|
||||
}
|
||||
|
||||
if(Devices.size()<500)
|
||||
Done=true;
|
||||
|
||||
Offset += Devices.size();
|
||||
}
|
||||
|
||||
for(auto &i:Set) {
|
||||
std::string SNum{i};
|
||||
StorageService()->DeleteDevice(SNum);
|
||||
}
|
||||
|
||||
return OK();
|
||||
|
||||
} else if (StorageService()->DeleteDevice(SerialNumber)) {
|
||||
return OK();
|
||||
}
|
||||
|
||||
NotFound();
|
||||
}
|
||||
|
||||
@@ -55,46 +82,43 @@ namespace OpenWifi {
|
||||
|
||||
std::string SerialNumber = GetBinding(RESTAPI::Protocol::SERIALNUMBER, "");
|
||||
if(SerialNumber.empty()) {
|
||||
BadRequest(RESTAPI::Errors::MissingSerialNumber);
|
||||
return;
|
||||
return BadRequest(RESTAPI::Errors::MissingSerialNumber);
|
||||
}
|
||||
|
||||
std::string Arg;
|
||||
if(HasParameter("validateOnly",Arg) && Arg=="true") {
|
||||
auto Body = ParseStream();
|
||||
if(!Body->has("configuration")) {
|
||||
BadRequest("Must have 'configuration' element.");
|
||||
return;
|
||||
return BadRequest("Must have 'configuration' element.");
|
||||
}
|
||||
auto Config=Body->get("configuration").toString();
|
||||
Poco::JSON::Object Answer;
|
||||
auto Res = ValidateUCentralConfiguration(Config);
|
||||
std::string Error;
|
||||
auto Res = ValidateUCentralConfiguration(Config, Error);
|
||||
Answer.set("valid",Res);
|
||||
ReturnObject(Answer);
|
||||
return;
|
||||
if(!Error.empty())
|
||||
Answer.set("error",Error);
|
||||
return ReturnObject(Answer);
|
||||
}
|
||||
|
||||
if (!Utils::ValidSerialNumber(SerialNumber)) {
|
||||
Logger_.warning(Poco::format("CREATE-DEVICE(%s): Illegal serial number.", SerialNumber));
|
||||
BadRequest( RESTAPI::Errors::InvalidSerialNumber);
|
||||
return;
|
||||
return BadRequest( RESTAPI::Errors::InvalidSerialNumber);
|
||||
}
|
||||
|
||||
auto Obj = ParseStream();
|
||||
GWObjects::Device Device;
|
||||
if (!Device.from_json(Obj)) {
|
||||
BadRequest(RESTAPI::Errors::InvalidJSONDocument);
|
||||
return;
|
||||
return BadRequest(RESTAPI::Errors::InvalidJSONDocument);
|
||||
}
|
||||
|
||||
if(SerialNumber!=Device.SerialNumber) {
|
||||
BadRequest(RESTAPI::Errors::SerialNumberMismatch);
|
||||
return;
|
||||
return BadRequest(RESTAPI::Errors::SerialNumberMismatch);
|
||||
}
|
||||
|
||||
if(Device.Configuration.empty() || (!Device.Configuration.empty() && !ValidateUCentralConfiguration(Device.Configuration))) {
|
||||
BadRequest(RESTAPI::Errors::ConfigBlockInvalid);
|
||||
return;
|
||||
std::string Error;
|
||||
if(Device.Configuration.empty() || (!Device.Configuration.empty() && !ValidateUCentralConfiguration(Device.Configuration,Error))) {
|
||||
return BadRequest(RESTAPI::Errors::ConfigBlockInvalid);
|
||||
}
|
||||
|
||||
for(auto &i:Device.Notes)
|
||||
@@ -107,12 +131,11 @@ namespace OpenWifi {
|
||||
|
||||
Poco::toLowerInPlace(Device.SerialNumber);
|
||||
|
||||
if (Storage()->CreateDevice(Device)) {
|
||||
if (StorageService()->CreateDevice(Device)) {
|
||||
SetCurrentConfigurationID(SerialNumber, Device.UUID);
|
||||
Poco::JSON::Object DevObj;
|
||||
Device.to_json(DevObj);
|
||||
ReturnObject(DevObj);
|
||||
return;
|
||||
return ReturnObject(DevObj);
|
||||
}
|
||||
InternalError(RESTAPI::Errors::RecordNotCreated);
|
||||
}
|
||||
@@ -121,27 +144,24 @@ namespace OpenWifi {
|
||||
std::string SerialNumber = GetBinding(RESTAPI::Protocol::SERIALNUMBER, "");
|
||||
|
||||
if(SerialNumber.empty()) {
|
||||
BadRequest(RESTAPI::Errors::MissingSerialNumber);
|
||||
return;
|
||||
return BadRequest(RESTAPI::Errors::MissingSerialNumber);
|
||||
}
|
||||
|
||||
auto Obj = ParseStream();
|
||||
GWObjects::Device NewDevice;
|
||||
if (!NewDevice.from_json(Obj)) {
|
||||
BadRequest(RESTAPI::Errors::InvalidJSONDocument);
|
||||
return;
|
||||
return BadRequest(RESTAPI::Errors::InvalidJSONDocument);
|
||||
}
|
||||
|
||||
GWObjects::Device Existing;
|
||||
if(!Storage()->GetDevice(SerialNumber, Existing)) {
|
||||
NotFound();
|
||||
return;
|
||||
if(!StorageService()->GetDevice(SerialNumber, Existing)) {
|
||||
return NotFound();
|
||||
}
|
||||
|
||||
if(!NewDevice.Configuration.empty()) {
|
||||
if (!ValidateUCentralConfiguration(NewDevice.Configuration)) {
|
||||
BadRequest(RESTAPI::Errors::ConfigBlockInvalid);
|
||||
return;
|
||||
std::string Error;
|
||||
if (!ValidateUCentralConfiguration(NewDevice.Configuration, Error)) {
|
||||
return BadRequest(RESTAPI::Errors::ConfigBlockInvalid);
|
||||
}
|
||||
Config::Config NewConfig(NewDevice.Configuration);
|
||||
uint64_t NewConfigUUID = std::time(nullptr);
|
||||
@@ -160,12 +180,11 @@ namespace OpenWifi {
|
||||
}
|
||||
|
||||
Existing.LastConfigurationChange = std::time(nullptr);
|
||||
if (Storage()->UpdateDevice(Existing)) {
|
||||
if (StorageService()->UpdateDevice(Existing)) {
|
||||
SetCurrentConfigurationID(SerialNumber, Existing.UUID);
|
||||
Poco::JSON::Object DevObj;
|
||||
NewDevice.to_json(DevObj);
|
||||
ReturnObject(DevObj);
|
||||
return;
|
||||
return ReturnObject(DevObj);
|
||||
}
|
||||
InternalError(RESTAPI::Errors::RecordNotUpdated);
|
||||
}
|
||||
@@ -9,9 +9,9 @@
|
||||
#ifndef UCENTRAL_RESTAPI_DEVICEHANDLER_H
|
||||
#define UCENTRAL_RESTAPI_DEVICEHANDLER_H
|
||||
|
||||
#include "RESTAPI_handler.h"
|
||||
#include "Poco/Net/HTTPServerRequest.h"
|
||||
#include "Poco/Net/HTTPServerResponse.h"
|
||||
#include "framework/MicroService.h"
|
||||
|
||||
namespace OpenWifi {
|
||||
class RESTAPI_device_handler : public RESTAPIHandler {
|
||||
@@ -10,11 +10,9 @@
|
||||
#include "Poco/JSON/Stringifier.h"
|
||||
|
||||
#include "RESTAPI_devices_handler.h"
|
||||
#include "RESTAPI_protocol.h"
|
||||
#include "StorageService.h"
|
||||
#include "Utils.h"
|
||||
|
||||
#include "Utils.h"
|
||||
#include "framework/RESTAPI_protocol.h"
|
||||
#include "framework/MicroService.h"
|
||||
|
||||
namespace OpenWifi {
|
||||
void RESTAPI_devices_handler::DoGet() {
|
||||
@@ -28,7 +26,7 @@ namespace OpenWifi {
|
||||
std::vector<std::string> Numbers = Utils::Split(QB_.Select);
|
||||
for (auto &i : Numbers) {
|
||||
GWObjects::Device D;
|
||||
if (Storage()->GetDevice(i, D)) {
|
||||
if (StorageService()->GetDevice(i, D)) {
|
||||
Poco::JSON::Object Obj;
|
||||
if (deviceWithStatus)
|
||||
D.to_json_with_status(Obj);
|
||||
@@ -47,13 +45,12 @@ namespace OpenWifi {
|
||||
|
||||
} else if (QB_.CountOnly == true) {
|
||||
uint64_t Count = 0;
|
||||
if (Storage()->GetDeviceCount(Count)) {
|
||||
ReturnCountOnly(Count);
|
||||
return;
|
||||
if (StorageService()->GetDeviceCount(Count)) {
|
||||
return ReturnCountOnly(Count);
|
||||
}
|
||||
} else if (serialOnly) {
|
||||
std::vector<std::string> SerialNumbers;
|
||||
Storage()->GetDeviceSerialNumbers(QB_.Offset, QB_.Limit, SerialNumbers);
|
||||
StorageService()->GetDeviceSerialNumbers(QB_.Offset, QB_.Limit, SerialNumbers);
|
||||
Poco::JSON::Array Objects;
|
||||
for (const auto &i : SerialNumbers) {
|
||||
Objects.add(i);
|
||||
@@ -61,7 +58,7 @@ namespace OpenWifi {
|
||||
RetObj.set(RESTAPI::Protocol::SERIALNUMBERS, Objects);
|
||||
} else {
|
||||
std::vector<GWObjects::Device> Devices;
|
||||
Storage()->GetDevices(QB_.Offset, QB_.Limit, Devices);
|
||||
StorageService()->GetDevices(QB_.Offset, QB_.Limit, Devices);
|
||||
Poco::JSON::Array Objects;
|
||||
for (const auto &i : Devices) {
|
||||
Poco::JSON::Object Obj;
|
||||
@@ -9,7 +9,7 @@
|
||||
#ifndef UCENTRAL_RESTAPI_DEVICESHANDLER_H
|
||||
#define UCENTRAL_RESTAPI_DEVICESHANDLER_H
|
||||
|
||||
#include "RESTAPI_handler.h"
|
||||
#include "framework/MicroService.h"
|
||||
|
||||
namespace OpenWifi {
|
||||
class RESTAPI_devices_handler : public RESTAPIHandler {
|
||||
@@ -12,9 +12,9 @@
|
||||
#include "Poco/File.h"
|
||||
#include "StorageService.h"
|
||||
|
||||
#include "framework/RESTAPI_errors.h"
|
||||
#include "framework/RESTAPI_protocol.h"
|
||||
#include <fstream>
|
||||
#include "RESTAPI_protocol.h"
|
||||
#include "RESTAPI_errors.h"
|
||||
|
||||
namespace OpenWifi {
|
||||
void RESTAPI_file::DoGet() {
|
||||
@@ -25,9 +25,8 @@ namespace OpenWifi {
|
||||
Poco::File DownloadFile(FileUploader()->Path() + "/" + UUID);
|
||||
|
||||
std::string FileType;
|
||||
if (!Storage()->GetAttachedFile(UUID, SerialNumber, DownloadFile.path(), FileType)) {
|
||||
NotFound();
|
||||
return;
|
||||
if (!StorageService()->GetAttachedFile(UUID, SerialNumber, DownloadFile.path(), FileType)) {
|
||||
return NotFound();
|
||||
}
|
||||
SendFile(DownloadFile, UUID);
|
||||
DownloadFile.remove();
|
||||
@@ -37,13 +36,11 @@ namespace OpenWifi {
|
||||
auto UUID = GetBinding(RESTAPI::Protocol::FILEUUID, "");
|
||||
|
||||
if (UUID.empty()) {
|
||||
BadRequest(RESTAPI::Errors::MissingUUID);
|
||||
return;
|
||||
return BadRequest(RESTAPI::Errors::MissingUUID);
|
||||
}
|
||||
|
||||
if (Storage()->RemoveAttachedFile(UUID)) {
|
||||
OK();
|
||||
return;
|
||||
if (StorageService()->RemoveAttachedFile(UUID)) {
|
||||
return OK();
|
||||
}
|
||||
BadRequest(RESTAPI::Errors::CouldNotBeDeleted);
|
||||
}
|
||||
@@ -9,7 +9,7 @@
|
||||
#ifndef UCENTRAL_RESTAPI_FILE_H
|
||||
#define UCENTRAL_RESTAPI_FILE_H
|
||||
|
||||
#include "RESTAPI_handler.h"
|
||||
#include "framework/MicroService.h"
|
||||
|
||||
namespace OpenWifi {
|
||||
class RESTAPI_file : public RESTAPIHandler {
|
||||
@@ -3,8 +3,6 @@
|
||||
//
|
||||
|
||||
#include "RESTAPI_ouis.h"
|
||||
#include "RESTAPI_protocol.h"
|
||||
#include "Utils.h"
|
||||
#include "OUIServer.h"
|
||||
|
||||
namespace OpenWifi {
|
||||
@@ -5,7 +5,7 @@
|
||||
#ifndef UCENTRALGW_RESTAPI_OUIS_H
|
||||
#define UCENTRALGW_RESTAPI_OUIS_H
|
||||
|
||||
#include "RESTAPI_handler.h"
|
||||
#include "framework/MicroService.h"
|
||||
|
||||
namespace OpenWifi {
|
||||
class RESTAPI_ouis : public RESTAPIHandler {
|
||||
@@ -2,17 +2,15 @@
|
||||
// Created by stephane bourque on 2021-08-12.
|
||||
//
|
||||
|
||||
#include "RESTAPI_webSocketServer.h"
|
||||
#include "Poco/Net/WebSocket.h"
|
||||
#include "Poco/Net/NetException.h"
|
||||
#include "Poco/Net/HTTPResponse.h"
|
||||
#include "Poco/JSON/Object.h"
|
||||
#include "Poco/JSON/Parser.h"
|
||||
#include "Poco/JSON/Stringifier.h"
|
||||
|
||||
#include "RESTAPI_webSocketServer.h"
|
||||
#include "SerialNumberCache.h"
|
||||
|
||||
#include "Utils.h"
|
||||
#include "AuthClient.h"
|
||||
#include "framework/MicroService.h"
|
||||
|
||||
namespace OpenWifi {
|
||||
|
||||
@@ -48,7 +46,8 @@ namespace OpenWifi {
|
||||
if(!Authenticated) {
|
||||
std::string Frame{IncomingFrame.begin()};
|
||||
auto Tokens = Utils::Split(Frame,':');
|
||||
if(Tokens.size()==2 && AuthClient()->IsTokenAuthorized(Tokens[1], UserInfo_)) {
|
||||
bool Expired=false;
|
||||
if(Tokens.size()==2 && AuthClient()->IsAuthorized(Tokens[1], UserInfo_, Expired)) {
|
||||
Authenticated=true;
|
||||
std::string S{"Welcome! Bienvenue! Bienvenidos!"};
|
||||
WS.sendFrame(S.c_str(),S.size());
|
||||
@@ -76,6 +75,12 @@ namespace OpenWifi {
|
||||
}
|
||||
}
|
||||
break;
|
||||
case Poco::Net::WebSocket::FRAME_OP_CLOSE: {
|
||||
Logger_.warning(Poco::format("CLOSE(%s): Client is closing its WS connection.", UserInfo_.userinfo.email));
|
||||
Done=true;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
{
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
#ifndef UCENTRALGW_RESTAPI_WEBSOCKETSERVER_H
|
||||
#define UCENTRALGW_RESTAPI_WEBSOCKETSERVER_H
|
||||
|
||||
#include "RESTAPI_handler.h"
|
||||
#include "framework/MicroService.h"
|
||||
|
||||
namespace OpenWifi {
|
||||
class RESTAPI_webSocketServer : public RESTAPIHandler {
|
||||
@@ -1,89 +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 <ctime>
|
||||
|
||||
#include "Poco/JSON/Parser.h"
|
||||
#include "Poco/JSON/Stringifier.h"
|
||||
#include "RESTAPI_BlackList.h"
|
||||
#include "RESTAPI_protocol.h"
|
||||
#include "StorageService.h"
|
||||
#include "RESTAPI_errors.h"
|
||||
|
||||
namespace OpenWifi {
|
||||
|
||||
void RESTAPI_BlackList::DoDelete() {
|
||||
auto SerialNumber = GetBinding(RESTAPI::Protocol::SERIALNUMBER, "");
|
||||
|
||||
if(SerialNumber.empty()) {
|
||||
BadRequest(RESTAPI::Errors::MissingSerialNumber);
|
||||
return;
|
||||
}
|
||||
|
||||
GWObjects::BlackListedDevice D;
|
||||
if(!Storage()->GetBlackListDevice(SerialNumber, D)) {
|
||||
NotFound();
|
||||
return;
|
||||
}
|
||||
|
||||
if (Storage()->DeleteBlackListDevice(SerialNumber)) {
|
||||
OK();
|
||||
return;
|
||||
}
|
||||
BadRequest(RESTAPI::Errors::CouldNotBeDeleted);
|
||||
}
|
||||
|
||||
void RESTAPI_BlackList::DoGet() {
|
||||
std::vector<GWObjects::BlackListedDevice> Devices;
|
||||
Poco::JSON::Array Objects;
|
||||
if (Storage()->GetBlackListDevices(QB_.Offset, QB_.Limit, Devices)) {
|
||||
for (const auto &i : Devices) {
|
||||
Poco::JSON::Object Obj;
|
||||
i.to_json(Obj);
|
||||
Objects.add(Obj);
|
||||
}
|
||||
}
|
||||
Poco::JSON::Object RetObj;
|
||||
RetObj.set(RESTAPI::Protocol::DEVICES, Objects);
|
||||
ReturnObject(RetObj);
|
||||
}
|
||||
|
||||
void RESTAPI_BlackList::DoPost() {
|
||||
auto Obj = ParseStream();
|
||||
if (Obj->has(RESTAPI::Protocol::DEVICES) &&
|
||||
Obj->isArray(RESTAPI::Protocol::DEVICES)) {
|
||||
std::vector<GWObjects::BlackListedDevice> 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(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_,
|
||||
.Created = (uint64_t)time(nullptr)};
|
||||
Devices.push_back(D);
|
||||
}
|
||||
}
|
||||
if (!Devices.empty()) {
|
||||
if (Storage()->AddBlackListDevices(Devices)) {
|
||||
OK();
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
|
||||
}
|
||||
} else {
|
||||
BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
//
|
||||
// Created by stephane bourque on 2021-09-15.
|
||||
//
|
||||
|
||||
#include "RESTAPI_GenericServer.h"
|
||||
@@ -1,78 +0,0 @@
|
||||
//
|
||||
// Created by stephane bourque on 2021-09-15.
|
||||
//
|
||||
|
||||
#ifndef OWPROV_RESTAPI_GENERICSERVER_H
|
||||
#define OWPROV_RESTAPI_GENERICSERVER_H
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
#include "Daemon.h"
|
||||
#include "Poco/StringTokenizer.h"
|
||||
#include "Poco/Net/HTTPRequest.h"
|
||||
|
||||
namespace OpenWifi {
|
||||
|
||||
class RESTAPI_GenericServer {
|
||||
public:
|
||||
|
||||
enum {
|
||||
LOG_GET=0,
|
||||
LOG_DELETE,
|
||||
LOG_PUT,
|
||||
LOG_POST
|
||||
};
|
||||
|
||||
void inline SetFlags(bool External, const std::string &Methods) {
|
||||
Poco::StringTokenizer Tokens(Methods,",");
|
||||
auto Offset = (External ? 0 : 4);
|
||||
for(const auto &i:Tokens) {
|
||||
if(Poco::icompare(i,Poco::Net::HTTPRequest::HTTP_DELETE)==0)
|
||||
LogFlags_[Offset+LOG_DELETE]=true;
|
||||
else if(Poco::icompare(i,Poco::Net::HTTPRequest::HTTP_PUT)==0)
|
||||
LogFlags_[Offset+LOG_PUT]=true;
|
||||
else if(Poco::icompare(i,Poco::Net::HTTPRequest::HTTP_POST)==0)
|
||||
LogFlags_[Offset+LOG_POST]=true;
|
||||
else if(Poco::icompare(i,Poco::Net::HTTPRequest::HTTP_GET)==0)
|
||||
LogFlags_[Offset+LOG_GET]=true;
|
||||
}
|
||||
}
|
||||
inline void InitLogging() {
|
||||
std::string Public = Daemon()->ConfigGetString("apilogging.public.methods","PUT,POST,DELETE");
|
||||
SetFlags(true, Public);
|
||||
std::string Private = Daemon()->ConfigGetString("apilogging.private.methods","PUT,POST,DELETE");
|
||||
SetFlags(false, Private);
|
||||
|
||||
std::string PublicBadTokens = Daemon()->ConfigGetString("apilogging.public.badtokens.methods","");
|
||||
LogBadTokens_[0] = (Poco::icompare(PublicBadTokens,"true")==0);
|
||||
std::string PrivateBadTokens = Daemon()->ConfigGetString("apilogging.private.badtokens.methods","");
|
||||
LogBadTokens_[1] = (Poco::icompare(PrivateBadTokens,"true")==0);
|
||||
}
|
||||
|
||||
[[nodiscard]] inline bool LogIt(const std::string &Method, bool External) const {
|
||||
auto Offset = (External ? 0 : 4);
|
||||
if(Method == Poco::Net::HTTPRequest::HTTP_GET)
|
||||
return LogFlags_[Offset+LOG_GET];
|
||||
if(Method == Poco::Net::HTTPRequest::HTTP_POST)
|
||||
return LogFlags_[Offset+LOG_POST];
|
||||
if(Method == Poco::Net::HTTPRequest::HTTP_PUT)
|
||||
return LogFlags_[Offset+LOG_PUT];
|
||||
if(Method == Poco::Net::HTTPRequest::HTTP_DELETE)
|
||||
return LogFlags_[Offset+LOG_DELETE];
|
||||
return false;
|
||||
};
|
||||
|
||||
[[nodiscard]] inline bool LogBadTokens(bool External) const {
|
||||
return LogBadTokens_[ (External ? 0 : 1) ];
|
||||
};
|
||||
|
||||
private:
|
||||
std::array<bool,8> LogFlags_{false};
|
||||
std::array<bool,2> LogBadTokens_{false};
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif //OWPROV_RESTAPI_GENERICSERVER_H
|
||||
@@ -1,82 +0,0 @@
|
||||
//
|
||||
// Created by stephane bourque on 2021-06-29.
|
||||
//
|
||||
|
||||
#include "RESTAPI_InternalServer.h"
|
||||
|
||||
#include "Poco/URI.h"
|
||||
|
||||
#include "RESTAPI_BlackList.h"
|
||||
#include "RESTAPI_command.h"
|
||||
#include "RESTAPI_commands.h"
|
||||
#include "RESTAPI_default_configuration.h"
|
||||
#include "RESTAPI_default_configurations.h"
|
||||
#include "RESTAPI_device_commandHandler.h"
|
||||
#include "RESTAPI_device_handler.h"
|
||||
#include "RESTAPI_devices_handler.h"
|
||||
#include "RESTAPI_file.h"
|
||||
#include "RESTAPI_ouis.h"
|
||||
#include "Utils.h"
|
||||
|
||||
namespace OpenWifi {
|
||||
|
||||
class RESTAPI_InternalServer *RESTAPI_InternalServer::instance_ = nullptr;
|
||||
|
||||
int RESTAPI_InternalServer::Start() {
|
||||
Logger_.information("Starting.");
|
||||
Server_.InitLogging();
|
||||
|
||||
for(const auto & Svr: ConfigServersList_) {
|
||||
Logger_.information(Poco::format("Starting: %s:%s Keyfile:%s CertFile: %s", Svr.Address(), std::to_string(Svr.Port()),
|
||||
Svr.KeyFile(),Svr.CertFile()));
|
||||
|
||||
auto Sock{Svr.CreateSecureSocket(Logger_)};
|
||||
|
||||
Svr.LogCert(Logger_);
|
||||
if(!Svr.RootCA().empty())
|
||||
Svr.LogCas(Logger_);
|
||||
auto Params = new Poco::Net::HTTPServerParams;
|
||||
Params->setMaxThreads(50);
|
||||
Params->setMaxQueued(200);
|
||||
Params->setKeepAlive(true);
|
||||
|
||||
auto NewServer = std::make_unique<Poco::Net::HTTPServer>(new InternalRequestHandlerFactory(Server_), Pool_, Sock, Params);
|
||||
NewServer->start();
|
||||
RESTServers_.push_back(std::move(NewServer));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void RESTAPI_InternalServer::Stop() {
|
||||
Logger_.information("Stopping ");
|
||||
for( const auto & svr : RESTServers_ )
|
||||
svr->stop();
|
||||
RESTServers_.clear();
|
||||
}
|
||||
|
||||
void RESTAPI_InternalServer::reinitialize(Poco::Util::Application &self) {
|
||||
Daemon()->LoadConfigurationFile();
|
||||
Logger_.information("Reinitializing.");
|
||||
Stop();
|
||||
Start();
|
||||
}
|
||||
|
||||
Poco::Net::HTTPRequestHandler *InternalRequestHandlerFactory::createRequestHandler(const Poco::Net::HTTPServerRequest & Request) {
|
||||
Poco::URI uri(Request.getURI());
|
||||
const auto & Path = uri.getPath();
|
||||
RESTAPIHandler::BindingMap Bindings;
|
||||
|
||||
return RESTAPI_Router_I<
|
||||
RESTAPI_devices_handler,
|
||||
RESTAPI_device_handler,
|
||||
RESTAPI_device_commandHandler,
|
||||
RESTAPI_default_configurations,
|
||||
RESTAPI_default_configuration,
|
||||
RESTAPI_command,
|
||||
RESTAPI_commands,
|
||||
RESTAPI_ouis,
|
||||
RESTAPI_file,
|
||||
RESTAPI_BlackList>(Path,Bindings,Logger_, Server_); }
|
||||
|
||||
}
|
||||
@@ -1,62 +0,0 @@
|
||||
//
|
||||
// Created by stephane bourque on 2021-06-29.
|
||||
//
|
||||
|
||||
#ifndef UCENTRALSEC_RESTAPI_INTERNALSERVER_H
|
||||
#define UCENTRALSEC_RESTAPI_INTERNALSERVER_H
|
||||
|
||||
#include "SubSystemServer.h"
|
||||
#include "Poco/Net/HTTPServer.h"
|
||||
#include "Poco/Net/HTTPRequestHandler.h"
|
||||
#include "Poco/Net/HTTPRequestHandlerFactory.h"
|
||||
#include "Poco/Net/HTTPServerRequest.h"
|
||||
#include "Poco/Net/NetException.h"
|
||||
#include "RESTAPI_GenericServer.h"
|
||||
|
||||
namespace OpenWifi {
|
||||
|
||||
class RESTAPI_InternalServer : public SubSystemServer {
|
||||
|
||||
public:
|
||||
|
||||
static RESTAPI_InternalServer *instance() {
|
||||
if (instance_ == nullptr) {
|
||||
instance_ = new RESTAPI_InternalServer;
|
||||
}
|
||||
return instance_;
|
||||
}
|
||||
|
||||
int Start() override;
|
||||
void Stop() override;
|
||||
void reinitialize(Poco::Util::Application &self) override;
|
||||
|
||||
private:
|
||||
static RESTAPI_InternalServer *instance_;
|
||||
std::vector<std::unique_ptr<Poco::Net::HTTPServer>> RESTServers_;
|
||||
Poco::ThreadPool Pool_;
|
||||
RESTAPI_GenericServer Server_;
|
||||
|
||||
RESTAPI_InternalServer() noexcept: SubSystemServer("RESTAPIInternalServer", "REST-ISRV", "openwifi.internal.restapi")
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
inline RESTAPI_InternalServer * RESTAPI_InternalServer() { return RESTAPI_InternalServer::instance(); };
|
||||
|
||||
class InternalRequestHandlerFactory : public Poco::Net::HTTPRequestHandlerFactory {
|
||||
public:
|
||||
explicit InternalRequestHandlerFactory(RESTAPI_GenericServer & Server) :
|
||||
Logger_(RESTAPI_InternalServer()->Logger()),
|
||||
Server_(Server)
|
||||
{}
|
||||
|
||||
Poco::Net::HTTPRequestHandler *createRequestHandler(const Poco::Net::HTTPServerRequest &request) override;
|
||||
private:
|
||||
Poco::Logger & Logger_;
|
||||
RESTAPI_GenericServer & Server_;
|
||||
};
|
||||
|
||||
|
||||
} // namespace
|
||||
|
||||
#endif //UCENTRALSEC_RESTAPI_INTERNALSERVER_H
|
||||
@@ -1,479 +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 <cctype>
|
||||
#include <algorithm>
|
||||
#include <functional>
|
||||
#include <iostream>
|
||||
#include <iterator>
|
||||
#include <future>
|
||||
#include <chrono>
|
||||
|
||||
#include "Poco/URI.h"
|
||||
#include "Poco/Net/OAuth20Credentials.h"
|
||||
|
||||
#include "RESTAPI_errors.h"
|
||||
|
||||
#ifdef TIP_SECURITY_SERVICE
|
||||
#include "AuthService.h"
|
||||
#else
|
||||
#include "AuthClient.h"
|
||||
#endif
|
||||
|
||||
#include "RESTAPI_handler.h"
|
||||
#include "RESTAPI_protocol.h"
|
||||
#include "Utils.h"
|
||||
#include "Daemon.h"
|
||||
|
||||
namespace OpenWifi {
|
||||
|
||||
void RESTAPIHandler::handleRequest(Poco::Net::HTTPServerRequest &RequestIn,
|
||||
Poco::Net::HTTPServerResponse &ResponseIn) {
|
||||
try {
|
||||
Request = &RequestIn;
|
||||
Response = &ResponseIn;
|
||||
|
||||
if (!ContinueProcessing())
|
||||
return;
|
||||
|
||||
if (AlwaysAuthorize_ && !IsAuthorized())
|
||||
return;
|
||||
|
||||
ParseParameters();
|
||||
if (Request->getMethod() == Poco::Net::HTTPRequest::HTTP_GET)
|
||||
DoGet();
|
||||
else if (Request->getMethod() == Poco::Net::HTTPRequest::HTTP_POST)
|
||||
DoPost();
|
||||
else if (Request->getMethod() == Poco::Net::HTTPRequest::HTTP_DELETE)
|
||||
DoDelete();
|
||||
else if (Request->getMethod() == Poco::Net::HTTPRequest::HTTP_PUT)
|
||||
DoPut();
|
||||
else
|
||||
BadRequest(RESTAPI::Errors::UnsupportedHTTPMethod);
|
||||
return;
|
||||
} catch (const Poco::Exception &E) {
|
||||
Logger_.log(E);
|
||||
BadRequest(RESTAPI::Errors::InternalError);
|
||||
}
|
||||
}
|
||||
|
||||
const Poco::JSON::Object::Ptr &RESTAPIHandler::ParseStream() {
|
||||
return IncomingParser_.parse(Request->stream()).extract<Poco::JSON::Object::Ptr>();
|
||||
}
|
||||
|
||||
bool RESTAPIHandler::ParseBindings(const std::string & Request, const std::list<const char *> & EndPoints, BindingMap &bindings) {
|
||||
bindings.clear();
|
||||
std::vector<std::string> PathItems = Utils::Split(Request, '/');
|
||||
|
||||
for(const auto &EndPoint:EndPoints) {
|
||||
std::vector<std::string> ParamItems = Utils::Split(EndPoint, '/');
|
||||
if (PathItems.size() != ParamItems.size())
|
||||
continue;
|
||||
|
||||
bool Matched = true;
|
||||
for (auto i = 0; i != PathItems.size() && Matched; i++) {
|
||||
if (PathItems[i] != ParamItems[i]) {
|
||||
if (ParamItems[i][0] == '{') {
|
||||
auto ParamName = ParamItems[i].substr(1, ParamItems[i].size() - 2);
|
||||
bindings[Poco::toLower(ParamName)] = PathItems[i];
|
||||
} else {
|
||||
Matched = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(Matched)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void RESTAPIHandler::PrintBindings() {
|
||||
for (const auto &[key, value] : Bindings_)
|
||||
std::cout << "Key = " << key << " Value= " << value << std::endl;
|
||||
}
|
||||
|
||||
void RESTAPIHandler::ParseParameters() {
|
||||
Poco::URI uri(Request->getURI());
|
||||
Parameters_ = uri.getQueryParameters();
|
||||
InitQueryBlock();
|
||||
}
|
||||
|
||||
static bool is_number(const std::string &s) {
|
||||
return !s.empty() && std::all_of(s.begin(), s.end(), ::isdigit);
|
||||
}
|
||||
|
||||
static bool is_bool(const std::string &s) {
|
||||
if (s == "true" || s == "false")
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
uint64_t RESTAPIHandler::GetParameter(const std::string &Name, const uint64_t Default) {
|
||||
auto Hint = std::find_if(Parameters_.begin(),Parameters_.end(),[Name](const std::pair<std::string,std::string> &S){ return S.first==Name; });
|
||||
if(Hint==Parameters_.end() || !is_number(Hint->second))
|
||||
return Default;
|
||||
return std::stoull(Hint->second);
|
||||
}
|
||||
|
||||
bool RESTAPIHandler::GetBoolParameter(const std::string &Name, bool Default) {
|
||||
auto Hint = std::find_if(begin(Parameters_),end(Parameters_),[Name](const std::pair<std::string,std::string> &S){ return S.first==Name; });
|
||||
if(Hint==end(Parameters_) || !is_bool(Hint->second))
|
||||
return Default;
|
||||
return Hint->second=="true";
|
||||
}
|
||||
|
||||
std::string RESTAPIHandler::GetParameter(const std::string &Name, const std::string &Default) {
|
||||
auto Hint = std::find_if(begin(Parameters_),end(Parameters_),[Name](const std::pair<std::string,std::string> &S){ return S.first==Name; });
|
||||
if(Hint==end(Parameters_))
|
||||
return Default;
|
||||
return Hint->second;
|
||||
}
|
||||
|
||||
bool RESTAPIHandler::HasParameter(const std::string &Name, std::string &Value) {
|
||||
auto Hint = std::find_if(begin(Parameters_),end(Parameters_),[Name](const std::pair<std::string,std::string> &S){ return S.first==Name; });
|
||||
if(Hint==end(Parameters_))
|
||||
return false;
|
||||
Value = Hint->second;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RESTAPIHandler::HasParameter(const std::string &Name, uint64_t & Value) {
|
||||
auto Hint = std::find_if(begin(Parameters_),end(Parameters_),[Name](const std::pair<std::string,std::string> &S){ return S.first==Name; });
|
||||
if(Hint==end(Parameters_))
|
||||
return false;
|
||||
Value = std::stoull(Hint->second);
|
||||
return true;
|
||||
}
|
||||
|
||||
const std::string &RESTAPIHandler::GetBinding(const std::string &Name, const std::string &Default) {
|
||||
auto E = Bindings_.find(Poco::toLower(Name));
|
||||
if (E == Bindings_.end())
|
||||
return Default;
|
||||
|
||||
return E->second;
|
||||
}
|
||||
|
||||
static std::string MakeList(const std::vector<std::string> &L) {
|
||||
std::string Return;
|
||||
for (const auto &i : L)
|
||||
if (Return.empty())
|
||||
Return = i;
|
||||
else
|
||||
Return += ", " + i;
|
||||
|
||||
return Return;
|
||||
}
|
||||
|
||||
bool RESTAPIHandler::AssignIfPresent(const Poco::JSON::Object::Ptr &O, const std::string &Field, std::string &Value) {
|
||||
if(O->has(Field)) {
|
||||
Value = O->get(Field).toString();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool RESTAPIHandler::AssignIfPresent(const Poco::JSON::Object::Ptr &O, const std::string &Field, uint64_t &Value) {
|
||||
if(O->has(Field)) {
|
||||
Value = O->get(Field);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void RESTAPIHandler::AddCORS() {
|
||||
auto Origin = Request->find("Origin");
|
||||
if (Origin != Request->end()) {
|
||||
Response->set("Access-Control-Allow-Origin", Origin->second);
|
||||
Response->set("Vary", "Origin");
|
||||
} else {
|
||||
Response->set("Access-Control-Allow-Origin", "*");
|
||||
}
|
||||
Response->set("Access-Control-Allow-Headers", "*");
|
||||
Response->set("Access-Control-Allow-Methods", MakeList(Methods_));
|
||||
Response->set("Access-Control-Max-Age", "86400");
|
||||
}
|
||||
|
||||
void RESTAPIHandler::SetCommonHeaders(bool CloseConnection) {
|
||||
Response->setVersion(Poco::Net::HTTPMessage::HTTP_1_1);
|
||||
Response->setChunkedTransferEncoding(true);
|
||||
Response->setContentType("application/json");
|
||||
if(CloseConnection) {
|
||||
Response->set("Connection", "close");
|
||||
Response->setKeepAlive(false);
|
||||
} else {
|
||||
Response->setKeepAlive(true);
|
||||
Response->set("Connection", "Keep-Alive");
|
||||
Response->set("Keep-Alive", "timeout=5, max=1000");
|
||||
}
|
||||
}
|
||||
|
||||
void RESTAPIHandler::ProcessOptions() {
|
||||
AddCORS();
|
||||
SetCommonHeaders();
|
||||
Response->setContentLength(0);
|
||||
Response->set("Access-Control-Allow-Credentials", "true");
|
||||
Response->setStatus(Poco::Net::HTTPResponse::HTTP_OK);
|
||||
Response->set("Vary", "Origin, Access-Control-Request-Headers, Access-Control-Request-Method");
|
||||
Response->send();
|
||||
}
|
||||
|
||||
void RESTAPIHandler::PrepareResponse( Poco::Net::HTTPResponse::HTTPStatus Status,
|
||||
bool CloseConnection) {
|
||||
Response->setStatus(Status);
|
||||
AddCORS();
|
||||
SetCommonHeaders(CloseConnection);
|
||||
}
|
||||
|
||||
void RESTAPIHandler::BadRequest(const std::string & Reason) {
|
||||
PrepareResponse(Poco::Net::HTTPResponse::HTTP_BAD_REQUEST);
|
||||
Poco::JSON::Object ErrorObject;
|
||||
ErrorObject.set("ErrorCode",400);
|
||||
ErrorObject.set("ErrorDetails",Request->getMethod());
|
||||
ErrorObject.set("ErrorDescription",Reason.empty() ? "Command is missing parameters or wrong values." : Reason) ;
|
||||
std::ostream &Answer = Response->send();
|
||||
Poco::JSON::Stringifier::stringify(ErrorObject, Answer);
|
||||
}
|
||||
|
||||
void RESTAPIHandler::InternalError(const std::string & Reason) {
|
||||
PrepareResponse(Poco::Net::HTTPResponse::HTTP_INTERNAL_SERVER_ERROR);
|
||||
Poco::JSON::Object ErrorObject;
|
||||
ErrorObject.set("ErrorCode",500);
|
||||
ErrorObject.set("ErrorDetails",Request->getMethod());
|
||||
ErrorObject.set("ErrorDescription",Reason.empty() ? "Please try later or review the data submitted." : Reason) ;
|
||||
std::ostream &Answer = Response->send();
|
||||
Poco::JSON::Stringifier::stringify(ErrorObject, Answer);
|
||||
}
|
||||
|
||||
void RESTAPIHandler::UnAuthorized(const std::string & Reason) {
|
||||
PrepareResponse(Poco::Net::HTTPResponse::HTTP_FORBIDDEN);
|
||||
Poco::JSON::Object ErrorObject;
|
||||
ErrorObject.set("ErrorCode",403);
|
||||
ErrorObject.set("ErrorDetails",Request->getMethod());
|
||||
ErrorObject.set("ErrorDescription",Reason.empty() ? "No access allowed." : Reason) ;
|
||||
std::ostream &Answer = Response->send();
|
||||
Poco::JSON::Stringifier::stringify(ErrorObject, Answer);
|
||||
}
|
||||
|
||||
void RESTAPIHandler::NotFound() {
|
||||
PrepareResponse(Poco::Net::HTTPResponse::HTTP_NOT_FOUND);
|
||||
Poco::JSON::Object ErrorObject;
|
||||
ErrorObject.set("ErrorCode",404);
|
||||
ErrorObject.set("ErrorDetails",Request->getMethod());
|
||||
ErrorObject.set("ErrorDescription","This resource does not exist.");
|
||||
std::ostream &Answer = Response->send();
|
||||
Poco::JSON::Stringifier::stringify(ErrorObject, Answer);
|
||||
Logger_.debug(Poco::format("RES-NOTFOUND: User='%s' Method='%s' Path='%s",
|
||||
Utils::FormatIPv6(Request->clientAddress().toString()),
|
||||
Request->getMethod(),
|
||||
Request->getURI()));
|
||||
}
|
||||
|
||||
void RESTAPIHandler::OK() {
|
||||
PrepareResponse();
|
||||
if( Request->getMethod()==Poco::Net::HTTPRequest::HTTP_DELETE ||
|
||||
Request->getMethod()==Poco::Net::HTTPRequest::HTTP_OPTIONS) {
|
||||
Response->send();
|
||||
} else {
|
||||
Poco::JSON::Object ErrorObject;
|
||||
ErrorObject.set("Code", 0);
|
||||
ErrorObject.set("Operation", Request->getMethod());
|
||||
ErrorObject.set("Details", "Command completed.");
|
||||
std::ostream &Answer = Response->send();
|
||||
Poco::JSON::Stringifier::stringify(ErrorObject, Answer);
|
||||
}
|
||||
}
|
||||
|
||||
void RESTAPIHandler::SendFile(Poco::File & File, const std::string & UUID) {
|
||||
Response->set("Content-Type","application/octet-stream");
|
||||
Response->set("Content-Disposition", "attachment; filename=" + UUID );
|
||||
Response->set("Content-Transfer-Encoding","binary");
|
||||
Response->set("Accept-Ranges", "bytes");
|
||||
Response->set("Cache-Control", "private");
|
||||
Response->set("Pragma", "private");
|
||||
Response->set("Expires", "Mon, 26 Jul 2027 05:00:00 GMT");
|
||||
Response->set("Content-Length", std::to_string(File.getSize()));
|
||||
AddCORS();
|
||||
Response->sendFile(File.path(),"application/octet-stream");
|
||||
}
|
||||
|
||||
void RESTAPIHandler::SendFile(Poco::File & File) {
|
||||
Poco::Path P(File.path());
|
||||
auto MT = Utils::FindMediaType(File);
|
||||
if(MT.Encoding==Utils::BINARY) {
|
||||
Response->set("Content-Transfer-Encoding","binary");
|
||||
Response->set("Accept-Ranges", "bytes");
|
||||
}
|
||||
Response->set("Cache-Control", "private");
|
||||
Response->set("Pragma", "private");
|
||||
Response->set("Expires", "Mon, 26 Jul 2027 05:00:00 GMT");
|
||||
AddCORS();
|
||||
Response->sendFile(File.path(),MT.ContentType);
|
||||
}
|
||||
|
||||
void RESTAPIHandler::SendFile(Poco::TemporaryFile &TempAvatar, const std::string &Type, const std::string & Name) {
|
||||
auto MT = Utils::FindMediaType(Name);
|
||||
if(MT.Encoding==Utils::BINARY) {
|
||||
Response->set("Content-Transfer-Encoding","binary");
|
||||
Response->set("Accept-Ranges", "bytes");
|
||||
}
|
||||
Response->set("Content-Disposition", "attachment; filename=" + Name );
|
||||
Response->set("Accept-Ranges", "bytes");
|
||||
Response->set("Cache-Control", "private");
|
||||
Response->set("Pragma", "private");
|
||||
Response->set("Expires", "Mon, 26 Jul 2027 05:00:00 GMT");
|
||||
AddCORS();
|
||||
Response->sendFile(TempAvatar.path(),MT.ContentType);
|
||||
}
|
||||
|
||||
void RESTAPIHandler::SendHTMLFileBack(Poco::File & File,
|
||||
const Types::StringPairVec & FormVars) {
|
||||
Response->set("Pragma", "private");
|
||||
Response->set("Expires", "Mon, 26 Jul 2027 05:00:00 GMT");
|
||||
Response->set("Content-Length", std::to_string(File.getSize()));
|
||||
AddCORS();
|
||||
auto FormContent = Utils::LoadFile(File.path());
|
||||
Utils::ReplaceVariables(FormContent, FormVars);
|
||||
Response->setChunkedTransferEncoding(true);
|
||||
Response->setContentType("text/html");
|
||||
std::ostream& ostr = Response->send();
|
||||
ostr << FormContent;
|
||||
}
|
||||
|
||||
void RESTAPIHandler::ReturnStatus(Poco::Net::HTTPResponse::HTTPStatus Status, bool CloseConnection) {
|
||||
PrepareResponse(Status, CloseConnection);
|
||||
if(Status == Poco::Net::HTTPResponse::HTTP_NO_CONTENT) {
|
||||
Response->setContentLength(0);
|
||||
Response->erase("Content-Type");
|
||||
Response->setChunkedTransferEncoding(false);
|
||||
}
|
||||
Response->send();
|
||||
}
|
||||
|
||||
bool RESTAPIHandler::ContinueProcessing() {
|
||||
if (Request->getMethod() == Poco::Net::HTTPRequest::HTTP_OPTIONS) {
|
||||
ProcessOptions();
|
||||
return false;
|
||||
} else if (std::find(Methods_.begin(), Methods_.end(), Request->getMethod()) == Methods_.end()) {
|
||||
BadRequest(RESTAPI::Errors::UnsupportedHTTPMethod);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RESTAPIHandler::IsAuthorized() {
|
||||
if(Internal_) {
|
||||
auto Allowed = Daemon()->IsValidAPIKEY(*Request);
|
||||
if(!Allowed) {
|
||||
if(Server_.LogBadTokens(false)) {
|
||||
Logger_.debug(Poco::format("I-REQ-DENIED(%s): Method='%s' Path='%s",
|
||||
Utils::FormatIPv6(Request->clientAddress().toString()),
|
||||
Request->getMethod(), Request->getURI()));
|
||||
}
|
||||
} else {
|
||||
auto Id = Request->get("X-INTERNAL-NAME", "unknown");
|
||||
if(Server_.LogIt(Request->getMethod(),true)) {
|
||||
Logger_.debug(Poco::format("I-REQ-ALLOWED(%s): User='%s' Method='%s' Path='%s",
|
||||
Utils::FormatIPv6(Request->clientAddress().toString()), Id,
|
||||
Request->getMethod(), Request->getURI()));
|
||||
}
|
||||
}
|
||||
return Allowed;
|
||||
} else {
|
||||
if (SessionToken_.empty()) {
|
||||
try {
|
||||
Poco::Net::OAuth20Credentials Auth(*Request);
|
||||
if (Auth.getScheme() == "Bearer") {
|
||||
SessionToken_ = Auth.getBearerToken();
|
||||
}
|
||||
} catch (const Poco::Exception &E) {
|
||||
Logger_.log(E);
|
||||
}
|
||||
}
|
||||
#ifdef TIP_SECURITY_SERVICE
|
||||
if (AuthService()->IsAuthorized(*Request, SessionToken_, UserInfo_)) {
|
||||
#else
|
||||
if (AuthClient()->IsAuthorized(*Request, SessionToken_, UserInfo_)) {
|
||||
#endif
|
||||
if(Server_.LogIt(Request->getMethod(),true)) {
|
||||
Logger_.debug(Poco::format("X-REQ-ALLOWED(%s): User='%s@%s' Method='%s' Path='%s",
|
||||
Utils::FormatIPv6(Request->clientAddress().toString()),
|
||||
UserInfo_.userinfo.email,
|
||||
Request->clientAddress().toString(),
|
||||
Request->getMethod(),
|
||||
Request->getURI()));
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
if(Server_.LogBadTokens(true)) {
|
||||
Logger_.debug(Poco::format("X-REQ-DENIED(%s): Method='%s' Path='%s",
|
||||
Utils::FormatIPv6(Request->clientAddress().toString()),
|
||||
Request->getMethod(), Request->getURI()));
|
||||
}
|
||||
UnAuthorized();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void RESTAPIHandler::ReturnObject(Poco::JSON::Object &Object) {
|
||||
PrepareResponse();
|
||||
std::ostream &Answer = Response->send();
|
||||
Poco::JSON::Stringifier::stringify(Object, Answer);
|
||||
}
|
||||
|
||||
void RESTAPIHandler::ReturnCountOnly(uint64_t Count) {
|
||||
Poco::JSON::Object Answer;
|
||||
Answer.set("count", Count);
|
||||
ReturnObject(Answer);
|
||||
}
|
||||
|
||||
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);
|
||||
QB_.CountOnly = GetBoolParameter(RESTAPI::Protocol::COUNTONLY,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){
|
||||
if(Obj->has(Parameter))
|
||||
return Obj->get(Parameter);
|
||||
return Default;
|
||||
}
|
||||
|
||||
[[nodiscard]] std::string RESTAPIHandler::GetS(const char *Parameter,const Poco::JSON::Object::Ptr &Obj, const std::string & Default){
|
||||
if(Obj->has(Parameter))
|
||||
return Obj->get(Parameter).toString();
|
||||
return Default;
|
||||
}
|
||||
|
||||
[[nodiscard]] bool RESTAPIHandler::GetB(const char *Parameter,const Poco::JSON::Object::Ptr &Obj, bool Default){
|
||||
if(Obj->has(Parameter))
|
||||
return Obj->get(Parameter).toString()=="true";
|
||||
return Default;
|
||||
}
|
||||
|
||||
[[nodiscard]] uint64_t RESTAPIHandler::GetWhen(const Poco::JSON::Object::Ptr &Obj) {
|
||||
return RESTAPIHandler::Get(RESTAPI::Protocol::WHEN, Obj);
|
||||
}
|
||||
}
|
||||
@@ -1,233 +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 UCENTRAL_RESTAPI_HANDLER_H
|
||||
#define UCENTRAL_RESTAPI_HANDLER_H
|
||||
|
||||
#include "Poco/URI.h"
|
||||
#include "Poco/Net/HTTPRequestHandler.h"
|
||||
#include "Poco/Net/HTTPRequestHandlerFactory.h"
|
||||
#include "Poco/Net/HTTPServerRequest.h"
|
||||
#include "Poco/Net/HTTPServerResponse.h"
|
||||
#include "Poco/Net/NetException.h"
|
||||
#include "Poco/Net/PartHandler.h"
|
||||
|
||||
#include "Poco/Logger.h"
|
||||
#include "Poco/File.h"
|
||||
#include "Poco/TemporaryFile.h"
|
||||
#include "Poco/JSON/Object.h"
|
||||
#include "Poco/CountingStream.h"
|
||||
#include "Poco/NullStream.h"
|
||||
|
||||
#include "RESTAPI_SecurityObjects.h"
|
||||
#include "RESTAPI_utils.h"
|
||||
#include "RESTAPI_GenericServer.h"
|
||||
|
||||
namespace OpenWifi {
|
||||
|
||||
class RESTAPI_PartHandler: public Poco::Net::PartHandler
|
||||
{
|
||||
public:
|
||||
RESTAPI_PartHandler():
|
||||
_length(0)
|
||||
{
|
||||
}
|
||||
|
||||
void handlePart(const Poco::Net::MessageHeader& header, std::istream& stream) override
|
||||
{
|
||||
_type = header.get("Content-Type", "(unspecified)");
|
||||
if (header.has("Content-Disposition"))
|
||||
{
|
||||
std::string disp;
|
||||
Poco::Net::NameValueCollection params;
|
||||
Poco::Net::MessageHeader::splitParameters(header["Content-Disposition"], disp, params);
|
||||
_name = params.get("name", "(unnamed)");
|
||||
_fileName = params.get("filename", "(unnamed)");
|
||||
}
|
||||
|
||||
Poco::CountingInputStream istr(stream);
|
||||
Poco::NullOutputStream ostr;
|
||||
Poco::StreamCopier::copyStream(istr, ostr);
|
||||
_length = (int)istr.chars();
|
||||
}
|
||||
|
||||
[[nodiscard]] int length() const
|
||||
{
|
||||
return _length;
|
||||
}
|
||||
|
||||
[[nodiscard]] const std::string& name() const
|
||||
{
|
||||
return _name;
|
||||
}
|
||||
|
||||
[[nodiscard]] const std::string& fileName() const
|
||||
{
|
||||
return _fileName;
|
||||
}
|
||||
|
||||
[[nodiscard]] const std::string& contentType() const
|
||||
{
|
||||
return _type;
|
||||
}
|
||||
|
||||
private:
|
||||
int _length;
|
||||
std::string _type;
|
||||
std::string _name;
|
||||
std::string _fileName;
|
||||
};
|
||||
|
||||
class RESTAPIHandler : public Poco::Net::HTTPRequestHandler {
|
||||
public:
|
||||
struct QueryBlock {
|
||||
uint64_t StartDate = 0 , EndDate = 0 , Offset = 0 , Limit = 0, LogType = 0 ;
|
||||
std::string SerialNumber, Filter, Select;
|
||||
bool Lifetime=false, LastOnly=false, Newest=false, CountOnly=false;
|
||||
};
|
||||
|
||||
typedef std::map<std::string, std::string> BindingMap;
|
||||
|
||||
RESTAPIHandler(BindingMap map, Poco::Logger &l, std::vector<std::string> Methods, RESTAPI_GenericServer & Server, bool Internal=false, bool AlwaysAuthorize=true)
|
||||
: Bindings_(std::move(map)), Logger_(l), Methods_(std::move(Methods)), Server_(Server), Internal_(Internal), AlwaysAuthorize_(AlwaysAuthorize) {}
|
||||
|
||||
static bool ParseBindings(const std::string & Request, const std::list<const char *> & EndPoints, BindingMap &Keys);
|
||||
void PrintBindings();
|
||||
void ParseParameters();
|
||||
|
||||
void AddCORS();
|
||||
void SetCommonHeaders(bool CloseConnection=false);
|
||||
void ProcessOptions();
|
||||
void
|
||||
PrepareResponse(Poco::Net::HTTPResponse::HTTPStatus Status = Poco::Net::HTTPResponse::HTTP_OK,
|
||||
bool CloseConnection = false);
|
||||
bool ContinueProcessing();
|
||||
bool IsAuthorized();
|
||||
|
||||
uint64_t GetParameter(const std::string &Name, uint64_t Default);
|
||||
std::string GetParameter(const std::string &Name, const std::string &Default);
|
||||
bool GetBoolParameter(const std::string &Name, bool Default);
|
||||
|
||||
void BadRequest(const std::string &Reason );
|
||||
void InternalError(const std::string &Reason = "");
|
||||
void UnAuthorized(const std::string &Reason = "");
|
||||
void ReturnObject(Poco::JSON::Object &Object);
|
||||
void NotFound();
|
||||
void OK();
|
||||
void ReturnStatus(Poco::Net::HTTPResponse::HTTPStatus Status,
|
||||
bool CloseConnection=false);
|
||||
void SendFile(Poco::File & File, const std::string & UUID);
|
||||
void SendHTMLFileBack(Poco::File & File,
|
||||
const Types::StringPairVec & FormVars);
|
||||
void SendFile(Poco::TemporaryFile &TempAvatar, const std::string &Type, const std::string & Name);
|
||||
|
||||
void SendFile(Poco::File & File);
|
||||
|
||||
const std::string &GetBinding(const std::string &Name, const std::string &Default);
|
||||
bool InitQueryBlock();
|
||||
|
||||
void ReturnCountOnly(uint64_t Count);
|
||||
|
||||
[[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);
|
||||
|
||||
static bool AssignIfPresent(const Poco::JSON::Object::Ptr &O, const std::string &Field, std::string &Value);
|
||||
static bool AssignIfPresent(const Poco::JSON::Object::Ptr &O, const std::string &Field, uint64_t &Value);
|
||||
|
||||
template<typename T> void ReturnObject(const char *Name, const std::vector<T> & Objects) {
|
||||
Poco::JSON::Object Answer;
|
||||
RESTAPI_utils::field_to_json(Answer,Name,Objects);
|
||||
ReturnObject(Answer);
|
||||
}
|
||||
|
||||
Poco::Logger & Logger() { return Logger_; }
|
||||
|
||||
void handleRequest(Poco::Net::HTTPServerRequest &request,
|
||||
Poco::Net::HTTPServerResponse &response) final;
|
||||
|
||||
virtual void DoGet() = 0 ;
|
||||
virtual void DoDelete() = 0 ;
|
||||
virtual void DoPost() = 0 ;
|
||||
virtual void DoPut() = 0 ;
|
||||
|
||||
const Poco::JSON::Object::Ptr & ParseStream();
|
||||
|
||||
protected:
|
||||
BindingMap Bindings_;
|
||||
Poco::URI::QueryParameters Parameters_;
|
||||
Poco::Logger &Logger_;
|
||||
std::string SessionToken_;
|
||||
SecurityObjects::UserInfoAndPolicy UserInfo_;
|
||||
std::vector<std::string> Methods_;
|
||||
QueryBlock QB_;
|
||||
bool Internal_=false;
|
||||
bool QueryBlockInitialized_=false;
|
||||
Poco::Net::HTTPServerRequest *Request= nullptr;
|
||||
Poco::Net::HTTPServerResponse *Response= nullptr;
|
||||
bool AlwaysAuthorize_=true;
|
||||
Poco::JSON::Parser IncomingParser_;
|
||||
RESTAPI_GenericServer & Server_;
|
||||
};
|
||||
|
||||
class RESTAPI_UnknownRequestHandler : public RESTAPIHandler {
|
||||
public:
|
||||
RESTAPI_UnknownRequestHandler(const RESTAPIHandler::BindingMap &bindings, Poco::Logger &L, RESTAPI_GenericServer & Server)
|
||||
: RESTAPIHandler(bindings, L, std::vector<std::string>{}, Server) {}
|
||||
inline void DoGet() override {};
|
||||
inline void DoPost() override {};
|
||||
inline void DoPut() override {};
|
||||
inline void DoDelete() override {};
|
||||
};
|
||||
|
||||
template<class T>
|
||||
constexpr auto test_has_PathName_method(T*)
|
||||
-> decltype( T::PathName() , std::true_type{} )
|
||||
{
|
||||
return std::true_type{};
|
||||
}
|
||||
constexpr auto test_has_PathName_method(...) -> std::false_type
|
||||
{
|
||||
return std::false_type{};
|
||||
}
|
||||
|
||||
template<typename T, typename... Args>
|
||||
RESTAPIHandler * RESTAPI_Router(const std::string & RequestedPath, RESTAPIHandler::BindingMap &Bindings, Poco::Logger & Logger, RESTAPI_GenericServer & Server) {
|
||||
static_assert(test_has_PathName_method((T*)nullptr), "Class must have a static PathName() method.");
|
||||
if(RESTAPIHandler::ParseBindings(RequestedPath,T::PathName(),Bindings)) {
|
||||
return new T(Bindings, Logger, Server, false);
|
||||
}
|
||||
|
||||
if constexpr (sizeof...(Args) == 0) {
|
||||
return new RESTAPI_UnknownRequestHandler(Bindings,Logger, Server);
|
||||
} else {
|
||||
return RESTAPI_Router<Args...>(RequestedPath, Bindings, Logger, Server);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T, typename... Args>
|
||||
RESTAPIHandler * RESTAPI_Router_I(const std::string & RequestedPath, RESTAPIHandler::BindingMap &Bindings, Poco::Logger & Logger, RESTAPI_GenericServer & Server) {
|
||||
static_assert(test_has_PathName_method((T*)nullptr), "Class must have a static PathName() method.");
|
||||
if(RESTAPIHandler::ParseBindings(RequestedPath,T::PathName(),Bindings)) {
|
||||
return new T(Bindings, Logger, Server, true);
|
||||
}
|
||||
|
||||
if constexpr (sizeof...(Args) == 0) {
|
||||
return new RESTAPI_UnknownRequestHandler(Bindings,Logger, Server);
|
||||
} else {
|
||||
return RESTAPI_Router_I<Args...>(RequestedPath, Bindings, Logger, Server);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif //UCENTRAL_RESTAPI_HANDLER_H
|
||||
@@ -1,96 +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 "RESTAPI_server.h"
|
||||
|
||||
#include "Poco/URI.h"
|
||||
|
||||
#include "RESTAPI_BlackList.h"
|
||||
#include "RESTAPI_command.h"
|
||||
#include "RESTAPI_commands.h"
|
||||
#include "RESTAPI_default_configuration.h"
|
||||
#include "RESTAPI_default_configurations.h"
|
||||
#include "RESTAPI_device_commandHandler.h"
|
||||
#include "RESTAPI_device_handler.h"
|
||||
#include "RESTAPI_devices_handler.h"
|
||||
#include "RESTAPI_file.h"
|
||||
#include "RESTAPI_system_command.h"
|
||||
#include "RESTAPI_ouis.h"
|
||||
#include "RESTAPI_deviceDashboardHandler.h"
|
||||
|
||||
#include "Utils.h"
|
||||
#include "RESTAPI_webSocketServer.h"
|
||||
#include "RESTAPI_TelemetryWebSocket.h"
|
||||
|
||||
namespace OpenWifi {
|
||||
|
||||
class RESTAPI_server *RESTAPI_server::instance_ = nullptr;
|
||||
|
||||
int RESTAPI_server::Start() {
|
||||
Logger_.information("Starting.");
|
||||
Server_.InitLogging();
|
||||
for(const auto & Svr: ConfigServersList_) {
|
||||
Logger_.information(Poco::format("Starting: %s:%s Keyfile:%s CertFile: %s", Svr.Address(), std::to_string(Svr.Port()),
|
||||
Svr.KeyFile(),Svr.CertFile()));
|
||||
|
||||
auto Sock{Svr.CreateSecureSocket(Logger_)};
|
||||
|
||||
Svr.LogCert(Logger_);
|
||||
if(!Svr.RootCA().empty())
|
||||
Svr.LogCas(Logger_);
|
||||
|
||||
auto Params = new Poco::Net::HTTPServerParams;
|
||||
Params->setMaxThreads(50);
|
||||
Params->setMaxQueued(200);
|
||||
Params->setKeepAlive(true);
|
||||
|
||||
auto NewServer = std::make_unique<Poco::Net::HTTPServer>(new RESTAPIServerRequestHandlerFactory(Server_), Pool_, Sock, Params);
|
||||
NewServer->start();
|
||||
RESTServers_.push_back(std::move(NewServer));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void RESTAPI_server::reinitialize(Poco::Util::Application &self) {
|
||||
Daemon()->LoadConfigurationFile();
|
||||
Logger_.information("Reinitializing.");
|
||||
Stop();
|
||||
Start();
|
||||
}
|
||||
|
||||
void RESTAPI_server::Stop() {
|
||||
Logger_.information("Stopping ");
|
||||
for( const auto & svr : RESTServers_ )
|
||||
svr->stop();
|
||||
RESTServers_.clear();
|
||||
}
|
||||
|
||||
Poco::Net::HTTPRequestHandler *RESTAPIServerRequestHandlerFactory::createRequestHandler(const Poco::Net::HTTPServerRequest & Request) {
|
||||
Poco::URI uri(Request.getURI());
|
||||
const auto & Path = uri.getPath();
|
||||
RESTAPIHandler::BindingMap Bindings;
|
||||
|
||||
return RESTAPI_Router<
|
||||
RESTAPI_devices_handler,
|
||||
RESTAPI_device_handler,
|
||||
RESTAPI_device_commandHandler,
|
||||
RESTAPI_default_configurations,
|
||||
RESTAPI_default_configuration,
|
||||
RESTAPI_command,
|
||||
RESTAPI_commands,
|
||||
RESTAPI_ouis,
|
||||
RESTAPI_file,
|
||||
RESTAPI_system_command,
|
||||
RESTAPI_deviceDashboardHandler,
|
||||
RESTAPI_webSocketServer,
|
||||
RESTAPI_BlackList,
|
||||
RESTAPI_TelemetryWebSocket>(Path,Bindings,Logger_, Server_);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
@@ -1,61 +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 UCENTRAL_UCENTRALRESTAPISERVER_H
|
||||
#define UCENTRAL_UCENTRALRESTAPISERVER_H
|
||||
|
||||
#include "SubSystemServer.h"
|
||||
|
||||
#include "Poco/Net/HTTPServer.h"
|
||||
#include "Poco/Net/HTTPRequestHandler.h"
|
||||
#include "Poco/Net/HTTPRequestHandlerFactory.h"
|
||||
#include "Poco/Net/HTTPServerRequest.h"
|
||||
#include "Poco/Net/NetException.h"
|
||||
#include "RESTAPI_GenericServer.h"
|
||||
|
||||
namespace OpenWifi {
|
||||
|
||||
class RESTAPI_server : public SubSystemServer {
|
||||
|
||||
public:
|
||||
int Start() override;
|
||||
void Stop() override;
|
||||
static RESTAPI_server *instance() {
|
||||
if (instance_ == nullptr) {
|
||||
instance_ = new RESTAPI_server;
|
||||
}
|
||||
return instance_;
|
||||
}
|
||||
void reinitialize(Poco::Util::Application &self) override;
|
||||
private:
|
||||
static RESTAPI_server *instance_;
|
||||
std::vector<std::unique_ptr<Poco::Net::HTTPServer>> RESTServers_;
|
||||
Poco::ThreadPool Pool_;
|
||||
RESTAPI_GenericServer Server_;
|
||||
|
||||
RESTAPI_server() noexcept: SubSystemServer("RESTAPIServer", "RESTAPIServer", "openwifi.restapi")
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
class RESTAPIServerRequestHandlerFactory : public Poco::Net::HTTPRequestHandlerFactory {
|
||||
public:
|
||||
explicit RESTAPIServerRequestHandlerFactory(RESTAPI_GenericServer &Server) :
|
||||
Logger_(RESTAPI_server::instance()->Logger()),
|
||||
Server_(Server){}
|
||||
|
||||
Poco::Net::HTTPRequestHandler *createRequestHandler(const Poco::Net::HTTPServerRequest &request) override;
|
||||
private:
|
||||
Poco::Logger &Logger_;
|
||||
RESTAPI_GenericServer &Server_;
|
||||
};
|
||||
|
||||
inline RESTAPI_server * RESTAPI_server() { return RESTAPI_server::instance(); }
|
||||
} // namespace
|
||||
|
||||
#endif //UCENTRAL_UCENTRALRESTAPISERVER_H
|
||||
@@ -1,146 +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 "RESTAPI_system_command.h"
|
||||
|
||||
#include "Poco/Exception.h"
|
||||
#include "Poco/JSON/Parser.h"
|
||||
#include "Poco/DateTime.h"
|
||||
#include "Poco/DateTimeFormat.h"
|
||||
|
||||
#include "Daemon.h"
|
||||
#include "RESTAPI_protocol.h"
|
||||
#include "RESTAPI_errors.h"
|
||||
#include <thread>
|
||||
#include <chrono>
|
||||
|
||||
using namespace std::chrono_literals;
|
||||
|
||||
namespace OpenWifi {
|
||||
void RESTAPI_system_command::DoPost() {
|
||||
auto Obj = ParseStream();
|
||||
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::SUBSYSTEMS) &&
|
||||
Obj->isArray(RESTAPI::Protocol::SUBSYSTEMS)) {
|
||||
auto ParametersBlock = Obj->getArray(RESTAPI::Protocol::SUBSYSTEMS);
|
||||
for (const auto &i : *ParametersBlock) {
|
||||
Poco::JSON::Parser pp;
|
||||
auto InnerObj = pp.parse(i).extract<Poco::JSON::Object::Ptr>();
|
||||
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));
|
||||
}
|
||||
}
|
||||
OK();
|
||||
return;
|
||||
}
|
||||
} 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(RESTAPI::Protocol::TAG, Name);
|
||||
Pair.set(RESTAPI::Protocol::VALUE, Level);
|
||||
Array.add(Pair);
|
||||
}
|
||||
Result.set(RESTAPI::Protocol::TAGLIST, Array);
|
||||
ReturnObject(Result);
|
||||
return;
|
||||
} 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(RESTAPI::Protocol::LIST, LevelNamesArray);
|
||||
ReturnObject(Result);
|
||||
return;
|
||||
} 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(RESTAPI::Protocol::LIST, LevelNamesArray);
|
||||
ReturnObject(Result);
|
||||
return;
|
||||
} else if (Command == RESTAPI::Protocol::STATS) {
|
||||
|
||||
} else if (Command == RESTAPI::Protocol::RELOAD) {
|
||||
if (Obj->has(RESTAPI::Protocol::SUBSYSTEMS) &&
|
||||
Obj->isArray(RESTAPI::Protocol::SUBSYSTEMS)) {
|
||||
auto SubSystems = Obj->getArray(RESTAPI::Protocol::SUBSYSTEMS);
|
||||
std::vector<std::string> Names;
|
||||
for (const auto &i : *SubSystems)
|
||||
Names.push_back(i.toString());
|
||||
std::thread ReloadThread([Names](){
|
||||
std::this_thread::sleep_for(10000ms);
|
||||
for(const auto &i:Names) {
|
||||
if(i=="daemon")
|
||||
Daemon()->Reload();
|
||||
else
|
||||
Daemon()->Reload(i);
|
||||
}
|
||||
});
|
||||
ReloadThread.detach();
|
||||
}
|
||||
OK();
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
BadRequest(RESTAPI::Errors::InvalidCommand);
|
||||
return;
|
||||
}
|
||||
BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
|
||||
}
|
||||
|
||||
void RESTAPI_system_command::DoGet() {
|
||||
std::string Arg;
|
||||
if(HasParameter("command",Arg) && Arg=="info") {
|
||||
Poco::JSON::Object Answer;
|
||||
Answer.set(RESTAPI::Protocol::VERSION, Daemon()->Version());
|
||||
Answer.set(RESTAPI::Protocol::UPTIME, Daemon()->uptime().totalSeconds());
|
||||
Answer.set(RESTAPI::Protocol::START, Daemon()->startTime().epochTime());
|
||||
Answer.set(RESTAPI::Protocol::OS, Poco::Environment::osName());
|
||||
Answer.set(RESTAPI::Protocol::PROCESSORS, Poco::Environment::processorCount());
|
||||
Answer.set(RESTAPI::Protocol::HOSTNAME, Poco::Environment::nodeName());
|
||||
|
||||
Poco::JSON::Array Certificates;
|
||||
auto SubSystems = Daemon()->GetFullSubSystems();
|
||||
std::set<std::string> CertNames;
|
||||
|
||||
for(const auto &i:SubSystems) {
|
||||
auto Hosts=i->HostSize();
|
||||
for(uint64_t j=0;j<Hosts;++j) {
|
||||
auto CertFileName = i->Host(j).CertFile();
|
||||
if(!CertFileName.empty()) {
|
||||
auto InsertResult = CertNames.insert(CertFileName);
|
||||
if(InsertResult.second) {
|
||||
Poco::JSON::Object Inner;
|
||||
Inner.set("filename", CertFileName);
|
||||
Poco::Crypto::X509Certificate C(CertFileName);
|
||||
auto ExpiresOn = C.expiresOn();
|
||||
Inner.set("expiresOn",ExpiresOn.timestamp().epochTime());
|
||||
Certificates.add(Inner);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Answer.set("certificates", Certificates);
|
||||
ReturnObject(Answer);
|
||||
return;
|
||||
}
|
||||
BadRequest(RESTAPI::Errors::InvalidCommand);
|
||||
}
|
||||
}
|
||||
@@ -1,32 +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_RESTAPI_SYSTEM_COMMAND_H
|
||||
#define UCENTRALGW_RESTAPI_SYSTEM_COMMAND_H
|
||||
|
||||
#include "RESTAPI_handler.h"
|
||||
|
||||
namespace OpenWifi {
|
||||
class RESTAPI_system_command : public RESTAPIHandler {
|
||||
public:
|
||||
RESTAPI_system_command(const RESTAPIHandler::BindingMap &bindings, Poco::Logger &L, RESTAPI_GenericServer & Server, bool Internal)
|
||||
: RESTAPIHandler(bindings, L,
|
||||
std::vector<std::string>{Poco::Net::HTTPRequest::HTTP_POST,
|
||||
Poco::Net::HTTPRequest::HTTP_GET,
|
||||
Poco::Net::HTTPRequest::HTTP_OPTIONS},
|
||||
Server,
|
||||
Internal) {}
|
||||
static const std::list<const char *> PathName() { return std::list<const char *>{"/api/v1/system"};}
|
||||
|
||||
void DoGet() final;
|
||||
void DoPost() final;
|
||||
void DoPut() final {};
|
||||
void DoDelete() final {};
|
||||
};
|
||||
}
|
||||
#endif // UCENTRALGW_RESTAPI_SYSTEM_COMMAND_H
|
||||
@@ -1,17 +0,0 @@
|
||||
//
|
||||
// Created by stephane bourque on 2021-07-05.
|
||||
//
|
||||
|
||||
#include "RESTAPI_utils.h"
|
||||
|
||||
namespace OpenWifi::RESTAPI_utils {
|
||||
|
||||
void EmbedDocument(const std::string & ObjName, Poco::JSON::Object & Obj, const std::string &ObjStr) {
|
||||
std::string D = ObjStr.empty() ? "{}" : ObjStr;
|
||||
Poco::JSON::Parser P;
|
||||
Poco::Dynamic::Var result = P.parse(D);
|
||||
const auto &DetailsObj = result.extract<Poco::JSON::Object::Ptr>();
|
||||
Obj.set(ObjName, DetailsObj);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,216 +0,0 @@
|
||||
//
|
||||
// Created by stephane bourque on 2021-07-05.
|
||||
//
|
||||
|
||||
#ifndef UCENTRALGW_RESTAPI_UTILS_H
|
||||
#define UCENTRALGW_RESTAPI_UTILS_H
|
||||
#include <functional>
|
||||
|
||||
#include "Poco/JSON/Object.h"
|
||||
#include "Poco/JSON/Parser.h"
|
||||
#include "Poco/Net/HTTPServerRequest.h"
|
||||
#include "OpenWifiTypes.h"
|
||||
#include "Utils.h"
|
||||
|
||||
namespace OpenWifi::RESTAPI_utils {
|
||||
|
||||
void EmbedDocument(const std::string & ObjName, Poco::JSON::Object & Obj, const std::string &ObjStr);
|
||||
|
||||
inline void field_to_json(Poco::JSON::Object &Obj, const char *Field, bool V) {
|
||||
Obj.set(Field,V);
|
||||
}
|
||||
|
||||
inline void field_to_json(Poco::JSON::Object &Obj, const char *Field, const std::string & S) {
|
||||
Obj.set(Field,S);
|
||||
}
|
||||
|
||||
inline void field_to_json(Poco::JSON::Object &Obj, const char *Field, const char * S) {
|
||||
Obj.set(Field,S);
|
||||
}
|
||||
|
||||
inline void field_to_json(Poco::JSON::Object &Obj, const char *Field, uint64_t V) {
|
||||
Obj.set(Field,V);
|
||||
}
|
||||
|
||||
inline void field_to_json(Poco::JSON::Object &Obj, const char *Field, const Types::StringVec &V) {
|
||||
Poco::JSON::Array A;
|
||||
for(const auto &i:V)
|
||||
A.add(i);
|
||||
Obj.set(Field,A);
|
||||
}
|
||||
|
||||
inline void field_to_json(Poco::JSON::Object &Obj, const char *Field, const Types::CountedMap &M) {
|
||||
Poco::JSON::Array A;
|
||||
for(const auto &[Key,Value]:M) {
|
||||
Poco::JSON::Object O;
|
||||
O.set("tag",Key);
|
||||
O.set("value", Value);
|
||||
A.add(O);
|
||||
}
|
||||
Obj.set(Field,A);
|
||||
}
|
||||
|
||||
|
||||
template<typename T> void field_to_json(Poco::JSON::Object &Obj,
|
||||
const char *Field,
|
||||
const T &V,
|
||||
std::function<std::string(const T &)> F) {
|
||||
Obj.set(Field, F(V));
|
||||
}
|
||||
|
||||
template<typename T> bool field_from_json(Poco::JSON::Object::Ptr Obj, const char *Field, T & V,
|
||||
std::function<T(const std::string &)> F) {
|
||||
if(Obj->has(Field))
|
||||
V = F(Obj->get(Field).toString());
|
||||
return true;
|
||||
}
|
||||
|
||||
inline void field_from_json(Poco::JSON::Object::Ptr Obj, const char *Field, std::string &S) {
|
||||
if(Obj->has(Field))
|
||||
S = Obj->get(Field).toString();
|
||||
}
|
||||
|
||||
inline void field_from_json(Poco::JSON::Object::Ptr Obj, const char *Field, uint64_t &V) {
|
||||
if(Obj->has(Field))
|
||||
V = Obj->get(Field);
|
||||
}
|
||||
|
||||
inline void field_from_json(Poco::JSON::Object::Ptr Obj, const char *Field, bool &V) {
|
||||
if(Obj->has(Field))
|
||||
V = (Obj->get(Field).toString() == "true");
|
||||
}
|
||||
|
||||
inline void field_from_json(Poco::JSON::Object::Ptr Obj, const char *Field, Types::StringVec &V) {
|
||||
if(Obj->isArray(Field)) {
|
||||
V.clear();
|
||||
Poco::JSON::Array::Ptr A = Obj->getArray(Field);
|
||||
for(const auto &i:*A) {
|
||||
V.push_back(i.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<class T> void field_to_json(Poco::JSON::Object &Obj, const char *Field, const std::vector<T> &Value) {
|
||||
Poco::JSON::Array Arr;
|
||||
for(const auto &i:Value) {
|
||||
Poco::JSON::Object AO;
|
||||
i.to_json(AO);
|
||||
Arr.add(AO);
|
||||
}
|
||||
Obj.set(Field, Arr);
|
||||
}
|
||||
|
||||
template<class T> void field_from_json(const Poco::JSON::Object::Ptr &Obj, const char *Field, std::vector<T> &Value) {
|
||||
if(Obj->isArray(Field)) {
|
||||
Poco::JSON::Array::Ptr Arr = Obj->getArray(Field);
|
||||
for(auto &i:*Arr) {
|
||||
auto InnerObj = i.extract<Poco::JSON::Object::Ptr>();
|
||||
T NewItem;
|
||||
NewItem.from_json(InnerObj);
|
||||
Value.push_back(NewItem);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<class T> void field_from_json(const Poco::JSON::Object::Ptr &Obj, const char *Field, T &Value) {
|
||||
if(Obj->isObject(Field)) {
|
||||
Poco::JSON::Object::Ptr A = Obj->getObject(Field);
|
||||
Value.from_json(A);
|
||||
}
|
||||
}
|
||||
|
||||
inline std::string to_string(const Types::StringVec & ObjectArray) {
|
||||
Poco::JSON::Array OutputArr;
|
||||
if(ObjectArray.empty())
|
||||
return "[]";
|
||||
for(auto const &i:ObjectArray) {
|
||||
OutputArr.add(i);
|
||||
}
|
||||
std::ostringstream OS;
|
||||
Poco::JSON::Stringifier::condense(OutputArr,OS);
|
||||
return OS.str();
|
||||
}
|
||||
|
||||
template<class T> std::string to_string(const std::vector<T> & ObjectArray) {
|
||||
Poco::JSON::Array OutputArr;
|
||||
if(ObjectArray.empty())
|
||||
return "[]";
|
||||
for(auto const &i:ObjectArray) {
|
||||
Poco::JSON::Object O;
|
||||
i.to_json(O);
|
||||
OutputArr.add(O);
|
||||
}
|
||||
std::ostringstream OS;
|
||||
Poco::JSON::Stringifier::condense(OutputArr,OS);
|
||||
return OS.str();
|
||||
}
|
||||
|
||||
template<class T> std::string to_string(const T & Object) {
|
||||
Poco::JSON::Object OutputObj;
|
||||
Object.to_json(OutputObj);
|
||||
std::ostringstream OS;
|
||||
Poco::JSON::Stringifier::condense(OutputObj,OS);
|
||||
return OS.str();
|
||||
}
|
||||
|
||||
inline Types::StringVec to_object_array(const std::string & ObjectString) {
|
||||
|
||||
Types::StringVec Result;
|
||||
if(ObjectString.empty())
|
||||
return Result;
|
||||
|
||||
try {
|
||||
Poco::JSON::Parser P;
|
||||
auto Object = P.parse(ObjectString).template extract<Poco::JSON::Array::Ptr>();
|
||||
for (auto const i : *Object) {
|
||||
Result.push_back(i.toString());
|
||||
}
|
||||
} catch (...) {
|
||||
|
||||
}
|
||||
return Result;
|
||||
}
|
||||
|
||||
template<class T> std::vector<T> to_object_array(const std::string & ObjectString) {
|
||||
|
||||
std::vector<T> Result;
|
||||
if(ObjectString.empty())
|
||||
return Result;
|
||||
|
||||
try {
|
||||
Poco::JSON::Parser P;
|
||||
auto Object = P.parse(ObjectString).template extract<Poco::JSON::Array::Ptr>();
|
||||
for (auto const i : *Object) {
|
||||
auto InnerObject = i.template extract<Poco::JSON::Object::Ptr>();
|
||||
T Obj;
|
||||
Obj.from_json(InnerObject);
|
||||
Result.push_back(Obj);
|
||||
}
|
||||
} catch (...) {
|
||||
|
||||
}
|
||||
return Result;
|
||||
}
|
||||
|
||||
template<class T> T to_object(const std::string & ObjectString) {
|
||||
T Result;
|
||||
|
||||
if(ObjectString.empty())
|
||||
return Result;
|
||||
|
||||
Poco::JSON::Parser P;
|
||||
auto Object = P.parse(ObjectString).template extract<Poco::JSON::Object::Ptr>();
|
||||
Result.from_json(Object);
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
template<class T> bool from_request(T & Obj, Poco::Net::HTTPServerRequest &Request) {
|
||||
Poco::JSON::Parser IncomingParser;
|
||||
auto RawObject = IncomingParser.parse(Request.stream()).extract<Poco::JSON::Object::Ptr>();
|
||||
Obj.from_json(RawObject);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
#endif // UCENTRALGW_RESTAPI_UTILS_H
|
||||
248
src/RESTObjects/RESTAPI_FMSObjects.cpp
Normal file
248
src/RESTObjects/RESTAPI_FMSObjects.cpp
Normal file
@@ -0,0 +1,248 @@
|
||||
//
|
||||
// Created by stephane bourque on 2021-07-12.
|
||||
//
|
||||
|
||||
#include "RESTAPI_FMSObjects.h"
|
||||
#include "framework/MicroService.h"
|
||||
|
||||
using OpenWifi::RESTAPI_utils::field_to_json;
|
||||
using OpenWifi::RESTAPI_utils::field_from_json;
|
||||
|
||||
namespace OpenWifi::FMSObjects {
|
||||
|
||||
void Firmware::to_json(Poco::JSON::Object &Obj) const {
|
||||
field_to_json(Obj, "id", id);
|
||||
field_to_json(Obj, "release", release);
|
||||
field_to_json(Obj, "deviceType", deviceType);
|
||||
field_to_json(Obj, "description", description);
|
||||
field_to_json(Obj, "revision", revision);
|
||||
field_to_json(Obj, "uri", uri);
|
||||
field_to_json(Obj, "image", image);
|
||||
field_to_json(Obj, "imageDate", imageDate);
|
||||
field_to_json(Obj, "size", size);
|
||||
field_to_json(Obj, "downloadCount", downloadCount);
|
||||
field_to_json(Obj, "firmwareHash", firmwareHash);
|
||||
field_to_json(Obj, "owner", owner);
|
||||
field_to_json(Obj, "location", location);
|
||||
field_to_json(Obj, "uploader", uploader);
|
||||
field_to_json(Obj, "digest", digest);
|
||||
field_to_json(Obj, "latest", latest);
|
||||
field_to_json(Obj, "notes", notes);
|
||||
field_to_json(Obj, "created", created);
|
||||
};
|
||||
|
||||
bool Firmware::from_json(const Poco::JSON::Object::Ptr &Obj) {
|
||||
try {
|
||||
field_from_json(Obj, "id", id);
|
||||
field_from_json(Obj, "release", release);
|
||||
field_from_json(Obj, "deviceType", deviceType);
|
||||
field_from_json(Obj, "description", description);
|
||||
field_from_json(Obj, "revision", revision);
|
||||
field_from_json(Obj, "uri", uri);
|
||||
field_from_json(Obj, "image", image);
|
||||
field_from_json(Obj, "imageDate", imageDate);
|
||||
field_from_json(Obj, "size", size);
|
||||
field_from_json(Obj, "downloadCount", downloadCount);
|
||||
field_from_json(Obj, "firmwareHash", firmwareHash);
|
||||
field_from_json(Obj, "owner", owner);
|
||||
field_from_json(Obj, "location", location);
|
||||
field_from_json(Obj, "uploader", uploader);
|
||||
field_from_json(Obj, "digest", digest);
|
||||
field_from_json(Obj, "latest", latest);
|
||||
field_from_json(Obj, "notes", notes);
|
||||
field_from_json(Obj, "created", created);
|
||||
return true;
|
||||
} catch (...) {
|
||||
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void FirmwareList::to_json(Poco::JSON::Object &Obj) const {
|
||||
field_to_json(Obj,"firmwares",firmwares);
|
||||
}
|
||||
|
||||
bool FirmwareList::from_json(const Poco::JSON::Object::Ptr &Obj) {
|
||||
try {
|
||||
field_from_json(Obj, "firmwares", firmwares);
|
||||
return true;
|
||||
} catch (...) {
|
||||
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void DeviceType::to_json(Poco::JSON::Object &Obj) const {
|
||||
field_to_json(Obj, "id", id);
|
||||
field_to_json(Obj, "deviceType", deviceType);
|
||||
field_to_json(Obj, "manufacturer", manufacturer);
|
||||
field_to_json(Obj, "model", model);
|
||||
field_to_json(Obj, "policy", policy);
|
||||
field_to_json(Obj, "notes", notes);
|
||||
field_to_json(Obj, "lastUpdate", lastUpdate);
|
||||
field_to_json(Obj, "created", created);
|
||||
field_to_json(Obj, "id", id);
|
||||
field_to_json(Obj, "id", id);
|
||||
field_to_json(Obj, "id", id);
|
||||
}
|
||||
|
||||
bool DeviceType::from_json(const Poco::JSON::Object::Ptr &Obj) {
|
||||
try {
|
||||
field_from_json(Obj, "id", id);
|
||||
field_from_json(Obj, "deviceType", deviceType);
|
||||
field_from_json(Obj, "manufacturer", manufacturer);
|
||||
field_from_json(Obj, "model", model);
|
||||
field_from_json(Obj, "policy", policy);
|
||||
field_from_json(Obj, "notes", notes);
|
||||
field_from_json(Obj, "lastUpdate", lastUpdate);
|
||||
field_from_json(Obj, "created", created);
|
||||
field_from_json(Obj, "id", id);
|
||||
field_from_json(Obj, "id", id);
|
||||
field_from_json(Obj, "id", id);
|
||||
return true;
|
||||
} catch (...) {
|
||||
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void DeviceTypeList::to_json(Poco::JSON::Object &Obj) const {
|
||||
field_to_json(Obj,"deviceTypes", deviceTypes);
|
||||
}
|
||||
|
||||
bool DeviceTypeList::from_json(const Poco::JSON::Object::Ptr &Obj) {
|
||||
try {
|
||||
field_from_json(Obj,"deviceTypes", deviceTypes);
|
||||
return true;
|
||||
} catch(...) {
|
||||
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void RevisionHistoryEntry::to_json(Poco::JSON::Object &Obj) const {
|
||||
field_to_json(Obj, "id", id);
|
||||
field_to_json(Obj, "serialNumber", serialNumber);
|
||||
field_to_json(Obj, "fromRelease", fromRelease);
|
||||
field_to_json(Obj, "toRelease", toRelease);
|
||||
field_to_json(Obj, "commandUUID", commandUUID);
|
||||
field_to_json(Obj, "revisionId", revisionId);
|
||||
field_to_json(Obj, "upgraded", upgraded);
|
||||
}
|
||||
|
||||
bool RevisionHistoryEntry::from_json(const Poco::JSON::Object::Ptr &Obj) {
|
||||
try {
|
||||
field_from_json(Obj, "id", id);
|
||||
field_from_json(Obj, "serialNumber", serialNumber);
|
||||
field_from_json(Obj, "fromRelease", fromRelease);
|
||||
field_from_json(Obj, "toRelease", toRelease);
|
||||
field_from_json(Obj, "commandUUID", commandUUID);
|
||||
field_from_json(Obj, "revisionId", revisionId);
|
||||
field_from_json(Obj, "upgraded", upgraded);
|
||||
return true;
|
||||
} catch(...) {
|
||||
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void RevisionHistoryEntryList::to_json(Poco::JSON::Object &Obj) const {
|
||||
field_to_json(Obj,"deviceTypes", history);
|
||||
}
|
||||
|
||||
bool RevisionHistoryEntryList::from_json(const Poco::JSON::Object::Ptr &Obj) {
|
||||
try {
|
||||
field_from_json(Obj,"deviceTypes", history);
|
||||
return true;
|
||||
} catch(...) {
|
||||
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void FirmwareAgeDetails::to_json(Poco::JSON::Object &Obj) const {
|
||||
field_to_json(Obj,"latestId", latestId);
|
||||
field_to_json(Obj,"image", image);
|
||||
field_to_json(Obj,"imageDate", imageDate);
|
||||
field_to_json(Obj,"revision", revision);
|
||||
field_to_json(Obj,"uri", uri);
|
||||
field_to_json(Obj,"age", age);
|
||||
field_to_json(Obj,"latest",latest);
|
||||
}
|
||||
|
||||
bool FirmwareAgeDetails::from_json(const Poco::JSON::Object::Ptr &Obj) {
|
||||
try {
|
||||
field_from_json(Obj,"latestId", latestId);
|
||||
field_from_json(Obj,"image", image);
|
||||
field_from_json(Obj,"imageDate", imageDate);
|
||||
field_from_json(Obj,"revision", revision);
|
||||
field_from_json(Obj,"uri", uri);
|
||||
field_from_json(Obj,"age", age);
|
||||
field_from_json(Obj,"latest", latest);
|
||||
return true;
|
||||
} catch(...) {
|
||||
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void DeviceConnectionInformation::to_json(Poco::JSON::Object &Obj) const {
|
||||
field_to_json(Obj, "serialNumber", serialNumber);
|
||||
field_to_json(Obj, "revision", revision);
|
||||
field_to_json(Obj, "deviceType", deviceType);
|
||||
field_to_json(Obj, "endPoint", endPoint);
|
||||
field_to_json(Obj, "lastUpdate", lastUpdate);
|
||||
field_to_json(Obj, "status", status);
|
||||
}
|
||||
|
||||
bool DeviceConnectionInformation::from_json(const Poco::JSON::Object::Ptr &Obj) {
|
||||
try {
|
||||
field_from_json(Obj, "serialNumber", serialNumber);
|
||||
field_from_json(Obj, "revision", revision);
|
||||
field_from_json(Obj, "deviceType", deviceType);
|
||||
field_from_json(Obj, "endPoint", endPoint);
|
||||
field_from_json(Obj, "lastUpdate", lastUpdate);
|
||||
field_from_json(Obj, "status", status);
|
||||
return true;
|
||||
} catch(...) {
|
||||
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void DeviceReport::to_json(Poco::JSON::Object &Obj) const {
|
||||
field_to_json(Obj, "ouis",OUI_);
|
||||
field_to_json(Obj, "revisions", Revisions_);
|
||||
field_to_json(Obj, "deviceTypes", DeviceTypes_);
|
||||
field_to_json(Obj, "status", Status_);
|
||||
field_to_json(Obj, "endPoints", EndPoints_);
|
||||
field_to_json(Obj, "usingLatest", UsingLatest_);
|
||||
field_to_json(Obj, "unknownFirmwares", UnknownFirmwares_);
|
||||
field_to_json(Obj,"snapshot",snapshot);
|
||||
field_to_json(Obj,"numberOfDevices",numberOfDevices);
|
||||
field_to_json(Obj, "totalSecondsOld", totalSecondsOld_);
|
||||
}
|
||||
|
||||
void DeviceReport::reset() {
|
||||
OUI_.clear();
|
||||
Revisions_.clear();
|
||||
DeviceTypes_.clear();
|
||||
Status_.clear();
|
||||
EndPoints_.clear();
|
||||
UsingLatest_.clear();
|
||||
UnknownFirmwares_.clear();
|
||||
totalSecondsOld_.clear();
|
||||
numberOfDevices = 0 ;
|
||||
snapshot = std::time(nullptr);
|
||||
}
|
||||
|
||||
bool DeviceReport::from_json(const Poco::JSON::Object::Ptr &Obj) {
|
||||
try {
|
||||
|
||||
return true;
|
||||
} catch (...) {
|
||||
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
133
src/RESTObjects/RESTAPI_FMSObjects.h
Normal file
133
src/RESTObjects/RESTAPI_FMSObjects.h
Normal file
@@ -0,0 +1,133 @@
|
||||
//
|
||||
// Created by stephane bourque on 2021-07-12.
|
||||
//
|
||||
|
||||
#include <string>
|
||||
|
||||
#ifndef UCENTRALFMS_RESTAPI_FMSOBJECTS_H
|
||||
#define UCENTRALFMS_RESTAPI_FMSOBJECTS_H
|
||||
|
||||
|
||||
#include "RESTAPI_SecurityObjects.h"
|
||||
#include "framework/OpenWifiTypes.h"
|
||||
|
||||
namespace OpenWifi::FMSObjects {
|
||||
|
||||
struct Firmware {
|
||||
std::string id;
|
||||
std::string release;
|
||||
std::string deviceType;
|
||||
std::string description;
|
||||
std::string revision;
|
||||
std::string uri;
|
||||
std::string image;
|
||||
uint64_t imageDate=0;
|
||||
uint64_t size=0;
|
||||
uint64_t downloadCount=0;
|
||||
std::string firmwareHash;
|
||||
std::string owner;
|
||||
std::string location;
|
||||
std::string uploader;
|
||||
std::string digest;
|
||||
bool latest=false;
|
||||
SecurityObjects::NoteInfoVec notes;
|
||||
uint64_t created=0;
|
||||
|
||||
void to_json(Poco::JSON::Object &Obj) const;
|
||||
bool from_json(const Poco::JSON::Object::Ptr &Obj);
|
||||
};
|
||||
typedef std::vector<Firmware> FirmwareVec;
|
||||
|
||||
struct FirmwareList {
|
||||
FirmwareVec firmwares;
|
||||
|
||||
void to_json(Poco::JSON::Object &Obj) const;
|
||||
bool from_json(const Poco::JSON::Object::Ptr &Obj);
|
||||
};
|
||||
|
||||
struct DeviceType {
|
||||
std::string id;
|
||||
std::string deviceType;
|
||||
std::string manufacturer;
|
||||
std::string model;
|
||||
std::string policy;
|
||||
SecurityObjects::NoteInfoVec notes;
|
||||
uint64_t lastUpdate=0;
|
||||
uint64_t created=0;
|
||||
|
||||
void to_json(Poco::JSON::Object &Obj) const;
|
||||
bool from_json(const Poco::JSON::Object::Ptr &Obj);
|
||||
};
|
||||
typedef std::vector<DeviceType> DeviceTypeVec;
|
||||
|
||||
struct DeviceTypeList {
|
||||
DeviceTypeVec deviceTypes;
|
||||
|
||||
void to_json(Poco::JSON::Object &Obj) const;
|
||||
bool from_json(const Poco::JSON::Object::Ptr &Obj);
|
||||
};
|
||||
|
||||
struct RevisionHistoryEntry {
|
||||
std::string id;
|
||||
std::string serialNumber;
|
||||
std::string fromRelease;
|
||||
std::string toRelease;
|
||||
std::string commandUUID;
|
||||
std::string revisionId;
|
||||
uint64_t upgraded;
|
||||
|
||||
void to_json(Poco::JSON::Object &Obj) const;
|
||||
bool from_json(const Poco::JSON::Object::Ptr &Obj);
|
||||
};
|
||||
typedef std::vector<RevisionHistoryEntry> RevisionHistoryEntryVec;
|
||||
|
||||
struct RevisionHistoryEntryList {
|
||||
RevisionHistoryEntryVec history;
|
||||
|
||||
void to_json(Poco::JSON::Object &Obj) const;
|
||||
bool from_json(const Poco::JSON::Object::Ptr &Obj);
|
||||
};
|
||||
|
||||
struct FirmwareAgeDetails {
|
||||
std::string latestId;
|
||||
std::string image;
|
||||
uint64_t imageDate;
|
||||
std::string revision;
|
||||
std::string uri;
|
||||
uint64_t age=0;
|
||||
bool latest=true;
|
||||
|
||||
void to_json(Poco::JSON::Object &Obj) const;
|
||||
bool from_json(const Poco::JSON::Object::Ptr &Obj);
|
||||
};
|
||||
|
||||
struct DeviceConnectionInformation {
|
||||
std::string serialNumber;
|
||||
std::string revision;
|
||||
std::string deviceType;
|
||||
std::string endPoint;
|
||||
uint64_t lastUpdate;
|
||||
std::string status;
|
||||
void to_json(Poco::JSON::Object &Obj) const;
|
||||
bool from_json(const Poco::JSON::Object::Ptr &Obj);
|
||||
};
|
||||
|
||||
struct DeviceReport {
|
||||
uint64_t snapshot=0;
|
||||
uint64_t numberOfDevices=0;
|
||||
Types::CountedMap OUI_;
|
||||
Types::CountedMap Revisions_;
|
||||
Types::CountedMap DeviceTypes_;
|
||||
Types::CountedMap Status_;
|
||||
Types::CountedMap EndPoints_;
|
||||
Types::CountedMap UsingLatest_;
|
||||
Types::CountedMap UnknownFirmwares_;
|
||||
Types::CountedMap totalSecondsOld_;
|
||||
void to_json(Poco::JSON::Object &Obj) const;
|
||||
void reset();
|
||||
bool from_json(const Poco::JSON::Object::Ptr &Obj);
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
#endif //UCENTRALFMS_RESTAPI_FMSOBJECTS_H
|
||||
@@ -15,9 +15,7 @@
|
||||
#endif
|
||||
|
||||
#include "RESTAPI_GWobjects.h"
|
||||
#include "RESTAPI_handler.h"
|
||||
#include "RESTAPI_utils.h"
|
||||
#include "Utils.h"
|
||||
#include "framework/MicroService.h"
|
||||
|
||||
using OpenWifi::RESTAPI_utils::field_to_json;
|
||||
using OpenWifi::RESTAPI_utils::field_from_json;
|
||||
@@ -70,7 +68,7 @@ namespace OpenWifi::GWObjects {
|
||||
#endif
|
||||
}
|
||||
|
||||
bool Device::from_json(Poco::JSON::Object::Ptr Obj) {
|
||||
bool Device::from_json(Poco::JSON::Object::Ptr &Obj) {
|
||||
try {
|
||||
field_from_json(Obj,"serialNumber",SerialNumber);
|
||||
field_from_json(Obj,"deviceType",DeviceType);
|
||||
@@ -149,7 +147,7 @@ namespace OpenWifi::GWObjects {
|
||||
field_to_json(Obj,"attachFile", AttachDate);
|
||||
}
|
||||
|
||||
bool DefaultConfiguration::from_json(Poco::JSON::Object::Ptr Obj) {
|
||||
bool DefaultConfiguration::from_json(Poco::JSON::Object::Ptr &Obj) {
|
||||
try {
|
||||
field_from_json(Obj,"name",Name);
|
||||
field_from_json(Obj,"configuration",Configuration);
|
||||
@@ -162,10 +160,22 @@ namespace OpenWifi::GWObjects {
|
||||
}
|
||||
|
||||
void BlackListedDevice::to_json(Poco::JSON::Object &Obj) const {
|
||||
field_to_json(Obj,"serialNumber", SerialNumber);
|
||||
field_to_json(Obj,"author", Author);
|
||||
field_to_json(Obj,"reason", Reason);
|
||||
field_to_json(Obj,"created", Created);
|
||||
field_to_json(Obj,"serialNumber", serialNumber);
|
||||
field_to_json(Obj,"author", author);
|
||||
field_to_json(Obj,"reason", reason);
|
||||
field_to_json(Obj,"created", created);
|
||||
}
|
||||
|
||||
bool BlackListedDevice::from_json(Poco::JSON::Object::Ptr &Obj) {
|
||||
try {
|
||||
field_from_json(Obj,"serialNumber",serialNumber);
|
||||
field_from_json(Obj,"author",author);
|
||||
field_from_json(Obj,"reason",reason);
|
||||
field_from_json(Obj,"created",created);
|
||||
return true;
|
||||
} catch (const Poco::Exception &E) {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void ConnectionState::to_json(Poco::JSON::Object &Obj) const {
|
||||
@@ -243,5 +253,11 @@ namespace OpenWifi::GWObjects {
|
||||
numberOfDevices = 0 ;
|
||||
snapshot = std::time(nullptr);
|
||||
}
|
||||
|
||||
void CapabilitiesModel::to_json(Poco::JSON::Object &Obj) const{
|
||||
field_to_json(Obj,"deviceType", deviceType);
|
||||
field_to_json(Obj,"capabilities", capabilities);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -59,7 +59,7 @@ namespace OpenWifi::GWObjects {
|
||||
std::string DevicePassword;
|
||||
void to_json(Poco::JSON::Object &Obj) const;
|
||||
void to_json_with_status(Poco::JSON::Object &Obj) const;
|
||||
bool from_json(Poco::JSON::Object::Ptr Obj);
|
||||
bool from_json(Poco::JSON::Object::Ptr &Obj);
|
||||
void Print() const;
|
||||
};
|
||||
|
||||
@@ -116,7 +116,7 @@ namespace OpenWifi::GWObjects {
|
||||
uint64_t Created;
|
||||
uint64_t LastModified;
|
||||
void to_json(Poco::JSON::Object &Obj) const;
|
||||
bool from_json(Poco::JSON::Object::Ptr Obj);
|
||||
bool from_json(Poco::JSON::Object::Ptr &Obj);
|
||||
};
|
||||
|
||||
struct CommandDetails {
|
||||
@@ -142,11 +142,12 @@ namespace OpenWifi::GWObjects {
|
||||
};
|
||||
|
||||
struct BlackListedDevice {
|
||||
std::string SerialNumber;
|
||||
std::string Reason;
|
||||
std::string Author;
|
||||
uint64_t Created;
|
||||
std::string serialNumber;
|
||||
std::string reason;
|
||||
std::string author;
|
||||
uint64_t created;
|
||||
void to_json(Poco::JSON::Object &Obj) const;
|
||||
bool from_json(Poco::JSON::Object::Ptr &Obj);
|
||||
};
|
||||
|
||||
struct RttySessionDetails {
|
||||
@@ -182,6 +183,13 @@ namespace OpenWifi::GWObjects {
|
||||
void to_json(Poco::JSON::Object &Obj) const;
|
||||
void reset();
|
||||
};
|
||||
|
||||
struct CapabilitiesModel {
|
||||
std::string deviceType;
|
||||
std::string capabilities;
|
||||
|
||||
void to_json(Poco::JSON::Object &Obj) const;
|
||||
};
|
||||
}
|
||||
|
||||
#endif //UCENTRAL_RESTAPI_OBJECTS_H
|
||||
569
src/RESTObjects/RESTAPI_ProvObjects.cpp
Normal file
569
src/RESTObjects/RESTAPI_ProvObjects.cpp
Normal file
@@ -0,0 +1,569 @@
|
||||
//
|
||||
// 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 "RESTAPI_ProvObjects.h"
|
||||
#include "framework/MicroService.h"
|
||||
|
||||
using OpenWifi::RESTAPI_utils::field_to_json;
|
||||
using OpenWifi::RESTAPI_utils::field_from_json;
|
||||
|
||||
namespace OpenWifi::ProvObjects {
|
||||
|
||||
void ObjectInfo::to_json(Poco::JSON::Object &Obj) const {
|
||||
field_to_json(Obj,"id",id);
|
||||
field_to_json(Obj,"name",name);
|
||||
field_to_json(Obj,"description",description);
|
||||
field_to_json(Obj,"created",created);
|
||||
field_to_json(Obj,"modified",modified);
|
||||
field_to_json(Obj,"notes",notes);
|
||||
field_to_json(Obj,"tags",tags);
|
||||
}
|
||||
|
||||
bool ObjectInfo::from_json(const Poco::JSON::Object::Ptr &Obj) {
|
||||
try {
|
||||
field_from_json(Obj,"id",id);
|
||||
field_from_json(Obj,"name",name);
|
||||
field_from_json(Obj,"description",description);
|
||||
field_from_json(Obj,"created",created);
|
||||
field_from_json(Obj,"modified",modified);
|
||||
field_from_json(Obj,"notes",notes);
|
||||
field_from_json(Obj,"tags",tags);
|
||||
return true;
|
||||
} catch(...) {
|
||||
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void ManagementPolicyEntry::to_json(Poco::JSON::Object &Obj) const {
|
||||
field_to_json( Obj,"users",users);
|
||||
field_to_json( Obj,"resources",resources);
|
||||
field_to_json( Obj,"access",access);
|
||||
field_to_json( Obj,"policy",policy);
|
||||
}
|
||||
|
||||
bool ManagementPolicyEntry::from_json(const Poco::JSON::Object::Ptr &Obj) {
|
||||
try {
|
||||
field_from_json( Obj,"users",users);
|
||||
field_from_json( Obj,"resources",resources);
|
||||
field_from_json( Obj,"access",access);
|
||||
field_from_json( Obj,"policy",policy);
|
||||
return true;
|
||||
} catch(...) {
|
||||
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void ManagementPolicy::to_json(Poco::JSON::Object &Obj) const {
|
||||
info.to_json(Obj);
|
||||
field_to_json(Obj, "entries", entries);
|
||||
field_to_json(Obj, "inUse", inUse);
|
||||
field_to_json(Obj, "entity", entity);
|
||||
}
|
||||
|
||||
bool ManagementPolicy::from_json(const Poco::JSON::Object::Ptr &Obj) {
|
||||
try {
|
||||
info.from_json(Obj);
|
||||
field_from_json(Obj, "entries", entries);
|
||||
field_from_json(Obj, "inUse", inUse);
|
||||
field_from_json(Obj, "entity", entity);
|
||||
return true;
|
||||
} catch(...) {
|
||||
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void Entity::to_json(Poco::JSON::Object &Obj) const {
|
||||
info.to_json(Obj);
|
||||
field_to_json( Obj,"parent",parent);
|
||||
field_to_json( Obj,"venues",venues);
|
||||
field_to_json( Obj,"children",children);
|
||||
field_to_json( Obj,"contacts",contacts);
|
||||
field_to_json( Obj,"locations",locations);
|
||||
field_to_json( Obj,"managementPolicy",managementPolicy);
|
||||
field_to_json( Obj,"deviceConfiguration",deviceConfiguration);
|
||||
field_to_json( Obj,"devices",devices);
|
||||
field_to_json( Obj,"rrm",rrm);
|
||||
field_to_json( Obj,"sourceIP",sourceIP);
|
||||
}
|
||||
|
||||
bool Entity::from_json(const Poco::JSON::Object::Ptr &Obj) {
|
||||
try {
|
||||
info.from_json(Obj);
|
||||
field_from_json( Obj,"parent",parent);
|
||||
field_from_json( Obj,"venues",venues);
|
||||
field_from_json( Obj,"children",children);
|
||||
field_from_json( Obj,"contacts",contacts);
|
||||
field_from_json( Obj,"locations",locations);
|
||||
field_from_json( Obj,"managementPolicy",managementPolicy);
|
||||
field_from_json( Obj,"deviceConfiguration",deviceConfiguration);
|
||||
field_from_json( Obj,"devices",devices);
|
||||
field_from_json( Obj,"rrm",rrm);
|
||||
field_from_json( Obj,"sourceIP",sourceIP);
|
||||
return true;
|
||||
} catch(...) {
|
||||
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void DiGraphEntry::to_json(Poco::JSON::Object &Obj) const {
|
||||
field_to_json( Obj,"parent",parent);
|
||||
field_to_json( Obj,"child",child);
|
||||
}
|
||||
|
||||
bool DiGraphEntry::from_json(const Poco::JSON::Object::Ptr &Obj) {
|
||||
try {
|
||||
field_from_json( Obj,"parent",parent);
|
||||
field_from_json( Obj,"child",child);
|
||||
return true;
|
||||
} catch (...) {
|
||||
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void Venue::to_json(Poco::JSON::Object &Obj) const {
|
||||
info.to_json(Obj);
|
||||
field_to_json( Obj,"parent",parent);
|
||||
field_to_json( Obj,"entity",entity);
|
||||
field_to_json( Obj,"children",children);
|
||||
field_to_json( Obj,"devices",devices);
|
||||
field_to_json( Obj,"topology",topology);
|
||||
field_to_json( Obj,"parent",parent);
|
||||
field_to_json( Obj,"design",design);
|
||||
field_to_json( Obj,"managementPolicy",managementPolicy);
|
||||
field_to_json( Obj,"deviceConfiguration",deviceConfiguration);
|
||||
field_to_json( Obj,"contact",contact);
|
||||
field_to_json( Obj,"location",location);
|
||||
field_to_json( Obj,"rrm",rrm);
|
||||
field_to_json( Obj,"sourceIP",sourceIP);
|
||||
}
|
||||
|
||||
bool Venue::from_json(const Poco::JSON::Object::Ptr &Obj) {
|
||||
try {
|
||||
info.from_json(Obj);
|
||||
field_from_json( Obj,"parent",parent);
|
||||
field_from_json( Obj,"entity",entity);
|
||||
field_from_json( Obj,"children",children);
|
||||
field_from_json( Obj,"devices",devices);
|
||||
field_from_json( Obj,"topology",topology);
|
||||
field_from_json( Obj,"parent",parent);
|
||||
field_from_json( Obj,"design",design);
|
||||
field_from_json( Obj,"managementPolicy",managementPolicy);
|
||||
field_from_json( Obj,"deviceConfiguration",deviceConfiguration);
|
||||
field_from_json( Obj,"contact",contact);
|
||||
field_from_json( Obj,"location",location);
|
||||
field_from_json( Obj,"rrm",rrm);
|
||||
field_from_json( Obj,"sourceIP",sourceIP);
|
||||
return true;
|
||||
} catch (...) {
|
||||
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void UserInfoDigest::to_json(Poco::JSON::Object &Obj) const {
|
||||
field_to_json( Obj,"id",id);
|
||||
field_to_json( Obj,"entity",loginId);
|
||||
field_to_json( Obj,"children",userType);
|
||||
}
|
||||
|
||||
bool UserInfoDigest::from_json(const Poco::JSON::Object::Ptr &Obj) {
|
||||
try {
|
||||
field_from_json( Obj,"id",id);
|
||||
field_from_json( Obj,"entity",loginId);
|
||||
field_from_json( Obj,"children",userType);
|
||||
return true;
|
||||
} catch(...) {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void ManagementRole::to_json(Poco::JSON::Object &Obj) const {
|
||||
info.to_json(Obj);
|
||||
field_to_json( Obj,"managementPolicy",managementPolicy);
|
||||
field_to_json( Obj,"users",users);
|
||||
field_to_json( Obj,"entity",entity);
|
||||
}
|
||||
|
||||
bool ManagementRole::from_json(const Poco::JSON::Object::Ptr &Obj) {
|
||||
try {
|
||||
info.from_json(Obj);
|
||||
field_from_json( Obj,"managementPolicy",managementPolicy);
|
||||
field_from_json( Obj,"users",users);
|
||||
field_from_json( Obj,"entity",entity);
|
||||
return true;
|
||||
} catch(...) {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void Location::to_json(Poco::JSON::Object &Obj) const {
|
||||
info.to_json(Obj);
|
||||
field_to_json( Obj,"type",OpenWifi::ProvObjects::to_string(type));
|
||||
field_to_json( Obj,"buildingName",buildingName);
|
||||
field_to_json( Obj,"addressLines",addressLines);
|
||||
field_to_json( Obj,"city",city);
|
||||
field_to_json( Obj,"state",state);
|
||||
field_to_json( Obj,"postal",postal);
|
||||
field_to_json( Obj,"country",country);
|
||||
field_to_json( Obj,"phones",phones);
|
||||
field_to_json( Obj,"mobiles",mobiles);
|
||||
field_to_json( Obj,"geoCode",geoCode);
|
||||
field_to_json( Obj,"inUse",inUse);
|
||||
field_to_json( Obj,"entity",entity);
|
||||
field_to_json( Obj,"managementPolicy",managementPolicy);
|
||||
}
|
||||
|
||||
bool Location::from_json(const Poco::JSON::Object::Ptr &Obj) {
|
||||
try {
|
||||
info.from_json(Obj);
|
||||
std::string tmp_type;
|
||||
field_from_json( Obj,"type", tmp_type);
|
||||
type = location_from_string(tmp_type);
|
||||
field_from_json( Obj,"buildingName",buildingName);
|
||||
field_from_json( Obj,"addressLines",addressLines);
|
||||
field_from_json( Obj,"city",city);
|
||||
field_from_json( Obj,"state",state);
|
||||
field_from_json( Obj,"postal",postal);
|
||||
field_from_json( Obj,"country",country);
|
||||
field_from_json( Obj,"phones",phones);
|
||||
field_from_json( Obj,"mobiles",mobiles);
|
||||
field_from_json( Obj,"geoCode",geoCode);
|
||||
field_from_json( Obj,"inUse",inUse);
|
||||
field_from_json( Obj,"entity",entity);
|
||||
field_from_json( Obj,"managementPolicy",managementPolicy);
|
||||
return true;
|
||||
} catch (...) {
|
||||
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void Contact::to_json(Poco::JSON::Object &Obj) const {
|
||||
info.to_json(Obj);
|
||||
field_to_json( Obj,"type", to_string(type));
|
||||
field_to_json( Obj,"title",title);
|
||||
field_to_json( Obj,"salutation",salutation);
|
||||
field_to_json( Obj,"firstname",firstname);
|
||||
field_to_json( Obj,"lastname",lastname);
|
||||
field_to_json( Obj,"initials",initials);
|
||||
field_to_json( Obj,"visual",visual);
|
||||
field_to_json( Obj,"mobiles",mobiles);
|
||||
field_to_json( Obj,"phones",phones);
|
||||
field_to_json( Obj,"primaryEmail",primaryEmail);
|
||||
field_to_json( Obj,"secondaryEmail",secondaryEmail);
|
||||
field_to_json( Obj,"accessPIN",accessPIN);
|
||||
field_to_json( Obj,"inUse",inUse);
|
||||
field_to_json( Obj,"entity",entity);
|
||||
field_to_json( Obj,"managementPolicy",managementPolicy);
|
||||
}
|
||||
|
||||
bool Contact::from_json(const Poco::JSON::Object::Ptr &Obj) {
|
||||
try {
|
||||
info.from_json(Obj);
|
||||
std::string tmp_type;
|
||||
field_from_json( Obj,"type", tmp_type);
|
||||
type = contact_from_string(tmp_type);
|
||||
field_from_json( Obj,"title",title);
|
||||
field_from_json( Obj,"salutation",salutation);
|
||||
field_from_json( Obj,"firstname",firstname);
|
||||
field_from_json( Obj,"lastname",lastname);
|
||||
field_from_json( Obj,"initials",initials);
|
||||
field_from_json( Obj,"visual",visual);
|
||||
field_from_json( Obj,"mobiles",mobiles);
|
||||
field_from_json( Obj,"phones",phones);
|
||||
field_from_json( Obj,"primaryEmail",primaryEmail);
|
||||
field_from_json( Obj,"secondaryEmail",secondaryEmail);
|
||||
field_from_json( Obj,"accessPIN",accessPIN);
|
||||
field_from_json( Obj,"inUse",inUse);
|
||||
field_from_json( Obj,"entity",entity);
|
||||
field_from_json( Obj,"managementPolicy",managementPolicy);
|
||||
return true;
|
||||
} catch (...) {
|
||||
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void InventoryTag::to_json(Poco::JSON::Object &Obj) const {
|
||||
info.to_json(Obj);
|
||||
field_to_json(Obj, "serialNumber", serialNumber);
|
||||
field_to_json(Obj, "venue", venue);
|
||||
field_to_json(Obj, "entity", entity);
|
||||
field_to_json(Obj, "subscriber", subscriber);
|
||||
field_to_json(Obj, "deviceType", deviceType);
|
||||
field_to_json(Obj, "qrCode", qrCode);
|
||||
field_to_json(Obj, "geoCode", geoCode);
|
||||
field_to_json(Obj, "location", location);
|
||||
field_to_json(Obj, "contact", contact);
|
||||
field_to_json( Obj,"deviceConfiguration",deviceConfiguration);
|
||||
field_to_json( Obj,"rrm",rrm);
|
||||
field_to_json( Obj,"managementPolicy",managementPolicy);
|
||||
}
|
||||
|
||||
bool InventoryTag::from_json(const Poco::JSON::Object::Ptr &Obj) {
|
||||
try {
|
||||
info.from_json(Obj);
|
||||
field_from_json( Obj,"serialNumber",serialNumber);
|
||||
field_from_json( Obj,"venue",venue);
|
||||
field_from_json( Obj,"entity",entity);
|
||||
field_from_json( Obj,"subscriber",subscriber);
|
||||
field_from_json( Obj,"deviceType",deviceType);
|
||||
field_from_json(Obj, "qrCode", qrCode);
|
||||
field_from_json( Obj,"geoCode",geoCode);
|
||||
field_from_json( Obj,"location",location);
|
||||
field_from_json( Obj,"contact",contact);
|
||||
field_from_json( Obj,"deviceConfiguration",deviceConfiguration);
|
||||
field_from_json( Obj,"rrm",rrm);
|
||||
field_from_json( Obj,"managementPolicy",managementPolicy);
|
||||
return true;
|
||||
} catch(...) {
|
||||
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void DeviceConfigurationElement::to_json(Poco::JSON::Object &Obj) const {
|
||||
field_to_json( Obj,"name", name);
|
||||
field_to_json( Obj,"description", description);
|
||||
field_to_json( Obj,"weight", weight);
|
||||
field_to_json( Obj,"configuration", configuration);
|
||||
}
|
||||
|
||||
bool DeviceConfigurationElement::from_json(const Poco::JSON::Object::Ptr &Obj) {
|
||||
try {
|
||||
field_from_json( Obj,"name",name);
|
||||
field_from_json( Obj,"description",description);
|
||||
field_from_json( Obj,"weight",weight);
|
||||
field_from_json( Obj,"configuration",configuration);
|
||||
return true;
|
||||
} catch(...) {
|
||||
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void DeviceConfiguration::to_json(Poco::JSON::Object &Obj) const {
|
||||
info.to_json(Obj);
|
||||
field_to_json( Obj,"managementPolicy",managementPolicy);
|
||||
field_to_json( Obj,"deviceTypes",deviceTypes);
|
||||
field_to_json( Obj,"configuration",configuration);
|
||||
field_to_json( Obj,"inUse",inUse);
|
||||
field_to_json( Obj,"variables",variables);
|
||||
field_to_json( Obj,"rrm",rrm);
|
||||
field_to_json( Obj,"firmwareUpgrade",firmwareUpgrade);
|
||||
field_to_json( Obj,"firmwareRCOnly",firmwareRCOnly);
|
||||
}
|
||||
|
||||
bool DeviceConfiguration::from_json(const Poco::JSON::Object::Ptr &Obj) {
|
||||
try {
|
||||
info.from_json(Obj);
|
||||
field_from_json( Obj,"managementPolicy",managementPolicy);
|
||||
field_from_json( Obj,"deviceTypes",deviceTypes);
|
||||
field_from_json( Obj,"configuration",configuration);
|
||||
field_from_json( Obj,"inUse",inUse);
|
||||
field_from_json( Obj,"variables",variables);
|
||||
field_from_json( Obj,"rrm",rrm);
|
||||
field_from_json( Obj,"firmwareUpgrade",firmwareUpgrade);
|
||||
field_from_json( Obj,"firmwareRCOnly",firmwareRCOnly);
|
||||
return true;
|
||||
} catch(...) {
|
||||
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void Report::to_json(Poco::JSON::Object &Obj) const {
|
||||
field_to_json(Obj, "snapshot", snapShot);
|
||||
field_to_json(Obj, "devices", tenants);
|
||||
};
|
||||
|
||||
void Report::reset() {
|
||||
tenants.clear();
|
||||
}
|
||||
|
||||
void ExpandedUseEntry::to_json(Poco::JSON::Object &Obj) const {
|
||||
field_to_json(Obj, "uuid", uuid);
|
||||
field_to_json(Obj, "name", name);
|
||||
field_to_json(Obj, "description", description);
|
||||
}
|
||||
|
||||
bool ExpandedUseEntry::from_json(const Poco::JSON::Object::Ptr &Obj) {
|
||||
try {
|
||||
field_from_json( Obj,"uuid",uuid);
|
||||
field_from_json( Obj,"name",name);
|
||||
field_from_json( Obj,"description",description);
|
||||
return true;
|
||||
} catch(...) {
|
||||
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void ExpandedUseEntryList::to_json(Poco::JSON::Object &Obj) const {
|
||||
field_to_json(Obj, "type", type);
|
||||
field_to_json(Obj, "entries", entries);
|
||||
}
|
||||
|
||||
bool ExpandedUseEntryList::from_json(const Poco::JSON::Object::Ptr &Obj) {
|
||||
try {
|
||||
field_from_json( Obj,"type",type);
|
||||
field_from_json( Obj,"entries",entries);
|
||||
return true;
|
||||
} catch(...) {
|
||||
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void ExpandedUseEntryMapList::to_json(Poco::JSON::Object &Obj) const {
|
||||
field_to_json(Obj, "entries", entries);
|
||||
}
|
||||
|
||||
bool ExpandedUseEntryMapList::from_json(const Poco::JSON::Object::Ptr &Obj) {
|
||||
try {
|
||||
field_from_json( Obj,"entries",entries);
|
||||
return true;
|
||||
} catch(...) {
|
||||
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void UserList::to_json(Poco::JSON::Object &Obj) const {
|
||||
field_to_json(Obj, "list", list);
|
||||
}
|
||||
|
||||
bool UserList::from_json(const Poco::JSON::Object::Ptr &Obj) {
|
||||
try {
|
||||
field_from_json(Obj, "list", list);
|
||||
return true;
|
||||
} catch(...) {
|
||||
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void ObjectACL::to_json(Poco::JSON::Object &Obj) const {
|
||||
field_to_json(Obj, "users", users);
|
||||
field_to_json(Obj, "access", access);
|
||||
}
|
||||
|
||||
bool ObjectACL::from_json(const Poco::JSON::Object::Ptr &Obj) {
|
||||
try {
|
||||
field_from_json(Obj, "users", users);
|
||||
field_from_json(Obj, "access", access);
|
||||
return true;
|
||||
} catch(...) {
|
||||
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void ObjectACLList::to_json(Poco::JSON::Object &Obj) const {
|
||||
field_to_json(Obj, "list", list);
|
||||
}
|
||||
|
||||
bool ObjectACLList::from_json(const Poco::JSON::Object::Ptr &Obj) {
|
||||
try {
|
||||
field_from_json(Obj, "list", list);
|
||||
return true;
|
||||
} catch(...) {
|
||||
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void Map::to_json(Poco::JSON::Object &Obj) const {
|
||||
info.to_json(Obj);
|
||||
field_to_json( Obj,"data",data);
|
||||
field_to_json( Obj,"entity",entity);
|
||||
field_to_json( Obj,"creator",creator);
|
||||
field_to_json( Obj,"visibility",visibility);
|
||||
field_to_json( Obj,"access",access);
|
||||
}
|
||||
|
||||
bool Map::from_json(const Poco::JSON::Object::Ptr &Obj) {
|
||||
try {
|
||||
info.from_json(Obj);
|
||||
field_from_json( Obj,"data",data);
|
||||
field_from_json( Obj,"entity",entity);
|
||||
field_from_json( Obj,"creator",creator);
|
||||
field_from_json( Obj,"visibility",visibility);
|
||||
field_from_json( Obj,"access",access);
|
||||
return true;
|
||||
} catch(...) {
|
||||
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void MapList::to_json(Poco::JSON::Object &Obj) const {
|
||||
field_to_json( Obj,"list",list);
|
||||
}
|
||||
|
||||
bool MapList::from_json(const Poco::JSON::Object::Ptr &Obj) {
|
||||
try {
|
||||
field_from_json( Obj,"list",list);
|
||||
return true;
|
||||
} catch(...) {
|
||||
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool UpdateObjectInfo(const Poco::JSON::Object::Ptr &O, const SecurityObjects::UserInfo &U, ObjectInfo &I) {
|
||||
uint64_t Now = std::time(nullptr);
|
||||
if(O->has("name"))
|
||||
I.name = O->get("name").toString();
|
||||
|
||||
if(I.name.empty())
|
||||
return false;
|
||||
|
||||
if(O->has("description"))
|
||||
I.description = O->get("description").toString();
|
||||
SecurityObjects::MergeNotes(O,U,I.notes);
|
||||
SecurityObjects::NoteInfoVec N;
|
||||
for(auto &i:I.notes) {
|
||||
if(i.note.empty())
|
||||
continue;
|
||||
N.push_back(SecurityObjects::NoteInfo{.created=Now,.createdBy=U.email,.note=i.note});
|
||||
}
|
||||
I.modified = Now;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CreateObjectInfo(const Poco::JSON::Object::Ptr &O, const SecurityObjects::UserInfo &U, ObjectInfo &I) {
|
||||
uint64_t Now = std::time(nullptr);
|
||||
if(O->has("name"))
|
||||
I.name = O->get("name").toString();
|
||||
|
||||
if(I.name.empty())
|
||||
return false;
|
||||
|
||||
if(O->has("description"))
|
||||
I.description = O->get("description").toString();
|
||||
|
||||
SecurityObjects::NoteInfoVec N;
|
||||
for(auto &i:I.notes) {
|
||||
if(i.note.empty())
|
||||
continue;
|
||||
N.push_back(SecurityObjects::NoteInfo{.created=Now,.createdBy=U.email,.note=i.note});
|
||||
}
|
||||
I.notes = N;
|
||||
I.modified = I.created = Now;
|
||||
I.id = MicroService::instance().CreateUUID();
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
374
src/RESTObjects/RESTAPI_ProvObjects.h
Normal file
374
src/RESTObjects/RESTAPI_ProvObjects.h
Normal file
@@ -0,0 +1,374 @@
|
||||
//
|
||||
// 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 OWPROV_RESTAPI_PROVOBJECTS_H
|
||||
#define OWPROV_RESTAPI_PROVOBJECTS_H
|
||||
|
||||
#include <string>
|
||||
#include "RESTAPI_SecurityObjects.h"
|
||||
|
||||
namespace OpenWifi::ProvObjects {
|
||||
|
||||
enum FIRMWARE_UPGRADE_RULES {
|
||||
dont_upgrade,
|
||||
upgrade_inherit,
|
||||
upgrade_release_only,
|
||||
upgrade_latest
|
||||
};
|
||||
|
||||
struct ObjectInfo {
|
||||
Types::UUID_t id;
|
||||
std::string name;
|
||||
std::string description;
|
||||
SecurityObjects::NoteInfoVec notes;
|
||||
uint64_t created=0;
|
||||
uint64_t modified=0;
|
||||
Types::TagList tags;
|
||||
|
||||
void to_json(Poco::JSON::Object &Obj) const;
|
||||
bool from_json(const Poco::JSON::Object::Ptr &Obj);
|
||||
};
|
||||
|
||||
struct ManagementPolicyEntry {
|
||||
Types::UUIDvec_t users;
|
||||
Types::UUIDvec_t resources;
|
||||
Types::StringVec access;
|
||||
std::string policy;
|
||||
|
||||
void to_json(Poco::JSON::Object &Obj) const;
|
||||
bool from_json(const Poco::JSON::Object::Ptr &Obj);
|
||||
};
|
||||
|
||||
struct ManagementPolicy {
|
||||
ObjectInfo info;
|
||||
std::vector<ManagementPolicyEntry> entries;
|
||||
Types::StringVec inUse;
|
||||
Types::UUID_t entity;
|
||||
|
||||
void to_json(Poco::JSON::Object &Obj) const;
|
||||
bool from_json(const Poco::JSON::Object::Ptr &Obj);
|
||||
};
|
||||
typedef std::vector<ManagementPolicy> ManagementPolicyVec;
|
||||
|
||||
struct Entity {
|
||||
ObjectInfo info;
|
||||
Types::UUID_t parent;
|
||||
Types::UUIDvec_t children;
|
||||
Types::UUIDvec_t venues;
|
||||
Types::UUIDvec_t contacts; // all contacts associated in this entity
|
||||
Types::UUIDvec_t locations; // all locations associated in this entity
|
||||
Types::UUID_t managementPolicy;
|
||||
Types::UUIDvec_t deviceConfiguration;
|
||||
Types::UUIDvec_t devices;
|
||||
std::string rrm;
|
||||
Types::StringVec sourceIP;
|
||||
|
||||
void to_json(Poco::JSON::Object &Obj) const;
|
||||
bool from_json(const Poco::JSON::Object::Ptr &Obj);
|
||||
};
|
||||
typedef std::vector<Entity> EntityVec;
|
||||
|
||||
struct DiGraphEntry {
|
||||
Types::UUID_t parent;
|
||||
Types::UUID_t child;
|
||||
|
||||
void to_json(Poco::JSON::Object &Obj) const;
|
||||
bool from_json(const Poco::JSON::Object::Ptr &Obj);
|
||||
};
|
||||
|
||||
typedef std::vector<DiGraphEntry> DiGraph;
|
||||
|
||||
struct Venue {
|
||||
ObjectInfo info;
|
||||
Types::UUID_t entity;
|
||||
Types::UUID_t parent;
|
||||
Types::UUIDvec_t children;
|
||||
Types::UUID_t managementPolicy;
|
||||
Types::UUIDvec_t devices;
|
||||
DiGraph topology;
|
||||
std::string design;
|
||||
Types::UUIDvec_t deviceConfiguration;
|
||||
std::string contact;
|
||||
std::string location;
|
||||
std::string rrm;
|
||||
Types::StringVec sourceIP;
|
||||
|
||||
void to_json(Poco::JSON::Object &Obj) const;
|
||||
bool from_json(const Poco::JSON::Object::Ptr &Obj);
|
||||
};
|
||||
typedef std::vector<Venue> VenueVec;
|
||||
|
||||
struct UserInfoDigest {
|
||||
std::string id;
|
||||
std::string loginId;
|
||||
std::string userType;
|
||||
|
||||
void to_json(Poco::JSON::Object &Obj) const;
|
||||
bool from_json(const Poco::JSON::Object::Ptr &Obj);
|
||||
};
|
||||
|
||||
struct ManagementRole {
|
||||
ObjectInfo info;
|
||||
Types::UUID_t managementPolicy;
|
||||
Types::UUIDvec_t users;
|
||||
Types::StringVec inUse;
|
||||
Types::UUID_t entity;
|
||||
|
||||
void to_json(Poco::JSON::Object &Obj) const;
|
||||
bool from_json(const Poco::JSON::Object::Ptr &Obj);
|
||||
};
|
||||
typedef std::vector<ManagementRole> ManagementRoleVec;
|
||||
|
||||
enum LocationType {
|
||||
LT_SERVICE, LT_EQUIPMENT, LT_AUTO, LT_MANUAL,
|
||||
LT_SPECIAL, LT_UNKNOWN, LT_CORPORATE
|
||||
};
|
||||
|
||||
inline std::string to_string(LocationType L) {
|
||||
switch(L) {
|
||||
case LT_SERVICE: return "SERVICE";
|
||||
case LT_EQUIPMENT: return "EQUIPMENT";
|
||||
case LT_AUTO: return "AUTO";
|
||||
case LT_MANUAL: return "MANUAL";
|
||||
case LT_SPECIAL: return "SPECIAL";
|
||||
case LT_UNKNOWN: return "UNKNOWN";
|
||||
case LT_CORPORATE: return "CORPORATE";
|
||||
default: return "UNKNOWN";
|
||||
}
|
||||
}
|
||||
|
||||
inline LocationType location_from_string(const std::string &S) {
|
||||
if(!Poco::icompare(S,"SERVICE"))
|
||||
return LT_SERVICE;
|
||||
else if(!Poco::icompare(S,"EQUIPMENT"))
|
||||
return LT_EQUIPMENT;
|
||||
else if(!Poco::icompare(S,"AUTO"))
|
||||
return LT_AUTO;
|
||||
else if(!Poco::icompare(S,"MANUAL"))
|
||||
return LT_MANUAL;
|
||||
else if(!Poco::icompare(S,"SPECIAL"))
|
||||
return LT_SPECIAL;
|
||||
else if(!Poco::icompare(S,"UNKNOWN"))
|
||||
return LT_UNKNOWN;
|
||||
else if(!Poco::icompare(S,"CORPORATE"))
|
||||
return LT_CORPORATE;
|
||||
return LT_UNKNOWN;
|
||||
}
|
||||
|
||||
struct Location {
|
||||
ObjectInfo info;
|
||||
LocationType type;
|
||||
std::string buildingName;
|
||||
Types::StringVec addressLines;
|
||||
std::string city;
|
||||
std::string state;
|
||||
std::string postal;
|
||||
std::string country;
|
||||
Types::StringVec phones;
|
||||
Types::StringVec mobiles;
|
||||
std::string geoCode;
|
||||
Types::StringVec inUse;
|
||||
Types::UUID_t entity;
|
||||
Types::UUID_t managementPolicy;
|
||||
|
||||
void to_json(Poco::JSON::Object &Obj) const;
|
||||
bool from_json(const Poco::JSON::Object::Ptr &Obj);
|
||||
};
|
||||
typedef std::vector<Location> LocationVec;
|
||||
|
||||
enum ContactType {
|
||||
CT_SUBSCRIBER, CT_USER, CT_INSTALLER, CT_CSR, CT_MANAGER,
|
||||
CT_BUSINESSOWNER, CT_TECHNICIAN, CT_CORPORATE, CT_UNKNOWN
|
||||
};
|
||||
|
||||
inline std::string to_string(ContactType L) {
|
||||
switch(L) {
|
||||
case CT_SUBSCRIBER: return "SUBSCRIBER";
|
||||
case CT_USER: return "USER";
|
||||
case CT_INSTALLER: return "INSTALLER";
|
||||
case CT_CSR: return "CSR";
|
||||
case CT_MANAGER: return "MANAGER";
|
||||
case CT_BUSINESSOWNER: return "BUSINESSOWNER";
|
||||
case CT_TECHNICIAN: return "TECHNICIAN";
|
||||
case CT_CORPORATE: return "CORPORATE";
|
||||
case CT_UNKNOWN: return "UNKNOWN";
|
||||
default: return "UNKNOWN";
|
||||
}
|
||||
}
|
||||
|
||||
inline ContactType contact_from_string(const std::string &S) {
|
||||
if(!Poco::icompare(S,"SUBSCRIBER"))
|
||||
return CT_SUBSCRIBER;
|
||||
else if(!Poco::icompare(S,"USER"))
|
||||
return CT_USER;
|
||||
else if(!Poco::icompare(S,"INSTALLER"))
|
||||
return CT_INSTALLER;
|
||||
else if(!Poco::icompare(S,"CSR"))
|
||||
return CT_CSR;
|
||||
else if(!Poco::icompare(S,"BUSINESSOWNER"))
|
||||
return CT_BUSINESSOWNER;
|
||||
else if(!Poco::icompare(S,"TECHNICIAN"))
|
||||
return CT_TECHNICIAN;
|
||||
else if(!Poco::icompare(S,"CORPORATE"))
|
||||
return CT_CORPORATE;
|
||||
else if(!Poco::icompare(S,"UNKNOWN"))
|
||||
return CT_UNKNOWN;
|
||||
return CT_UNKNOWN;
|
||||
}
|
||||
|
||||
struct Contact {
|
||||
ObjectInfo info;
|
||||
ContactType type=CT_USER;
|
||||
std::string title;
|
||||
std::string salutation;
|
||||
std::string firstname;
|
||||
std::string lastname;
|
||||
std::string initials;
|
||||
std::string visual;
|
||||
Types::StringVec mobiles;
|
||||
Types::StringVec phones;
|
||||
std::string primaryEmail;
|
||||
std::string secondaryEmail;
|
||||
std::string accessPIN;
|
||||
Types::StringVec inUse;
|
||||
Types::UUID_t entity;
|
||||
Types::UUID_t managementPolicy;
|
||||
|
||||
void to_json(Poco::JSON::Object &Obj) const;
|
||||
bool from_json(const Poco::JSON::Object::Ptr &Obj);
|
||||
};
|
||||
typedef std::vector<Contact> ContactVec;
|
||||
|
||||
struct DeviceConfigurationElement {
|
||||
std::string name;
|
||||
std::string description;
|
||||
uint64_t weight;
|
||||
std::string configuration;
|
||||
|
||||
void to_json(Poco::JSON::Object &Obj) const;
|
||||
bool from_json(const Poco::JSON::Object::Ptr &Obj);
|
||||
};
|
||||
typedef std::vector<DeviceConfigurationElement> DeviceConfigurationElementVec;
|
||||
|
||||
struct DeviceConfiguration {
|
||||
ObjectInfo info;
|
||||
Types::UUID_t managementPolicy;
|
||||
Types::StringVec deviceTypes;
|
||||
DeviceConfigurationElementVec configuration;
|
||||
Types::StringVec inUse;
|
||||
Types::StringPairVec variables;
|
||||
std::string rrm;
|
||||
std::string firmwareUpgrade;
|
||||
bool firmwareRCOnly=false;
|
||||
|
||||
void to_json(Poco::JSON::Object &Obj) const;
|
||||
bool from_json(const Poco::JSON::Object::Ptr &Obj);
|
||||
};
|
||||
typedef std::vector<DeviceConfiguration> DeviceConfigurationVec;
|
||||
|
||||
struct InventoryTag {
|
||||
ObjectInfo info;
|
||||
std::string serialNumber;
|
||||
std::string venue;
|
||||
std::string entity;
|
||||
std::string subscriber;
|
||||
std::string deviceType;
|
||||
std::string qrCode;
|
||||
std::string geoCode;
|
||||
std::string location;
|
||||
std::string contact;
|
||||
std::string deviceConfiguration;
|
||||
std::string rrm;
|
||||
Types::UUID_t managementPolicy;
|
||||
|
||||
void to_json(Poco::JSON::Object &Obj) const;
|
||||
bool from_json(const Poco::JSON::Object::Ptr &Obj);
|
||||
};
|
||||
typedef std::vector<InventoryTag> InventoryTagVec;
|
||||
|
||||
struct Report {
|
||||
uint64_t snapShot=0;
|
||||
Types::CountedMap tenants;
|
||||
|
||||
void reset();
|
||||
void to_json(Poco::JSON::Object &Obj) const;
|
||||
};
|
||||
|
||||
struct ExpandedUseEntry {
|
||||
std::string uuid;
|
||||
std::string name;
|
||||
std::string description;
|
||||
|
||||
void to_json(Poco::JSON::Object &Obj) const;
|
||||
bool from_json(const Poco::JSON::Object::Ptr &Obj);
|
||||
};
|
||||
|
||||
struct ExpandedUseEntryList {
|
||||
std::string type;
|
||||
std::vector<ExpandedUseEntry> entries;
|
||||
|
||||
void to_json(Poco::JSON::Object &Obj) const;
|
||||
bool from_json(const Poco::JSON::Object::Ptr &Obj);
|
||||
};
|
||||
|
||||
struct ExpandedUseEntryMapList {
|
||||
std::vector<ExpandedUseEntryList> entries;
|
||||
|
||||
void to_json(Poco::JSON::Object &Obj) const;
|
||||
bool from_json(const Poco::JSON::Object::Ptr &Obj);
|
||||
};
|
||||
|
||||
struct UserList {
|
||||
std::vector<std::string> list;
|
||||
|
||||
void to_json(Poco::JSON::Object &Obj) const;
|
||||
bool from_json(const Poco::JSON::Object::Ptr &Obj);
|
||||
};
|
||||
|
||||
struct ObjectACL {
|
||||
UserList users;
|
||||
std::string access;
|
||||
|
||||
void to_json(Poco::JSON::Object &Obj) const;
|
||||
bool from_json(const Poco::JSON::Object::Ptr &Obj);
|
||||
};
|
||||
|
||||
struct ObjectACLList {
|
||||
std::vector<ObjectACL> list;
|
||||
|
||||
void to_json(Poco::JSON::Object &Obj) const;
|
||||
bool from_json(const Poco::JSON::Object::Ptr &Obj);
|
||||
};
|
||||
|
||||
struct Map {
|
||||
ObjectInfo info;
|
||||
std::string data;
|
||||
std::string entity;
|
||||
std::string creator;
|
||||
std::string visibility;
|
||||
ObjectACLList access;
|
||||
|
||||
void to_json(Poco::JSON::Object &Obj) const;
|
||||
bool from_json(const Poco::JSON::Object::Ptr &Obj);
|
||||
};
|
||||
|
||||
struct MapList {
|
||||
std::vector<Map> list;
|
||||
|
||||
void to_json(Poco::JSON::Object &Obj) const;
|
||||
bool from_json(const Poco::JSON::Object::Ptr &Obj);
|
||||
};
|
||||
|
||||
bool UpdateObjectInfo(const Poco::JSON::Object::Ptr &O, const SecurityObjects::UserInfo &U, ObjectInfo &I);
|
||||
bool CreateObjectInfo(const Poco::JSON::Object::Ptr &O, const SecurityObjects::UserInfo &U, ObjectInfo &I);
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif //OWPROV_RESTAPI_PROVOBJECTS_H
|
||||
@@ -9,8 +9,8 @@
|
||||
#include "Poco/JSON/Parser.h"
|
||||
#include "Poco/JSON/Stringifier.h"
|
||||
|
||||
#include "framework/MicroService.h"
|
||||
#include "RESTAPI_SecurityObjects.h"
|
||||
#include "RESTAPI_utils.h"
|
||||
|
||||
using OpenWifi::RESTAPI_utils::field_to_json;
|
||||
using OpenWifi::RESTAPI_utils::field_from_json;
|
||||
@@ -58,21 +58,28 @@ namespace OpenWifi::SecurityObjects {
|
||||
return CSR;
|
||||
else if (!Poco::icompare(U, "system"))
|
||||
return SYSTEM;
|
||||
else if (!Poco::icompare(U, "special"))
|
||||
return SPECIAL;
|
||||
else if (!Poco::icompare(U, "installer"))
|
||||
return INSTALLER;
|
||||
else if (!Poco::icompare(U, "noc"))
|
||||
return NOC;
|
||||
else if (!Poco::icompare(U, "accounting"))
|
||||
return ACCOUNTING;
|
||||
return UNKNOWN;
|
||||
}
|
||||
|
||||
std::string UserTypeToString(USER_ROLE U) {
|
||||
switch(U) {
|
||||
case UNKNOWN: return "unknown";
|
||||
case ROOT: return "root";
|
||||
case ADMIN: return "admin";
|
||||
case SUBSCRIBER: return "subscriber";
|
||||
case CSR: return "csr";
|
||||
case SYSTEM: return "system";
|
||||
case SPECIAL: return "special";
|
||||
case ADMIN: return "admin";
|
||||
default: return "unknown";
|
||||
case INSTALLER: return "installer";
|
||||
case NOC: return "noc";
|
||||
case ACCOUNTING: return "accounting";
|
||||
case UNKNOWN:
|
||||
default:
|
||||
return "unknown";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -125,6 +132,94 @@ namespace OpenWifi::SecurityObjects {
|
||||
return false;
|
||||
}
|
||||
|
||||
void MobilePhoneNumber::to_json(Poco::JSON::Object &Obj) const {
|
||||
field_to_json(Obj,"number", number);
|
||||
field_to_json(Obj,"verified", verified);
|
||||
field_to_json(Obj,"primary", primary);
|
||||
}
|
||||
|
||||
bool MobilePhoneNumber::from_json(Poco::JSON::Object::Ptr &Obj) {
|
||||
try {
|
||||
field_from_json(Obj,"number",number);
|
||||
field_from_json(Obj,"verified",verified);
|
||||
field_from_json(Obj,"primary",primary);
|
||||
return true;
|
||||
} catch (...) {
|
||||
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
void MfaAuthInfo::to_json(Poco::JSON::Object &Obj) const {
|
||||
field_to_json(Obj,"enabled", enabled);
|
||||
field_to_json(Obj,"method", method);
|
||||
}
|
||||
|
||||
bool MfaAuthInfo::from_json(Poco::JSON::Object::Ptr &Obj) {
|
||||
try {
|
||||
field_from_json(Obj,"enabled",enabled);
|
||||
field_from_json(Obj,"method",method);
|
||||
return true;
|
||||
} catch (...) {
|
||||
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void UserLoginLoginExtensions::to_json(Poco::JSON::Object &Obj) const {
|
||||
field_to_json(Obj, "mobiles", mobiles);
|
||||
field_to_json(Obj, "mfa", mfa);
|
||||
}
|
||||
|
||||
bool UserLoginLoginExtensions::from_json(Poco::JSON::Object::Ptr &Obj) {
|
||||
try {
|
||||
field_from_json(Obj,"mobiles",mobiles);
|
||||
field_from_json(Obj,"mfa",mfa);
|
||||
return true;
|
||||
} catch (...) {
|
||||
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void MFAChallengeRequest::to_json(Poco::JSON::Object &Obj) const {
|
||||
field_to_json(Obj, "uuid", uuid);
|
||||
field_to_json(Obj, "question", question);
|
||||
field_to_json(Obj, "created", created);
|
||||
field_to_json(Obj, "method", method);
|
||||
}
|
||||
|
||||
bool MFAChallengeRequest::from_json(Poco::JSON::Object::Ptr &Obj) {
|
||||
try {
|
||||
field_from_json(Obj,"uuid",uuid);
|
||||
field_from_json(Obj,"question",question);
|
||||
field_from_json(Obj,"created",created);
|
||||
field_from_json(Obj,"method",method);
|
||||
return true;
|
||||
} catch (...) {
|
||||
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
void MFAChallengeResponse::to_json(Poco::JSON::Object &Obj) const {
|
||||
field_to_json(Obj, "uuid", uuid);
|
||||
field_to_json(Obj, "answer", answer);
|
||||
|
||||
}
|
||||
|
||||
bool MFAChallengeResponse::from_json(Poco::JSON::Object::Ptr &Obj) {
|
||||
try {
|
||||
field_from_json(Obj,"uuid",uuid);
|
||||
field_from_json(Obj,"answer",answer);
|
||||
return true;
|
||||
} catch (...) {
|
||||
|
||||
}
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
void UserInfo::to_json(Poco::JSON::Object &Obj) const {
|
||||
field_to_json(Obj,"Id",Id);
|
||||
field_to_json(Obj,"name",name);
|
||||
@@ -292,40 +387,53 @@ namespace OpenWifi::SecurityObjects {
|
||||
field_to_json(Obj,"note", note);
|
||||
}
|
||||
|
||||
bool NoteInfo::from_json(Poco::JSON::Object::Ptr Obj) {
|
||||
bool NoteInfo::from_json(Poco::JSON::Object::Ptr &Obj) {
|
||||
try {
|
||||
field_from_json(Obj,"created",created);
|
||||
field_from_json(Obj,"createdBy",createdBy);
|
||||
field_from_json(Obj,"note",note);
|
||||
return true;
|
||||
} catch(...) {
|
||||
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool append_from_json(Poco::JSON::Object::Ptr Obj, const UserInfo &UInfo, NoteInfoVec & Notes) {
|
||||
bool MergeNotes(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);
|
||||
if(Obj->has("notes") && Obj->isArray("notes")) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
} catch(...) {
|
||||
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool MergeNotes(const NoteInfoVec & NewNotes, const UserInfo &UInfo, NoteInfoVec & ExistingNotes) {
|
||||
for(auto const &i:NewNotes) {
|
||||
SecurityObjects::NoteInfo ii{.created=(uint64_t)std::time(nullptr), .createdBy=UInfo.email, .note=i.note};
|
||||
ExistingNotes.push_back(ii);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void ProfileAction::to_json(Poco::JSON::Object &Obj) const {
|
||||
field_to_json(Obj,"resource", resource);
|
||||
field_to_json<ResourceAccessType>(Obj,"access", access, ResourceAccessTypeToString);
|
||||
}
|
||||
|
||||
bool ProfileAction::from_json(Poco::JSON::Object::Ptr Obj) {
|
||||
bool ProfileAction::from_json(Poco::JSON::Object::Ptr &Obj) {
|
||||
try {
|
||||
field_from_json(Obj,"resource",resource);
|
||||
field_from_json<ResourceAccessType>(Obj,"access",access,ResourceAccessTypeFromString );
|
||||
return true;
|
||||
} catch(...) {
|
||||
|
||||
}
|
||||
@@ -341,7 +449,7 @@ namespace OpenWifi::SecurityObjects {
|
||||
field_to_json(Obj,"notes", notes);
|
||||
}
|
||||
|
||||
bool SecurityProfile::from_json(Poco::JSON::Object::Ptr Obj) {
|
||||
bool SecurityProfile::from_json(Poco::JSON::Object::Ptr &Obj) {
|
||||
try {
|
||||
field_from_json(Obj,"id",id);
|
||||
field_from_json(Obj,"name",name);
|
||||
@@ -349,6 +457,7 @@ namespace OpenWifi::SecurityObjects {
|
||||
field_from_json(Obj,"policy",policy);
|
||||
field_from_json(Obj,"role",role);
|
||||
field_from_json(Obj,"notes",notes);
|
||||
return true;
|
||||
} catch(...) {
|
||||
|
||||
}
|
||||
@@ -359,13 +468,51 @@ namespace OpenWifi::SecurityObjects {
|
||||
field_to_json(Obj, "profiles", profiles);
|
||||
}
|
||||
|
||||
bool SecurityProfileList::from_json(Poco::JSON::Object::Ptr Obj) {
|
||||
bool SecurityProfileList::from_json(Poco::JSON::Object::Ptr &Obj) {
|
||||
try {
|
||||
field_from_json(Obj,"profiles",profiles);
|
||||
return true;
|
||||
} catch(...) {
|
||||
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void ActionLink::to_json(Poco::JSON::Object &Obj) const {
|
||||
field_to_json(Obj,"id",id);
|
||||
field_to_json(Obj,"action",action);
|
||||
field_to_json(Obj,"userId",userId);
|
||||
field_to_json(Obj,"actionTemplate",actionTemplate);
|
||||
field_to_json(Obj,"variables",variables);
|
||||
field_to_json(Obj,"locale",locale);
|
||||
field_to_json(Obj,"message",message);
|
||||
field_to_json(Obj,"sent",sent);
|
||||
field_to_json(Obj,"created",created);
|
||||
field_to_json(Obj,"expires",expires);
|
||||
field_to_json(Obj,"completed",completed);
|
||||
field_to_json(Obj,"canceled",canceled);
|
||||
|
||||
}
|
||||
|
||||
bool ActionLink::from_json(Poco::JSON::Object::Ptr &Obj) {
|
||||
try {
|
||||
field_from_json(Obj,"id",id);
|
||||
field_from_json(Obj,"action",action);
|
||||
field_from_json(Obj,"userId",userId);
|
||||
field_from_json(Obj,"actionTemplate",actionTemplate);
|
||||
field_from_json(Obj,"variables",variables);
|
||||
field_from_json(Obj,"locale",locale);
|
||||
field_from_json(Obj,"message",message);
|
||||
field_from_json(Obj,"sent",sent);
|
||||
field_from_json(Obj,"created",created);
|
||||
field_from_json(Obj,"expires",expires);
|
||||
field_from_json(Obj,"completed",completed);
|
||||
field_from_json(Obj,"canceled",canceled);
|
||||
return true;
|
||||
} catch(...) {
|
||||
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
#define UCENTRAL_RESTAPI_SECURITYOBJECTS_H
|
||||
|
||||
#include "Poco/JSON/Object.h"
|
||||
#include "OpenWifiTypes.h"
|
||||
#include "framework/OpenWifiTypes.h"
|
||||
|
||||
namespace OpenWifi::SecurityObjects {
|
||||
|
||||
@@ -42,7 +42,7 @@ namespace OpenWifi::SecurityObjects {
|
||||
};
|
||||
|
||||
enum USER_ROLE {
|
||||
UNKNOWN, ROOT, ADMIN, SUBSCRIBER, CSR, SYSTEM, SPECIAL
|
||||
UNKNOWN, ROOT, ADMIN, SUBSCRIBER, CSR, SYSTEM, INSTALLER, NOC, ACCOUNTING
|
||||
};
|
||||
|
||||
USER_ROLE UserTypeFromString(const std::string &U);
|
||||
@@ -53,10 +53,53 @@ namespace OpenWifi::SecurityObjects {
|
||||
std::string createdBy;
|
||||
std::string note;
|
||||
void to_json(Poco::JSON::Object &Obj) const;
|
||||
bool from_json(Poco::JSON::Object::Ptr Obj);
|
||||
bool from_json(Poco::JSON::Object::Ptr &Obj);
|
||||
};
|
||||
typedef std::vector<NoteInfo> NoteInfoVec;
|
||||
|
||||
struct MobilePhoneNumber {
|
||||
std::string number;
|
||||
bool verified = false;
|
||||
bool primary = false;
|
||||
|
||||
void to_json(Poco::JSON::Object &Obj) const;
|
||||
bool from_json(Poco::JSON::Object::Ptr &Obj);
|
||||
};
|
||||
|
||||
struct MfaAuthInfo {
|
||||
bool enabled = false;
|
||||
std::string method;
|
||||
|
||||
void to_json(Poco::JSON::Object &Obj) const;
|
||||
bool from_json(Poco::JSON::Object::Ptr &Obj);
|
||||
};
|
||||
|
||||
struct UserLoginLoginExtensions {
|
||||
std::vector<MobilePhoneNumber> mobiles;
|
||||
struct MfaAuthInfo mfa;
|
||||
|
||||
void to_json(Poco::JSON::Object &Obj) const;
|
||||
bool from_json(Poco::JSON::Object::Ptr &Obj);
|
||||
};
|
||||
|
||||
struct MFAChallengeRequest {
|
||||
std::string uuid;
|
||||
std::string question;
|
||||
std::string method;
|
||||
uint64_t created = std::time(nullptr);
|
||||
|
||||
void to_json(Poco::JSON::Object &Obj) const;
|
||||
bool from_json(Poco::JSON::Object::Ptr &Obj);
|
||||
};
|
||||
|
||||
struct MFAChallengeResponse {
|
||||
std::string uuid;
|
||||
std::string answer;
|
||||
|
||||
void to_json(Poco::JSON::Object &Obj) const;
|
||||
bool from_json(Poco::JSON::Object::Ptr &Obj);
|
||||
};
|
||||
|
||||
struct UserInfo {
|
||||
std::string Id;
|
||||
std::string name;
|
||||
@@ -81,7 +124,7 @@ namespace OpenWifi::SecurityObjects {
|
||||
bool suspended = false;
|
||||
bool blackListed = false;
|
||||
USER_ROLE userRole;
|
||||
std::string userTypeProprietaryInfo;
|
||||
UserLoginLoginExtensions userTypeProprietaryInfo;
|
||||
std::string securityPolicy;
|
||||
uint64_t securityPolicyChange = 0 ;
|
||||
std::string currentPassword;
|
||||
@@ -94,7 +137,9 @@ namespace OpenWifi::SecurityObjects {
|
||||
};
|
||||
typedef std::vector<UserInfo> UserInfoVec;
|
||||
|
||||
bool append_from_json(Poco::JSON::Object::Ptr Obj, const UserInfo &UInfo, NoteInfoVec & Notes);
|
||||
// bool append_from_json(Poco::JSON::Object::Ptr Obj, const UserInfo &UInfo, NoteInfoVec & Notes);
|
||||
bool MergeNotes(Poco::JSON::Object::Ptr Obj, const UserInfo &UInfo, NoteInfoVec & Notes);
|
||||
bool MergeNotes(const NoteInfoVec & NewNotes, const UserInfo &UInfo, NoteInfoVec & ExistingNotes);
|
||||
|
||||
struct InternalServiceInfo {
|
||||
std::string privateURI;
|
||||
@@ -155,7 +200,7 @@ namespace OpenWifi::SecurityObjects {
|
||||
std::string resource;
|
||||
ResourceAccessType access;
|
||||
void to_json(Poco::JSON::Object &Obj) const;
|
||||
bool from_json(Poco::JSON::Object::Ptr Obj);
|
||||
bool from_json(Poco::JSON::Object::Ptr &Obj);
|
||||
};
|
||||
typedef std::vector<ProfileAction> ProfileActionVec;
|
||||
|
||||
@@ -167,14 +212,37 @@ namespace OpenWifi::SecurityObjects {
|
||||
std::string role;
|
||||
NoteInfoVec notes;
|
||||
void to_json(Poco::JSON::Object &Obj) const;
|
||||
bool from_json(Poco::JSON::Object::Ptr Obj);
|
||||
bool from_json(Poco::JSON::Object::Ptr &Obj);
|
||||
};
|
||||
typedef std::vector<SecurityProfile> SecurityProfileVec;
|
||||
|
||||
struct SecurityProfileList {
|
||||
SecurityProfileVec profiles;
|
||||
void to_json(Poco::JSON::Object &Obj) const;
|
||||
bool from_json(Poco::JSON::Object::Ptr Obj);
|
||||
bool from_json(Poco::JSON::Object::Ptr &Obj);
|
||||
};
|
||||
|
||||
enum LinkActions {
|
||||
FORGOT_PASSWORD=1,
|
||||
VERIFY_EMAIL
|
||||
};
|
||||
|
||||
struct ActionLink {
|
||||
std::string id;
|
||||
uint64_t action;
|
||||
std::string userId;
|
||||
std::string actionTemplate;
|
||||
Types::StringPairVec variables;
|
||||
std::string locale;
|
||||
std::string message;
|
||||
uint64_t sent=0;
|
||||
uint64_t created=std::time(nullptr);
|
||||
uint64_t expires=0;
|
||||
uint64_t completed=0;
|
||||
uint64_t canceled=0;
|
||||
|
||||
void to_json(Poco::JSON::Object &Obj) const;
|
||||
bool from_json(Poco::JSON::Object::Ptr &Obj);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -5,15 +5,12 @@
|
||||
#include "SerialNumberCache.h"
|
||||
#include <mutex>
|
||||
|
||||
#include "Utils.h"
|
||||
#include "StorageService.h"
|
||||
|
||||
namespace OpenWifi {
|
||||
|
||||
class SerialNumberCache * SerialNumberCache::instance_ = nullptr;
|
||||
|
||||
int SerialNumberCache::Start() {
|
||||
Storage()->UpdateSerialNumberCache();
|
||||
StorageService()->UpdateSerialNumberCache();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -5,16 +5,14 @@
|
||||
#ifndef UCENTRALGW_SERIALNUMBERCACHE_H
|
||||
#define UCENTRALGW_SERIALNUMBERCACHE_H
|
||||
|
||||
#include "SubSystemServer.h"
|
||||
#include "framework/MicroService.h"
|
||||
|
||||
namespace OpenWifi {
|
||||
class SerialNumberCache : public SubSystemServer {
|
||||
public:
|
||||
|
||||
static SerialNumberCache *instance() {
|
||||
if (instance_ == nullptr) {
|
||||
instance_ = new SerialNumberCache;
|
||||
}
|
||||
static SerialNumberCache * instance() {
|
||||
static SerialNumberCache * instance_ = new SerialNumberCache;
|
||||
return instance_;
|
||||
}
|
||||
|
||||
@@ -23,9 +21,13 @@ namespace OpenWifi {
|
||||
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);
|
||||
inline bool NumberExists(const std::string &S) {
|
||||
std::lock_guard G(M_);
|
||||
uint64_t SN = std::stoull(S,0,16);
|
||||
return std::find(SNs_.begin(),SNs_.end(),SN)!=SNs_.end();
|
||||
}
|
||||
|
||||
private:
|
||||
static SerialNumberCache * instance_;
|
||||
uint64_t LastUpdate_ = 0 ;
|
||||
std::vector<uint64_t> SNs_;
|
||||
std::mutex M_;
|
||||
|
||||
@@ -13,49 +13,43 @@ namespace OpenWifi {
|
||||
try {
|
||||
UpdatesSinceLastWrite_++;
|
||||
// get the interfaces section
|
||||
if(O->has("interfaces")) {
|
||||
auto IFaces = O->get("interfaces");
|
||||
if(IFaces.isArray()) {
|
||||
auto IFaceObjs = IFaces.extract<Poco::JSON::Array::Ptr>();
|
||||
for (auto const &i : *IFaceObjs) {
|
||||
auto Interface = i.extract<Poco::JSON::Object::Ptr>();
|
||||
if (Interface->has("name") && Interface->has("counters")) {
|
||||
auto InterfaceName = Interface->get("name").toString();
|
||||
auto InterfaceMapEntry = Stats_.find(InterfaceName);
|
||||
if(InterfaceMapEntry == Stats_.end()) {
|
||||
std::map<std::string,uint64_t> NewStatEntry;
|
||||
Stats_[InterfaceName] = NewStatEntry;
|
||||
InterfaceMapEntry = Stats_.find(InterfaceName);
|
||||
}
|
||||
|
||||
auto CountersObj = Interface->get("counters").extract<Poco::JSON::Object::Ptr>();
|
||||
Poco::DynamicStruct CounterVars = *CountersObj;
|
||||
|
||||
for (const auto &j : CounterVars) {
|
||||
auto Entry = InterfaceMapEntry->second.find(j.first);
|
||||
if(Entry==InterfaceMapEntry->second.end()) {
|
||||
InterfaceMapEntry->second[j.first] = j.second;
|
||||
} else {
|
||||
InterfaceMapEntry->second[j.first] += j.second;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
if(O->has("interfaces") && O->isArray("interfaces")) {
|
||||
auto IFaces = O->getArray("interfaces");
|
||||
for (auto const &i : *IFaces) {
|
||||
auto Interface = i.extract<Poco::JSON::Object::Ptr>();
|
||||
if (Interface->has("name") && Interface->has("counters")) {
|
||||
auto InterfaceName = Interface->get("name").toString();
|
||||
auto InterfaceMapEntry = Stats_.find(InterfaceName);
|
||||
if(InterfaceMapEntry == Stats_.end()) {
|
||||
std::map<std::string,uint64_t> NewStatEntry;
|
||||
Stats_[InterfaceName] = NewStatEntry;
|
||||
InterfaceMapEntry = Stats_.find(InterfaceName);
|
||||
}
|
||||
auto CountersObj = Interface->getObject("counters");
|
||||
for (const auto &j : *CountersObj) {
|
||||
auto Entry = InterfaceMapEntry->second.find(j.first);
|
||||
if(Entry==InterfaceMapEntry->second.end()) {
|
||||
InterfaceMapEntry->second[j.first] = j.second;
|
||||
} else {
|
||||
InterfaceMapEntry->second[j.first] += j.second;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
if(Conn_)
|
||||
GetAssociations(O,Conn_->Associations_2G,Conn_->Associations_5G);
|
||||
|
||||
if(UpdatesSinceLastWrite_>10)
|
||||
Save();
|
||||
return true;
|
||||
}
|
||||
|
||||
if(Conn_)
|
||||
GetAssociations(O,Conn_->Conn_.Associations_2G,Conn_->Conn_.Associations_5G);
|
||||
|
||||
if(UpdatesSinceLastWrite_>10)
|
||||
Save();
|
||||
return true;
|
||||
} else {
|
||||
std::cout << "No interfaces section" << std::endl;
|
||||
Logger_.information(Poco::format("DEVICE(%s): State is missing interfaces",SerialNumber_));
|
||||
}
|
||||
} catch (const Poco::Exception &E ) {
|
||||
std::cout << "Exception0.. " << E.displayText() << " " << E.what() << std::endl;
|
||||
Logger_.log(E);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -67,7 +61,7 @@ namespace OpenWifi {
|
||||
const auto & Result = ParsedMessage.extract<Poco::JSON::Object::Ptr>();
|
||||
return Add(Result);
|
||||
} catch (const Poco::Exception &E) {
|
||||
std::cout << "Exception1.." << std::endl;
|
||||
Logger_.log(E);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -82,12 +76,6 @@ namespace OpenWifi {
|
||||
}
|
||||
|
||||
void StateProcessor::to_json(Poco::JSON::Object & Obj) const {
|
||||
/* interfaces: [
|
||||
name:
|
||||
counters: {
|
||||
|
||||
}
|
||||
*/
|
||||
Poco::JSON::Array Interfaces;
|
||||
for(const auto & Interface: Stats_) {
|
||||
Poco::JSON::Object InnerObj;
|
||||
@@ -121,7 +109,7 @@ namespace OpenWifi {
|
||||
UpdatesSinceLastWrite_ = 0;
|
||||
Stats_.clear();
|
||||
std::string Stats;
|
||||
if(Storage()->GetLifetimeStats(SerialNumber,Stats)) {
|
||||
if(StorageService()->GetLifetimeStats(SerialNumber,Stats)) {
|
||||
Add(Stats);
|
||||
return true;
|
||||
}
|
||||
@@ -131,7 +119,7 @@ namespace OpenWifi {
|
||||
bool StateProcessor::Save() {
|
||||
UpdatesSinceLastWrite_ = 0;
|
||||
std::string StatsToSave = toString();
|
||||
return Storage()->SetLifetimeStats(SerialNumber_, StatsToSave);
|
||||
return StorageService()->SetLifetimeStats(SerialNumber_, StatsToSave);
|
||||
}
|
||||
|
||||
static int ChannelToBand(uint64_t C) {
|
||||
@@ -151,7 +139,16 @@ namespace OpenWifi {
|
||||
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"));
|
||||
if(RadioObj->isArray("channel")) {
|
||||
auto ChannelArray = RadioObj->getArray("channel");
|
||||
if(ChannelArray->size()) {
|
||||
RadioPHYs[RadioObj->get("phy").toString()] =
|
||||
ChannelToBand( ChannelArray->getElement<uint64_t>(0) );
|
||||
}
|
||||
} else {
|
||||
RadioPHYs[RadioObj->get("phy").toString()] =
|
||||
ChannelToBand(RadioObj->get("channel"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user