Merge branch 'master' into WIFI-10581-switch-images-to-debian-slim

This commit is contained in:
Stephane Bourque
2022-10-02 09:47:21 -07:00
committed by GitHub
88 changed files with 3810 additions and 1797 deletions

View File

@@ -49,7 +49,7 @@ if(GIT_FOUND AND EXISTS "${PROJECT_SOURCE_DIR}/.git")
string(REGEX REPLACE "\n$" "" GIT_HASH "${GIT_HASH}") string(REGEX REPLACE "\n$" "" GIT_HASH "${GIT_HASH}")
endif() endif()
add_definitions(-DTIP_GATEWAY_SERVICE="1") add_definitions(-DTIP_GATEWAY_SERVICE="1" -DPOCO_LOG_DEBUG="1")
find_package(OpenSSL REQUIRED) find_package(OpenSSL REQUIRED)
find_package(ZLIB REQUIRED) find_package(ZLIB REQUIRED)
@@ -132,7 +132,7 @@ add_executable( owgw
src/AP_WS_Process_state.cpp src/AP_WS_Process_state.cpp
src/AP_WS_Process_healthcheck.cpp src/AP_WS_Process_healthcheck.cpp
src/AP_WS_Process_log.cpp src/AP_WS_Process_log.cpp
src/AP_WS_Process_crashlog.cpp src/AP_WS_Process_ping.cpp src/AP_WS_Process_cfgpending.cpp src/AP_WS_Process_recovery.cpp src/AP_WS_Process_deviceupdate.cpp src/AP_WS_Process_telemetry.cpp src/AP_WS_Process_venuebroadcast.cpp) src/AP_WS_Process_crashlog.cpp src/AP_WS_Process_ping.cpp src/AP_WS_Process_cfgpending.cpp src/AP_WS_Process_recovery.cpp src/AP_WS_Process_deviceupdate.cpp src/AP_WS_Process_telemetry.cpp src/AP_WS_Process_venuebroadcast.cpp src/RADSECserver.h)
if(NOT SMALL_BUILD) if(NOT SMALL_BUILD)

View File

@@ -8,7 +8,7 @@ FROM debian:$DEBIAN_VERSION AS build-base
RUN apt-get update && apt-get install --no-install-recommends -y \ RUN apt-get update && apt-get install --no-install-recommends -y \
make cmake g++ git \ make cmake g++ git \
unixodbc-dev libpq-dev libmariadb-dev libmariadbclient-dev-compat \ libpq-dev libmariadb-dev libmariadbclient-dev-compat \
librdkafka-dev libboost-all-dev libssl-dev \ librdkafka-dev libboost-all-dev libssl-dev \
zlib1g-dev nlohmann-json3-dev ca-certificates zlib1g-dev nlohmann-json3-dev ca-certificates

View File

@@ -18,17 +18,29 @@ System messages are what maintains the collection of micro-services working on t
} }
``` ```
### Responsibilities
Each micro service is responsible to generate its own messages and keep track of messages coming from other
micro services. This is necessary so that any micro service may reach our any other micro service. This provides
discovery for any micro service. All current micro services provided in OpenWiFi perform these functions. If you leverage
the C++ framework, this functionality if performed automatically.
### `event-type` ### `event-type`
When a service joins the bus, it should generate an event-type of `join`. When a service shutdown, it should generate a `leave` event-type. Every 30 seconds, a service Each micro service is responsible to generate and consume these events
should generate a `keep-alive` message.
#### `join` event
When a service start and joins the bus, it should generate an event-type of `join`.
### `leave` event
When a service shuts down, it should generate a `leave` event-type.
### `keep-alive` event
Every 30 seconds, a service should generate a `keep-alive` message.
### `id` ### `id`
You should generate a random number from some unique factor for the system. This ID is used to identify different services. You should reuse that ID You should generate a random number from some unique factor for the system. This ID is used to identify different services. You should reuse that ID
when you restart. when you restart.
## Micro-service maintaining bus state
A micro-service should maintain its own lists of available micro-services by looking at the messages it receives and keep a list.
## The `type` ## The `type`
The `type` in the system message is oen of the following: The `type` in the system message is oen of the following:
```c++ ```c++
@@ -47,11 +59,11 @@ The `type` in the system message is oen of the following:
The `type` is what you should use to find the `privateEndPoint` you are looking to communicate with. The `type` is what you should use to find the `privateEndPoint` you are looking to communicate with.
### Example ### Example
Assume you want to communicate with the gateway t pconfigure a device. Assume you want to communicate with the gateway to configure a device.
```text ```text
1. Look into my list of current Micro-services for the type=owgw. 1. Look into my list of current Micro-services for the type=owgw.
2. Use the priovateEndPoint associated with that entry 2. Use the privateEndPoint associated with that entry
``` ```
## REST API calls on the private interface ## REST API calls on the private interface
@@ -72,9 +84,9 @@ This is the `publicEndPoint` you included in your `system-messages`.
This method can _only_ be used to any another `privateEndPoint` in the system. You can use the exact same EndPoints provided in the OpenAPI files for any of the services. This method can _only_ be used to any another `privateEndPoint` in the system. You can use the exact same EndPoints provided in the OpenAPI files for any of the services.
## OpenAPI Integration ## OpenAPI Integration
To appear in the UI consoles, a micro-service should ne able to handle a get to the `/api/v1/system` endpoint on its `publicEndPoint` interface. To appear in the UI consoles, a microservice should be able to handle a get to the `/api/v1/system` endpoint on its `publicEndPoint` interface.
Here is a brief description of what the micro-service should answer: Here is a brief description of what the microservice should answer:
```yaml ```yaml
/system: /system:
get: get:

View File

@@ -11,16 +11,16 @@ In order to build the uCentralGW, you will need to install its dependencies, whi
- boost - boost
- POCO 1.10.1 or later - POCO 1.10.1 or later
- a C++17 compiler - a C++17 compiler
- libyaml
- openssl - openssl
- libpq-dev (PortgreSQL development libraries) - libpq-dev (PortgreSQL development libraries)
- mysql-client (MySQL client) - mysql-client (MySQL client)
- librdkafka - librdkafka
- cppkafka - cppkafka
-
The build is done in 2 parts. The first part is to build a local copy of the framework tailored to your environment. This The build is done in 2 parts. The first part is to build a local copy of the framework tailored to your environment. This
framework is called [Poco](https://github.com/pocoproject/poco). The version used in this project has a couple of fixes framework is called [Poco](https://github.com/pocoproject/poco). The version used in this project has a couple of fixes
from the master copy needed for cmake. Please use the version of this [Poco fix](https://github.com/stephb9959/poco). Building from the master copy needed for cmake. Please use the version of this [Poco fix](https://github.com/AriliaWireless/poco). Building
Poco may take several minutes depending on the platform you are building on. Poco may take several minutes depending on the platform you are building on.
### Ubuntu ### Ubuntu
@@ -58,6 +58,14 @@ cmake ..
make -j make -j
sudo make install sudo make install
git clone https://github.com/fmtlib/fmt --branch 9.0.0 /fmtlib
cd fmtlib
mkdir cmake-build
cd cmake-build
cmake ..
make
make install
cd ~ cd ~
git clone https://github.com/Telecominfraproject/wlan-cloud-ucentralgw git clone https://github.com/Telecominfraproject/wlan-cloud-ucentralgw
cd wlan-cloud-ucentralgw cd wlan-cloud-ucentralgw

2
build
View File

@@ -1 +1 @@
41 125

View File

@@ -38,7 +38,12 @@ if [[ "$TEMPLATE_CONFIG" = 'true' ]]; then
SYSTEM_URI_PRIVATE=${SYSTEM_URI_PRIVATE:-"https://localhost:17002"} \ SYSTEM_URI_PRIVATE=${SYSTEM_URI_PRIVATE:-"https://localhost:17002"} \
SYSTEM_URI_PUBLIC=${SYSTEM_URI_PUBLIC:-"https://localhost:16002"} \ SYSTEM_URI_PUBLIC=${SYSTEM_URI_PUBLIC:-"https://localhost:16002"} \
SYSTEM_URI_UI=${SYSTEM_URI_UI:-"http://localhost"} \ SYSTEM_URI_UI=${SYSTEM_URI_UI:-"http://localhost"} \
SECURITY_RESTAPI_DISABLE=${SECURITY_RESTAPI_DISABLE:-"false"} \
SIMULATORID=${SIMULATORID:-""} \ SIMULATORID=${SIMULATORID:-""} \
IPTOCOUNTRY_PROVIDER=${IPTOCOUNTRY_PROVIDER:-"ipinfo"} \
IPTOCOUNTRY_IPINFO_TOKEN=${IPTOCOUNTRY_IPINFO_TOKEN:-""} \
IPTOCOUNTRY_IPDATA_APIKEY=${IPTOCOUNTRY_IPDATA_APIKEY:-""} \
AUTOPROVISIONING_PROCESS=${AUTOPROVISIONING_PROCESS:-"prov,default"} \
RTTY_INTERNAL=${RTTY_INTERNAL:-"true"} \ RTTY_INTERNAL=${RTTY_INTERNAL:-"true"} \
RTTY_ENABLED=${RTTY_ENABLED:-"true"} \ RTTY_ENABLED=${RTTY_ENABLED:-"true"} \
RTTY_SERVER=${RTTY_SERVER:-"localhost"} \ RTTY_SERVER=${RTTY_SERVER:-"localhost"} \
@@ -47,6 +52,10 @@ if [[ "$TEMPLATE_CONFIG" = 'true' ]]; then
RTTY_TIMEOUT=${RTTY_TIMEOUT:-"60"} \ RTTY_TIMEOUT=${RTTY_TIMEOUT:-"60"} \
RTTY_VIEWPORT=${RTTY_VIEWPORT:-"5913"} \ RTTY_VIEWPORT=${RTTY_VIEWPORT:-"5913"} \
RTTY_ASSETS=${RTTY_ASSETS:-"\$OWGW_ROOT/rtty_ui"} \ RTTY_ASSETS=${RTTY_ASSETS:-"\$OWGW_ROOT/rtty_ui"} \
RADIUS_PROXY_ENABLE=${RADIUS_PROXY_ENABLE:-"false"} \
RADIUS_PROXY_ACCOUNTING_PORT=${RADIUS_PROXY_ACCOUNTING_PORT:-"1813"} \
RADIUS_PROXY_AUTHENTICATION_PORT=${RADIUS_PROXY_AUTHENTICATION_PORT:-"1812"} \
RADIUS_PROXY_COA_PORT=${RADIUS_PROXY_COA_PORT:-"3799"} \
KAFKA_ENABLE=${KAFKA_ENABLE:-"true"} \ KAFKA_ENABLE=${KAFKA_ENABLE:-"true"} \
KAFKA_BROKERLIST=${KAFKA_BROKERLIST:-"localhost:9092"} \ KAFKA_BROKERLIST=${KAFKA_BROKERLIST:-"localhost:9092"} \
KAFKA_SSL_CA_LOCATION=${KAFKA_SSL_CA_LOCATION:-""} \ KAFKA_SSL_CA_LOCATION=${KAFKA_SSL_CA_LOCATION:-""} \

View File

@@ -79,7 +79,8 @@ The following table lists the configurable parameters of the chart and their def
| persistence.size | string | Defines PV size | `'10Gi'` | | persistence.size | string | Defines PV size | `'10Gi'` |
| public_env_variables | hash | Defines list of environment variables to be passed to the Gateway | | | public_env_variables | hash | Defines list of environment variables to be passed to the Gateway | |
| configProperties | hash | Configuration properties that should be passed to the application in `owgw.properties`. May be passed by key in set (i.e. `configProperties."rtty\.token"`) | | | configProperties | hash | Configuration properties that should be passed to the application in `owgw.properties`. May be passed by key in set (i.e. `configProperties."rtty\.token"`) | |
| certs | hash | Defines files (keys and certificates) that should be passed to the Gateway (PEM format is adviced to be used) (see `volumes.owgw` on where it is mounted) | | | existingCertsSecret | string | Existing Kubernetes secret containing all required certificates and private keys for microservice operation. If set, certificates from `certs` key are ignored | `""` |
| certs | hash | Defines files (keys and certificates) that should be passed to the Gateway (PEM format is adviced to be used) (see `volumes.owgw` on where it is mounted). If `existingCertsSecret` is set, certificates passed this way will not be used. | |
| certsCAs | hash | Defines files with CAs that should be passed to the Gateway (see `volumes.owgw` on where it is mounted) | | | certsCAs | hash | Defines files with CAs that should be passed to the Gateway (see `volumes.owgw` on where it is mounted) | |

View File

@@ -1,4 +1,5 @@
{{- $root := . -}} {{- $root := . -}}
{{- $storageType := index .Values.configProperties "storage.type" -}}
--- ---
apiVersion: apps/v1 apiVersion: apps/v1
kind: Deployment kind: Deployment
@@ -48,6 +49,38 @@ spec:
- tcp://{{ index .Values.configProperties "openwifi.kafka.brokerlist" }} - tcp://{{ index .Values.configProperties "openwifi.kafka.brokerlist" }}
- -timeout - -timeout
- 600s - 600s
{{- if eq $storageType "postgresql" }}
- name: wait-postgres
image: "{{ .Values.images.owgw.repository }}:{{ .Values.images.owgw.tag }}"
imagePullPolicy: {{ .Values.images.owgw.pullPolicy }}
command:
- /wait-for-postgres.sh
- {{ index .Values.configProperties "storage.type.postgresql.host" }}
- echo
- "PostgreSQL is ready"
env:
- name: KUBERNETES_DEPLOYED
value: "{{ now }}"
{{- range $key, $value := .Values.public_env_variables }}
- name: {{ $key }}
value: {{ $value | quote }}
{{- end }}
{{- range $key, $value := .Values.secret_env_variables }}
- name: {{ $key }}
valueFrom:
secretKeyRef:
name: {{ include "owgw.fullname" $root }}-env
key: {{ $key }}
{{- end }}
volumeMounts:
{{- range .Values.volumes.owgw }}
- name: {{ .name }}
mountPath: {{ .mountPath }}
{{- if .subPath }}
subPath: {{ .subPath }}
{{- end }}
{{- end }}
{{- end }}
containers: containers:
@@ -76,6 +109,11 @@ spec:
containerPort: {{ $portValue.targetPort }} containerPort: {{ $portValue.targetPort }}
protocol: {{ $portValue.protocol }} protocol: {{ $portValue.protocol }}
{{- end }} {{- end }}
{{- range $port, $portValue := .Values.services.radius.ports }}
- name: {{ $port }}
containerPort: {{ $portValue.targetPort }}
protocol: {{ $portValue.protocol }}
{{- end }}
volumeMounts: volumeMounts:
{{- range .Values.volumes.owgw }} {{- range .Values.volumes.owgw }}

View File

@@ -46,6 +46,21 @@ services:
rttys-view: rttys-view:
servicePort: 5913 servicePort: 5913
targetPort: 5913 targetPort: 5913
radius:
type: ClusterIP
ports:
acc:
servicePort: 1813
targetPort: 1813
protocol: UDP
auth:
servicePort: 1812
targetPort: 1812
protocol: UDP
coa:
servicePort: 3799
targetPort: 3799
protocol: UDP
checks: checks:
owgw: owgw:
@@ -97,7 +112,7 @@ volumes:
mountPath: /owgw-data/certs mountPath: /owgw-data/certs
volumeDefinition: | volumeDefinition: |
secret: secret:
secretName: {{ include "owgw.fullname" . }}-certs secretName: {{ if .Values.existingCertsSecret }}{{ .Values.existingCertsSecret }}{{ else }}{{ include "owgw.fullname" . }}-certs{{ end }}
- name: certs-cas - name: certs-cas
mountPath: /owgw-data/certs/cas mountPath: /owgw-data/certs/cas
volumeDefinition: | volumeDefinition: |
@@ -231,6 +246,11 @@ configProperties:
rtty.timeout: 60 rtty.timeout: 60
rtty.viewport: 5913 rtty.viewport: 5913
rtty.assets: $OWGW_ROOT/rtty_ui rtty.assets: $OWGW_ROOT/rtty_ui
# RADIUS proxy
radius.proxy.enable: "true"
radius.proxy.accounting.port: 1813
radius.proxy.authentication.port: 1812
radius.proxy.coa.port: 3799
# ALB # ALB
alb.enable: "true" alb.enable: "true"
alb.port: 16102 alb.port: 16102
@@ -271,6 +291,7 @@ configProperties:
openwifi.system.debug: "true" openwifi.system.debug: "true"
openwifi.system.uri.private: https://localhost:17002 openwifi.system.uri.private: https://localhost:17002
openwifi.system.uri.public: https://localhost:16002 openwifi.system.uri.public: https://localhost:16002
openwifi.system.uri.ui: https://localhost
openwifi.system.commandchannel: /tmp/app_owgw openwifi.system.commandchannel: /tmp/app_owgw
# Logging # Logging
logging.type: console logging.type: console
@@ -310,166 +331,22 @@ configProperties:
storage.type.mysql.username: stephb storage.type.mysql.username: stephb
storage.type.mysql.password: snoopy99 storage.type.mysql.password: snoopy99
# NOTE: List of required certificates may be found in "certs" key. Alternative way to pass required certificates is to create external secret with all required certificates and set secret name in "existingCertsSecret" key. Details may be found in https://github.com/Telecominfraproject/wlan-cloud-ucentral-deploy/tree/main/chart#tldr
existingCertsSecret: ""
certs: certs:
clientcas.pem: | clientcas.pem: ""
-----BEGIN CERTIFICATE----- issuer.pem: ""
MIIEnDCCA4SgAwIBAgIUVpyCUx1MUeUwxg+7I1BvGFTz7HkwDQYJKoZIhvcNAQEL restapi-ca.pem: ""
BQAwaTELMAkGA1UEBhMCVVMxJDAiBgNVBAoTG1RlbGVjb20gSW5mcmEgUHJvamVj restapi-cert.pem: ""
dCwgSW5jLjEMMAoGA1UECxMDVElQMSYwJAYDVQQDEx1UZWxlY29tIEluZnJhIFBy restapi-key.pem: ""
b2plY3QgUm9vdCBDQTAeFw0yMTA0MTMyMjUxMjZaFw0yNjA0MTMyMjM4NDZaMGwx root.pem: ""
CzAJBgNVBAYTAlVTMSQwIgYDVQQKExtUZWxlY29tIEluZnJhIFByb2plY3QsIElu websocket-cert.pem: ""
Yy4xDDAKBgNVBAsTA1RJUDEpMCcGA1UEAxMgVGVsZWNvbSBJbmZyYSBQcm9qZWN0 websocket-key.pem: ""
IElzc3VpbmcgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDtKBrq
qd2aKVSk25KfL5xHu8X7/8rJrz3IvyPuVKWhk/N1zabot3suBcGaYNKjnRHxg78R
yKwKzajKYWtiQFqztu24g16LQeAnoUxZnF6a0z3JkkRPsz14A2y8TUhdEe1tx+UU
4VGsk3n+FMmOQHL+79FO57zQC1LwylgfLSltrI6mF3jowVUQvnwzKhUzT87AJ6EO
ndK/q0T/Bgi+aI39zfVOjJjsTJwghvrmYW3iarP1THSKxeib2s02bZKrvvHa5HL4
UI8+LvREpVZl4mzt1z6Nl344Y6f+UeJlYa/Ci0jJqaXJmyVnUbAz+c0i5JfwAVn3
YQzfC4eLnZCmdF8zAgMBAAGjggE3MIIBMzAPBgNVHRMBAf8EBTADAQH/MB0GA1Ud
DgQWBBSzG1S44EerPfM4gOQ85f0AYW3R6DAfBgNVHSMEGDAWgBQCRpZgebFT9qny
98WfIUDk6ZEB+jAOBgNVHQ8BAf8EBAMCAYYwgYMGCCsGAQUFBwEBBHcwdTAoBggr
BgEFBQcwAYYcaHR0cDovL29jc3Aub25lLmRpZ2ljZXJ0LmNvbTBJBggrBgEFBQcw
AoY9aHR0cDovL2NhY2VydHMub25lLmRpZ2ljZXJ0LmNvbS9UZWxlY29tSW5mcmFQ
cm9qZWN0Um9vdENBLmNydDBKBgNVHR8EQzBBMD+gPaA7hjlodHRwOi8vY3JsLm9u
ZS5kaWdpY2VydC5jb20vVGVsZWNvbUluZnJhUHJvamVjdFJvb3RDQS5jcmwwDQYJ
KoZIhvcNAQELBQADggEBAFbz+K94bHIkBMJqps0dApniUmOn0pO6Q6cGh47UP/kX
IiPIsnYgG+hqYD/qtsiqJhaWi0hixRWn38UmvZxMRk27aSTGE/TWx0JTC3qDGsSe
XkUagumbSfmS0ZyiTwMPeGAjXwyzGorqZWeA95eKfImntMiOf3E7//GK0K7HpCx8
IPCnLZsZD2q/mLyBsduImFIRQJbLAhwIxpcd1qYJk+BlGFL+HtBpEbq6JxW2Xy+v
DpNWc2WIsUTle0rTc9JNJrLX4ChUJmKqf8obKHap3Xh3//qw/jDB9pOAinA33FLJ
EmCnwBvQr9mfNmPBGMYZVU8cPruDQJ57GjmmvdisbJY=
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIDojCCAoqgAwIBAgIUPVYBpqNbcLYygF6Mx+qxSWwQyFowDQYJKoZIhvcNAQEL
BQAwaTELMAkGA1UEBhMCVVMxJDAiBgNVBAoTG1RlbGVjb20gSW5mcmEgUHJvamVj
dCwgSW5jLjEMMAoGA1UECxMDVElQMSYwJAYDVQQDEx1UZWxlY29tIEluZnJhIFBy
b2plY3QgUm9vdCBDQTAeFw0yMTA0MTMyMjQyNDRaFw0zMTA0MTMyMjM4NDZaMGkx
CzAJBgNVBAYTAlVTMSQwIgYDVQQKExtUZWxlY29tIEluZnJhIFByb2plY3QsIElu
Yy4xDDAKBgNVBAsTA1RJUDEmMCQGA1UEAxMdVGVsZWNvbSBJbmZyYSBQcm9qZWN0
IFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDIGCibwf5u
AAwZ+1H8U0e3u2V+0d2gSctucoK86XwUmfe1V2a/qlCYZd29r80IuN1IIeB0naIm
KnK/MzXW87clF6tFd1+HzEvmlY/W4KyIXalVCTEzirFSvBEG2oZpM0yC3AefytAO
aOpA00LaM3xTfTqMKIRhJBuLy0I4ANUVG6ixVebbGuc78IodleqiLoWy2Q9QHyEO
t/7hZndJhiVogh0PveRhho45EbsACu7ymDY+JhlIleevqwlE3iQoq0YcmYADHno6
Eq8vcwLpZFxihupUafkd1T3WJYQAJf9coCjBu2qIhNgrcrGD8R9fGswwNRzMRMpX
720+GjcDW3bJAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFAJG
lmB5sVP2qfL3xZ8hQOTpkQH6MA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG9w0BAQsF
AAOCAQEAVjl9dm4epG9NUYnagT9sg7scVQEPfz3Lt6w1NXJXgD8mAUlK0jXmEyvM
dCPD4514n+8+lM7US8fh+nxc7jO//LwK17Wm9FblgjNFR7+anv0Q99T9fP19DLlF
PSNHL2emogy1bl1lLTAoj8nxg2wVKPDSHBGviQ5LR9fsWUIJDv9Bs5k0qWugWYSj
19S6qnHeskRDB8MqRLhKMG82oDVLerSnhD0P6HjySBHgTTU7/tYS/OZr1jI6MPbG
L+/DtiR5fDVMNdBSGU89UNTi0wHY9+RFuNlIuvZC+x/swF0V9R5mN+ywquTPtDLA
5IOM7ItsRmen6u3qu+JXros54e4juQ==
-----END CERTIFICATE-----
issuer.pem: |
-----BEGIN CERTIFICATE-----
MIIEnDCCA4SgAwIBAgIUVpyCUx1MUeUwxg+7I1BvGFTz7HkwDQYJKoZIhvcNAQEL
BQAwaTELMAkGA1UEBhMCVVMxJDAiBgNVBAoTG1RlbGVjb20gSW5mcmEgUHJvamVj
dCwgSW5jLjEMMAoGA1UECxMDVElQMSYwJAYDVQQDEx1UZWxlY29tIEluZnJhIFBy
b2plY3QgUm9vdCBDQTAeFw0yMTA0MTMyMjUxMjZaFw0yNjA0MTMyMjM4NDZaMGwx
CzAJBgNVBAYTAlVTMSQwIgYDVQQKExtUZWxlY29tIEluZnJhIFByb2plY3QsIElu
Yy4xDDAKBgNVBAsTA1RJUDEpMCcGA1UEAxMgVGVsZWNvbSBJbmZyYSBQcm9qZWN0
IElzc3VpbmcgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDtKBrq
qd2aKVSk25KfL5xHu8X7/8rJrz3IvyPuVKWhk/N1zabot3suBcGaYNKjnRHxg78R
yKwKzajKYWtiQFqztu24g16LQeAnoUxZnF6a0z3JkkRPsz14A2y8TUhdEe1tx+UU
4VGsk3n+FMmOQHL+79FO57zQC1LwylgfLSltrI6mF3jowVUQvnwzKhUzT87AJ6EO
ndK/q0T/Bgi+aI39zfVOjJjsTJwghvrmYW3iarP1THSKxeib2s02bZKrvvHa5HL4
UI8+LvREpVZl4mzt1z6Nl344Y6f+UeJlYa/Ci0jJqaXJmyVnUbAz+c0i5JfwAVn3
YQzfC4eLnZCmdF8zAgMBAAGjggE3MIIBMzAPBgNVHRMBAf8EBTADAQH/MB0GA1Ud
DgQWBBSzG1S44EerPfM4gOQ85f0AYW3R6DAfBgNVHSMEGDAWgBQCRpZgebFT9qny
98WfIUDk6ZEB+jAOBgNVHQ8BAf8EBAMCAYYwgYMGCCsGAQUFBwEBBHcwdTAoBggr
BgEFBQcwAYYcaHR0cDovL29jc3Aub25lLmRpZ2ljZXJ0LmNvbTBJBggrBgEFBQcw
AoY9aHR0cDovL2NhY2VydHMub25lLmRpZ2ljZXJ0LmNvbS9UZWxlY29tSW5mcmFQ
cm9qZWN0Um9vdENBLmNydDBKBgNVHR8EQzBBMD+gPaA7hjlodHRwOi8vY3JsLm9u
ZS5kaWdpY2VydC5jb20vVGVsZWNvbUluZnJhUHJvamVjdFJvb3RDQS5jcmwwDQYJ
KoZIhvcNAQELBQADggEBAFbz+K94bHIkBMJqps0dApniUmOn0pO6Q6cGh47UP/kX
IiPIsnYgG+hqYD/qtsiqJhaWi0hixRWn38UmvZxMRk27aSTGE/TWx0JTC3qDGsSe
XkUagumbSfmS0ZyiTwMPeGAjXwyzGorqZWeA95eKfImntMiOf3E7//GK0K7HpCx8
IPCnLZsZD2q/mLyBsduImFIRQJbLAhwIxpcd1qYJk+BlGFL+HtBpEbq6JxW2Xy+v
DpNWc2WIsUTle0rTc9JNJrLX4ChUJmKqf8obKHap3Xh3//qw/jDB9pOAinA33FLJ
EmCnwBvQr9mfNmPBGMYZVU8cPruDQJ57GjmmvdisbJY=
-----END CERTIFICATE-----
# restapi-ca.pem: ""
# restapi-cert.pem: ""
# restapi-key.pem: ""
root.pem: |
-----BEGIN CERTIFICATE-----
MIIDojCCAoqgAwIBAgIUPVYBpqNbcLYygF6Mx+qxSWwQyFowDQYJKoZIhvcNAQEL
BQAwaTELMAkGA1UEBhMCVVMxJDAiBgNVBAoTG1RlbGVjb20gSW5mcmEgUHJvamVj
dCwgSW5jLjEMMAoGA1UECxMDVElQMSYwJAYDVQQDEx1UZWxlY29tIEluZnJhIFBy
b2plY3QgUm9vdCBDQTAeFw0yMTA0MTMyMjQyNDRaFw0zMTA0MTMyMjM4NDZaMGkx
CzAJBgNVBAYTAlVTMSQwIgYDVQQKExtUZWxlY29tIEluZnJhIFByb2plY3QsIElu
Yy4xDDAKBgNVBAsTA1RJUDEmMCQGA1UEAxMdVGVsZWNvbSBJbmZyYSBQcm9qZWN0
IFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDIGCibwf5u
AAwZ+1H8U0e3u2V+0d2gSctucoK86XwUmfe1V2a/qlCYZd29r80IuN1IIeB0naIm
KnK/MzXW87clF6tFd1+HzEvmlY/W4KyIXalVCTEzirFSvBEG2oZpM0yC3AefytAO
aOpA00LaM3xTfTqMKIRhJBuLy0I4ANUVG6ixVebbGuc78IodleqiLoWy2Q9QHyEO
t/7hZndJhiVogh0PveRhho45EbsACu7ymDY+JhlIleevqwlE3iQoq0YcmYADHno6
Eq8vcwLpZFxihupUafkd1T3WJYQAJf9coCjBu2qIhNgrcrGD8R9fGswwNRzMRMpX
720+GjcDW3bJAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFAJG
lmB5sVP2qfL3xZ8hQOTpkQH6MA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG9w0BAQsF
AAOCAQEAVjl9dm4epG9NUYnagT9sg7scVQEPfz3Lt6w1NXJXgD8mAUlK0jXmEyvM
dCPD4514n+8+lM7US8fh+nxc7jO//LwK17Wm9FblgjNFR7+anv0Q99T9fP19DLlF
PSNHL2emogy1bl1lLTAoj8nxg2wVKPDSHBGviQ5LR9fsWUIJDv9Bs5k0qWugWYSj
19S6qnHeskRDB8MqRLhKMG82oDVLerSnhD0P6HjySBHgTTU7/tYS/OZr1jI6MPbG
L+/DtiR5fDVMNdBSGU89UNTi0wHY9+RFuNlIuvZC+x/swF0V9R5mN+ywquTPtDLA
5IOM7ItsRmen6u3qu+JXros54e4juQ==
-----END CERTIFICATE-----
# websocket-cert.pem: ""
# websocket-key.pem: ""
certsCAs: certsCAs:
issuer.pem: | issuer.pem: ""
-----BEGIN CERTIFICATE----- root.pem: ""
MIIEnDCCA4SgAwIBAgIUVpyCUx1MUeUwxg+7I1BvGFTz7HkwDQYJKoZIhvcNAQEL
BQAwaTELMAkGA1UEBhMCVVMxJDAiBgNVBAoTG1RlbGVjb20gSW5mcmEgUHJvamVj
dCwgSW5jLjEMMAoGA1UECxMDVElQMSYwJAYDVQQDEx1UZWxlY29tIEluZnJhIFBy
b2plY3QgUm9vdCBDQTAeFw0yMTA0MTMyMjUxMjZaFw0yNjA0MTMyMjM4NDZaMGwx
CzAJBgNVBAYTAlVTMSQwIgYDVQQKExtUZWxlY29tIEluZnJhIFByb2plY3QsIElu
Yy4xDDAKBgNVBAsTA1RJUDEpMCcGA1UEAxMgVGVsZWNvbSBJbmZyYSBQcm9qZWN0
IElzc3VpbmcgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDtKBrq
qd2aKVSk25KfL5xHu8X7/8rJrz3IvyPuVKWhk/N1zabot3suBcGaYNKjnRHxg78R
yKwKzajKYWtiQFqztu24g16LQeAnoUxZnF6a0z3JkkRPsz14A2y8TUhdEe1tx+UU
4VGsk3n+FMmOQHL+79FO57zQC1LwylgfLSltrI6mF3jowVUQvnwzKhUzT87AJ6EO
ndK/q0T/Bgi+aI39zfVOjJjsTJwghvrmYW3iarP1THSKxeib2s02bZKrvvHa5HL4
UI8+LvREpVZl4mzt1z6Nl344Y6f+UeJlYa/Ci0jJqaXJmyVnUbAz+c0i5JfwAVn3
YQzfC4eLnZCmdF8zAgMBAAGjggE3MIIBMzAPBgNVHRMBAf8EBTADAQH/MB0GA1Ud
DgQWBBSzG1S44EerPfM4gOQ85f0AYW3R6DAfBgNVHSMEGDAWgBQCRpZgebFT9qny
98WfIUDk6ZEB+jAOBgNVHQ8BAf8EBAMCAYYwgYMGCCsGAQUFBwEBBHcwdTAoBggr
BgEFBQcwAYYcaHR0cDovL29jc3Aub25lLmRpZ2ljZXJ0LmNvbTBJBggrBgEFBQcw
AoY9aHR0cDovL2NhY2VydHMub25lLmRpZ2ljZXJ0LmNvbS9UZWxlY29tSW5mcmFQ
cm9qZWN0Um9vdENBLmNydDBKBgNVHR8EQzBBMD+gPaA7hjlodHRwOi8vY3JsLm9u
ZS5kaWdpY2VydC5jb20vVGVsZWNvbUluZnJhUHJvamVjdFJvb3RDQS5jcmwwDQYJ
KoZIhvcNAQELBQADggEBAFbz+K94bHIkBMJqps0dApniUmOn0pO6Q6cGh47UP/kX
IiPIsnYgG+hqYD/qtsiqJhaWi0hixRWn38UmvZxMRk27aSTGE/TWx0JTC3qDGsSe
XkUagumbSfmS0ZyiTwMPeGAjXwyzGorqZWeA95eKfImntMiOf3E7//GK0K7HpCx8
IPCnLZsZD2q/mLyBsduImFIRQJbLAhwIxpcd1qYJk+BlGFL+HtBpEbq6JxW2Xy+v
DpNWc2WIsUTle0rTc9JNJrLX4ChUJmKqf8obKHap3Xh3//qw/jDB9pOAinA33FLJ
EmCnwBvQr9mfNmPBGMYZVU8cPruDQJ57GjmmvdisbJY=
-----END CERTIFICATE-----
root.pem: |
-----BEGIN CERTIFICATE-----
MIIDojCCAoqgAwIBAgIUPVYBpqNbcLYygF6Mx+qxSWwQyFowDQYJKoZIhvcNAQEL
BQAwaTELMAkGA1UEBhMCVVMxJDAiBgNVBAoTG1RlbGVjb20gSW5mcmEgUHJvamVj
dCwgSW5jLjEMMAoGA1UECxMDVElQMSYwJAYDVQQDEx1UZWxlY29tIEluZnJhIFBy
b2plY3QgUm9vdCBDQTAeFw0yMTA0MTMyMjQyNDRaFw0zMTA0MTMyMjM4NDZaMGkx
CzAJBgNVBAYTAlVTMSQwIgYDVQQKExtUZWxlY29tIEluZnJhIFByb2plY3QsIElu
Yy4xDDAKBgNVBAsTA1RJUDEmMCQGA1UEAxMdVGVsZWNvbSBJbmZyYSBQcm9qZWN0
IFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDIGCibwf5u
AAwZ+1H8U0e3u2V+0d2gSctucoK86XwUmfe1V2a/qlCYZd29r80IuN1IIeB0naIm
KnK/MzXW87clF6tFd1+HzEvmlY/W4KyIXalVCTEzirFSvBEG2oZpM0yC3AefytAO
aOpA00LaM3xTfTqMKIRhJBuLy0I4ANUVG6ixVebbGuc78IodleqiLoWy2Q9QHyEO
t/7hZndJhiVogh0PveRhho45EbsACu7ymDY+JhlIleevqwlE3iQoq0YcmYADHno6
Eq8vcwLpZFxihupUafkd1T3WJYQAJf9coCjBu2qIhNgrcrGD8R9fGswwNRzMRMpX
720+GjcDW3bJAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFAJG
lmB5sVP2qfL3xZ8hQOTpkQH6MA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG9w0BAQsF
AAOCAQEAVjl9dm4epG9NUYnagT9sg7scVQEPfz3Lt6w1NXJXgD8mAUlK0jXmEyvM
dCPD4514n+8+lM7US8fh+nxc7jO//LwK17Wm9FblgjNFR7+anv0Q99T9fP19DLlF
PSNHL2emogy1bl1lLTAoj8nxg2wVKPDSHBGviQ5LR9fsWUIJDv9Bs5k0qWugWYSj
19S6qnHeskRDB8MqRLhKMG82oDVLerSnhD0P6HjySBHgTTU7/tYS/OZr1jI6MPbG
L+/DtiR5fDVMNdBSGU89UNTi0wHY9+RFuNlIuvZC+x/swF0V9R5mN+ywquTPtDLA
5IOM7ItsRmen6u3qu+JXros54e4juQ==
-----END CERTIFICATE-----
# PostgreSQL (https://github.com/bitnami/charts/tree/master/bitnami/postgresql) # PostgreSQL (https://github.com/bitnami/charts/tree/master/bitnami/postgresql)
postgresql: postgresql:

View File

@@ -190,6 +190,18 @@ components:
type: string type: string
minLength: 2 minLength: 2
maxLength: 2 maxLength: 2
started:
type: integer
format: int64
sessionId:
type: integer
format: int64
connectionCompletionTime:
type: number
format: double
totalConnectionTime:
type: integer
format: int64
DeviceList: DeviceList:
type: object type: object
@@ -282,6 +294,17 @@ components:
type: integer type: integer
format: int64 format: int64
DeviceConnectionStatistics:
type: object
description: Return some basic device statistics.
properties:
connectedDevices:
type: integer
format: int64
averageConnectionTime:
type: integer
format: int64
StatisticsDetails: StatisticsDetails:
type: object type: object
properties: properties:
@@ -1049,6 +1072,33 @@ components:
type: string type: string
certificate: certificate:
type: string type: string
radsec:
type: boolean
default: false
radsecPort:
type: integer
minimum: 1
maximum: 65535
radsecSecret:
type: string
radsecCacerts:
type: array
items:
type: string
radsecCert:
type: string
description: this must be the base64 encoded of the entire content of the certificate file, including the -----BEGIN lines
radsecKey:
type: string
description: this must be the base64 encoded of the entire content of the key file, including the -----BEGIN lines
radsecRealms:
description: each entry must be the base64 encoded of the entire content of the ca files, including the -----BEGIN lines
type: array
items:
type: string
ignore:
type: boolean
default: false
RadiusProxyServerConfig: RadiusProxyServerConfig:
type: object type: object
@@ -1162,6 +1212,13 @@ paths:
type: boolean type: boolean
default: false default: false
required: false required: false
- in: query
description: return extended information
name: connectionStatistics
schema:
type: boolean
default: false
required: false
responses: responses:
200: 200:
description: List devices description: List devices
@@ -1173,6 +1230,7 @@ paths:
- $ref: '#/components/schemas/DeviceListWithStatus' - $ref: '#/components/schemas/DeviceListWithStatus'
- $ref: '#/components/schemas/SerialNumberList' - $ref: '#/components/schemas/SerialNumberList'
- $ref: '#/components/schemas/DeviceCount' - $ref: '#/components/schemas/DeviceCount'
- $ref: '#/components/schemas/DeviceConnectionStatistics'
403: 403:
$ref: '#/components/responses/Unauthorized' $ref: '#/components/responses/Unauthorized'
404: 404:

View File

@@ -65,6 +65,7 @@ openwifi.system.debug = true
openwifi.system.uri.private = https://localhost:17002 openwifi.system.uri.private = https://localhost:17002
openwifi.system.uri.public = https://ucentral.dpaas.arilia.com:16002 openwifi.system.uri.public = https://ucentral.dpaas.arilia.com:16002
openwifi.system.uri.ui = https://ucentral-ui.arilia.com openwifi.system.uri.ui = https://ucentral-ui.arilia.com
openwifi.security.restapi.disable = false
openwifi.system.commandchannel = /tmp/app.ucentralgw openwifi.system.commandchannel = /tmp/app.ucentralgw
# #
@@ -177,4 +178,4 @@ archiver.db.3.keep = 7
######################################################################## ########################################################################
logging.type = file logging.type = file
logging.path = $OWGW_ROOT/logs logging.path = $OWGW_ROOT/logs
logging.level = debug logging.level = debug

View File

@@ -52,8 +52,8 @@ openwifi.fileuploader.host.0.cert = ${FILEUPLOADER_HOST_CERT}
openwifi.fileuploader.host.0.key = ${FILEUPLOADER_HOST_KEY} openwifi.fileuploader.host.0.key = ${FILEUPLOADER_HOST_KEY}
openwifi.fileuploader.host.0.key.password = ${FILEUPLOADER_HOST_KEY_PASSWORD} openwifi.fileuploader.host.0.key.password = ${FILEUPLOADER_HOST_KEY_PASSWORD}
openwifi.fileuploader.path = ${FILEUPLOADER_PATH} openwifi.fileuploader.path = ${FILEUPLOADER_PATH}
openwifi.fileuploader.uri = ${FILEUPLOADER_URI}
openwifi.fileuploader.maxsize = 10000 openwifi.fileuploader.maxsize = 10000
openwifi.fileuploader.uri = ${FILEUPLOADER_URI}
# #
# Generic section that all microservices must have # Generic section that all microservices must have
@@ -65,6 +65,7 @@ openwifi.system.debug = true
openwifi.system.uri.private = ${SYSTEM_URI_PRIVATE} openwifi.system.uri.private = ${SYSTEM_URI_PRIVATE}
openwifi.system.uri.public = ${SYSTEM_URI_PUBLIC} openwifi.system.uri.public = ${SYSTEM_URI_PUBLIC}
openwifi.system.uri.ui = ${SYSTEM_URI_UI} openwifi.system.uri.ui = ${SYSTEM_URI_UI}
openwifi.security.restapi.disable = ${SECURITY_RESTAPI_DISABLE}
openwifi.system.commandchannel = /tmp/app.ucentralgw openwifi.system.commandchannel = /tmp/app.ucentralgw
# #
@@ -75,8 +76,13 @@ openwifi.devicetypes.0 = AP:linksys_ea8300,edgecore_eap101,linksys_e8450-ubi
openwifi.devicetypes.1 = SWITCH:edgecore_ecs4100-12ph openwifi.devicetypes.1 = SWITCH:edgecore_ecs4100-12ph
openwifi.devicetypes.2 = IOT:esp32 openwifi.devicetypes.2 = IOT:esp32
oui.download.uri = https://standards-oui.ieee.org/oui/oui.txt oui.download.uri = https://standards-oui.ieee.org/oui/oui.txt
firmware.autoupdate.policy.default = auto
simulatorid = ${SIMULATORID} simulatorid = ${SIMULATORID}
iptocountry.default = US
iptocountry.provider = ${IPTOCOUNTRY_PROVIDER}
iptocountry.ipinfo.token = ${IPTOCOUNTRY_IPINFO_TOKEN}
iptocountry.ipdata.apikey = ${IPTOCOUNTRY_IPDATA_APIKEY}
autoprovisioning.process = ${AUTOPROVISIONING_PROCESS}
# #
# rtty # rtty
@@ -90,6 +96,12 @@ rtty.timeout = ${RTTY_TIMEOUT}
rtty.viewport = ${RTTY_VIEWPORT} rtty.viewport = ${RTTY_VIEWPORT}
rtty.assets = ${RTTY_ASSETS} rtty.assets = ${RTTY_ASSETS}
### RADIUS proxy config
radius.proxy.enable = ${RADIUS_PROXY_ENABLE}
radius.proxy.accounting.port = ${RADIUS_PROXY_ACCOUNTING_PORT}
radius.proxy.authentication.port = ${RADIUS_PROXY_AUTHENTICATION_PORT}
radius.proxy.coa.port = ${RADIUS_PROXY_COA_PORT}
############################# #############################
# Generic information for all micro services # Generic information for all micro services
############################# #############################
@@ -108,6 +120,7 @@ openwifi.kafka.enable = ${KAFKA_ENABLE}
openwifi.kafka.brokerlist = ${KAFKA_BROKERLIST} openwifi.kafka.brokerlist = ${KAFKA_BROKERLIST}
openwifi.kafka.auto.commit = false openwifi.kafka.auto.commit = false
openwifi.kafka.queue.buffering.max.ms = 50 openwifi.kafka.queue.buffering.max.ms = 50
openwifi.kafka.ssl.ca.location = ${KAFKA_SSL_CA_LOCATION} openwifi.kafka.ssl.ca.location = ${KAFKA_SSL_CA_LOCATION}
openwifi.kafka.ssl.certificate.location = ${KAFKA_SSL_CERTIFICATE_LOCATION} openwifi.kafka.ssl.certificate.location = ${KAFKA_SSL_CERTIFICATE_LOCATION}
openwifi.kafka.ssl.key.location = ${KAFKA_SSL_KEY_LOCATION} openwifi.kafka.ssl.key.location = ${KAFKA_SSL_KEY_LOCATION}

205
radius-proxy-orion.json Normal file
View File

@@ -0,0 +1,205 @@
{
"interfaces": [
{
"ethernet": [
{
"select-ports": [
"WAN*"
]
}
],
"ipv4": {
"addressing": "dynamic"
},
"ipv6": {
"addressing": "dynamic"
},
"name": "wan",
"role": "upstream",
"services": [
"ssh"
],
"ssids": []
},
{
"ethernet": [
{
"select-ports": [
"LAN*"
]
}
],
"ipv4": {
"addressing": "static",
"dhcp": {
"lease-count": 100,
"lease-first": 10,
"lease-time": "6h"
},
"gateway": "192.168.1.1",
"send-hostname": true,
"subnet": "192.168.1.1/24",
"use-dns": []
},
"ipv6": {
"addressing": "dynamic"
},
"name": "lan",
"role": "downstream",
"services": [
"wifi-steering",
"ssh"
],
"ssids": [
{
"bss-mode": "ap",
"encryption": {
"ieee80211w": "required",
"proto": "wpa"
},
"hidden-ssid": false,
"isolate-clients": false,
"maximum-clients": 64,
"name": "arilia-rad",
"radius": {
"authentication": {
"host": "0.0.0.0",
"port": 1812,
"secret": "radsec"
},
"accounting": {
"host": "0.0.0.0",
"port": 1813,
"secret": "radsec"
}
},
"services": [
"radius-gw-proxy"
],
"wifi-bands": [
"2G",
"5G"
],
"pass-point": {
"venue-name": [
"eng:Example passpoint_venue",
"fra:Exemple de lieu"
],
"domain-name": [
"onboard.almondlabs.net",
"test.com"
],
"asra": false,
"internet": true,
"esr": false,
"uesa": false,
"access-network-type": 0,
"hessid":"11:22:33:44:55:66",
"venue-group": 2,
"venue-type": 8,
"connection-capability":[
"1:0:2",
"6:22:1",
"17:5060:0"
],
"roaming-consortium": [
"F4F5E8F5F4",
"BAA2D00100",
"BAA2D00000"
],
"disable-dgaf": true,
"anqp-domain": 8888,
"ipaddr-type-available": 14,
"nai-realm": [
],
"osen": false,
"anqp-3gpp-cell-net": [
],
"friendly-name": [
"eng:AlmondLabs",
"fra:AlmondLabs"
],
"venue-url": [
"http://www.example.com/info-fra",
"http://www.example.com/info-eng"
],
"auth-type": {
"type": "terms-and-conditions"
}
}
}
]
}
],
"metrics": {
"dhcp-snooping": {
"filters": [
"ack",
"discover",
"offer",
"request",
"solicit",
"reply",
"renew"
]
},
"health": {
"interval": 60
},
"statistics": {
"interval": 60,
"types": [
"ssids",
"lldp",
"clients"
]
},
"wifi-frames": {
"filters": [
"probe",
"auth",
"assoc",
"disassoc",
"deauth",
"local-deauth",
"inactive-deauth",
"key-mismatch",
"beacon-report",
"radar-detected"
]
}
},
"radios": [
{
"band": "2G",
"bandwidth": 10,
"beacon-interval": 100,
"channel": "auto",
"channel-mode": "HT",
"channel-width": 20,
"country": "CA",
"dtim-period": 2,
"maximum-clients": 64,
"tx-power": 0
},
{
"band": "5G",
"bandwidth": 20,
"beacon-interval": 100,
"channel": "auto",
"channel-mode": "HE",
"channel-width": 40,
"country": "CA",
"dtim-period": 2,
"maximum-clients": 64,
"tx-power": 0
}
],
"services": {
"ssh": {
"password-authentication": true,
"port": 22
}
},
"uuid": 1661312631
}

32
radsec-config-sample.json Normal file
View File

@@ -0,0 +1,32 @@
{
"pools" : [
{
"name" : "master" ,
"description" : "master pool",
"useByDefault" : true,
"authConfig" : {
"strategy" : "weighted",
"monitor" : false,
"monitorMethod" : "none",
"methodParameters" : [],
"servers" : [ {
"name" : "orion",
"ip" : "216.239.32.91",
"port" : 2083,
"weight" : 10,
"radsec" : true,
"radsecPort" : 2083,
"radsecSecret" : "radsec",
"radsecKey" : "LS0tLS1CRUdJTiBFQyBQUklWQVRFIEtFWS0tLS0tCk1IY0NBUUVFSUR6RnpXeTZlYXg0QVoxTySG9VUURRZ0FFS3BnWVBHMktPTVd2S0w1Z3NMRXpUc09rREg1M3NHaEQyS3RsRXBDTXVnNDNIZlFnTFVpUgpTR1R2S1l0bDFmbmJaU1lnY0RJdncxdjNYRy9hVDhOY2JBPT0KLS0tLS1FTkQgRUMgUFJJVkFURSBLRVktLS0tLQo=",
"radsecCert" : "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUNRVENDQWVpZ0F3SUJBZ0lVY3BKS3pVM0Ba0dBMVVFQmhNQ1ZWTXhFekFSQmdOVkJBb1RDa0oxZEhSdmJuZHZiMlF4SFRBYkJnTlZCQU1URkVKMQpkSFJ2Ym5kdmIyUWdVbUZrYzJWaklFTkJNQjRYRFRJeU1EY3dNekExTWpVeE5Gb1hEVEkzTURVeE9UQTFNalV4Ck5Gb3dkVEVMTUFrR0ExVUVCaE1DVlZNeEV6QVJCZ05WQkFvVENrSjFkSFJ2Ym5kdmIyUXhOakEwQmdOVkJBTVQKTFdGeWFXeHBZUzVqWWpFd2FtTnVjemgxYlhCbk9HWnBjRFowTUM1dmNtbHZiaTVoY21WaE1USXdMbU52YlRFWgpNQmNHQ2dtU0pvbVQ4aXhrQVFFVENVZHZiMmRzWlRwVlV6QlpNQk1HQnlxR1NNNDlBZ0VHQ0NxR1NNNDlBd0VICkEwSUFCQ3FZR0R4dGlqakZyeWkrWUxDeE0wN0RwQXgrZDdCb1E5aXJaUktRakxvT054MzBJQzFJa1Voazd5bUwKWmRYNTIyVW1JSEF5TDhOYjkxeHYyay9EWEd5amdZa3dnWVl3RGdZRFZSMFBBUUgvQkFRREFnZUFNQk1HQTFVZApKUVFNTUFvR0NDc0dBUVVGQndNQ01Bd0dBMVVkRXdFQi93UUNNQUF3T0FZRFZSMFJCREV3TDRJdFlYSnBiR2xoCkxtTmlNVEJxWTI1ek9IVnRjR2M0Wm1sd05uUXdMbTl5YVc5dUxtRnlaV0V4TWpBdVkyOXRNQmNHQTFVZElBUVEKTUE0d0RBWUtLd1lCQkFIdUtnRUJCVEFLQmdncWhrak9QUVFEQWdOSEFEQkVBaUFwTmM1dUNBSkp6KzVyakdqdwpCWGtOdHE3UU83bWU5dUg5bkNsTDZnSVE5Z0lnUHM2VkVKVW5CcEZ0RktXbFF4eWJ1YlBxYnpJNjBPSERHQ0ExCmhXUk1PS1U9Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K",
"radsecCacerts" : [
"LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUJ0akNDQVZ1Z0F3SUJBZ0lCQyOXZaREVkTUJzR0ExVUVBeE1VUW5WMGRHOXVkMjl2WkNCU1lXUnpaV01nUTBFdwpJQmNOTVRrd05qQTJNVFV4TlRNeVdoZ1BNalV4T1RBMk1EY3hOVEUxTXpKYU1FRXhDekFKQmdOVkJBWVRBbFZUCk1STXdFUVlEVlFRS0V3cENkWFIwYjI1M2IyOWtNUjB3R3dZRFZRUURFeFJDZFhSMGIyNTNiMjlrSUZKaFpITmwKWXlCRFFUQlpNQk1HQnlxR1NNNDlBZ0VHQ0NxR1NNNDlBd0VIQTBJQUJJUW40QVBKaXdvUVFQblR1cFgrZTk1Ugp0ZzVoQVFVbUhCN1E0UkpwSG4welF6TUJpMDdSejkxV05RamFHeERydktLVlQ1OThIM2dxYkI4TTViOHN3aytqClFqQkFNQTRHQTFVZER3RUIvd1FFQXdJQ2hEQWRCZ05WSFNVRUZqQVVCZ2dyQmdFRkJRY0RBZ1lJS3dZQkJRVUgKQXdFd0R3WURWUjBUQVFIL0JBVXdBd0VCL3pBS0JnZ3Foa2pPUFFRREFnTkpBREJHQWlFQTkrbHUwN2NlaGc1OQpxSi81dWtzN05oL3F2aXFHWCs1WDFwSVVxdENGVlJjQ0lRREZmUGhwZzZJOFE0SUdBbzNuamlHRTdDWC9nMm56CkRzSW5FcG9vRlkxV0xRPT0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo="
],
"radsecRealms" : [],
"ignore" : false
}
]
}
}
]
}

View File

@@ -27,129 +27,285 @@
namespace OpenWifi { namespace OpenWifi {
#define DBL { std::cout << __LINE__ << " ID: " << ConnectionId_ << " Ser: " << SerialNumber_ << std::endl; }
void AP_WS_Connection::LogException(const Poco::Exception &E) { void AP_WS_Connection::LogException(const Poco::Exception &E) {
Logger().information(fmt::format("EXCEPTION({}): {}", CId_, E.displayText())); poco_information(Logger_,fmt::format("EXCEPTION({}): {}", CId_, E.displayText()));
} }
void AP_WS_Connection::CompleteStartup() { AP_WS_Connection::AP_WS_Connection(Poco::Net::HTTPServerRequest &request,
Poco::Net::HTTPServerResponse &response,
std::uint64_t connection_id,
Poco::Logger &L,
Poco::Net::SocketReactor &R)
: Logger_(L) ,
Reactor_(R)
{
State_.sessionId = connection_id;
WS_ = std::make_unique<Poco::Net::WebSocket>(request,response);
auto TS = Poco::Timespan(360, 0);
WS_->setMaxPayloadSize(BufSize);
WS_->setReceiveTimeout(TS);
WS_->setNoDelay(true);
WS_->setKeepAlive(true);
WS_->setBlocking(false);
Reactor_.addEventHandler(
*WS_, Poco::NObserver<AP_WS_Connection, Poco::Net::ReadableNotification>(
*this, &AP_WS_Connection::OnSocketReadable));
Reactor_.addEventHandler(
*WS_, Poco::NObserver<AP_WS_Connection, Poco::Net::ShutdownNotification>(
*this, &AP_WS_Connection::OnSocketShutdown));
Reactor_.addEventHandler(
*WS_, Poco::NObserver<AP_WS_Connection, Poco::Net::ErrorNotification>(
*this, &AP_WS_Connection::OnSocketError));
Registered_ = true;
}
class ThreadedCounter {
public:
ThreadedCounter(bool T, std::atomic_uint64_t &C) :
C_(C),
Threaded_(T) {
if(Threaded_) {
C_++;
}
}
~ThreadedCounter() {
if(Threaded_ && C_>0) {
C_--;
}
}
private:
std::atomic_uint64_t &C_;
bool Threaded_;
};
bool AP_WS_Connection::ValidatedDevice() {
if(DeviceValidated_)
return true;
std::lock_guard Guard(Mutex_);
try { try {
auto SockImpl = dynamic_cast<Poco::Net::WebSocketImpl *>(WS_->impl()); auto SockImpl = dynamic_cast<Poco::Net::WebSocketImpl *>(WS_->impl());
auto SS = dynamic_cast<Poco::Net::SecureStreamSocketImpl*>(SockImpl->streamSocketImpl()); auto SS = dynamic_cast<Poco::Net::SecureStreamSocketImpl*>(SockImpl->streamSocketImpl());
while (true) {
auto V = SS->completeHandshake();
if (V == 1)
break;
}
PeerAddress_ = SS->peerAddress().host(); PeerAddress_ = SS->peerAddress().host();
CId_ = Utils::FormatIPv6(SS->peerAddress().toString()); CId_ = Utils::FormatIPv6(SS->peerAddress().toString());
State_.started = OpenWifi::Now();
if (!SS->secure()) { if (!SS->secure()) {
poco_error(Logger(),fmt::format("CONNECTION({}): Connection is NOT secure. Device is not allowed.", CId_)); poco_warning(Logger_,fmt::format("TLS-CONNECTION({}): Session={} Connection is NOT secure. Device is not allowed.", CId_, State_.sessionId ));
return delete this; EndConnection();
} else { return false;
poco_trace(Logger(),fmt::format("CONNECTION({}): Connection is secure.", CId_));
} }
if (SS->havePeerCertificate()) { poco_debug(Logger_,fmt::format("TLS-CONNECTION({}): Session={} Connection is secure.", CId_, State_.sessionId ));
CertValidation_ = GWObjects::VALID_CERTIFICATE;
try {
Poco::Crypto::X509Certificate PeerCert(SS->peerCertificate());
if (AP_WS_Server()->ValidateCertificate(CId_, PeerCert)) { if (!SS->havePeerCertificate()) {
CN_ = Poco::trim(Poco::toLower(PeerCert.commonName())); State_.VerifiedCertificate = GWObjects::NO_CERTIFICATE;
CertValidation_ = GWObjects::MISMATCH_SERIAL; poco_warning(Logger_,fmt::format("TLS-CONNECTION({}): Session={} No certificates available..", CId_, State_.sessionId ));
poco_trace(Logger(),fmt::format("CONNECTION({}): Valid certificate: CN={}", CId_, CN_)); EndConnection();
} else { return false;
poco_error(Logger(),fmt::format("CONNECTION({}): Device certificate is not valid. Device is not allowed.", CId_));
return delete this;
}
} catch (const Poco::Exception &E) {
LogException(E);
poco_error(Logger(),fmt::format("CONNECTION({}): Device certificate is not valid. Device is not allowed.", CId_));
return delete this;
}
} else {
poco_error(Logger(),fmt::format("CONNECTION({}): No certificates available..", CId_));
return delete this;
} }
Poco::Crypto::X509Certificate PeerCert(SS->peerCertificate());
if (!AP_WS_Server()->ValidateCertificate(CId_, PeerCert)) {
State_.VerifiedCertificate = GWObjects::NO_CERTIFICATE;
poco_warning(Logger_, fmt::format("TLS-CONNECTION({}): Session={} Device certificate is not valid. Device is not allowed.",
CId_, State_.sessionId ));
EndConnection();
return false;
}
CN_ = Poco::trim(Poco::toLower(PeerCert.commonName()));
State_.VerifiedCertificate = GWObjects::VALID_CERTIFICATE;
poco_debug(Logger_,
fmt::format("TLS-CONNECTION({}): Session={} Valid certificate: CN={}", CId_, State_.sessionId , CN_));
if (AP_WS_Server::IsSim(CN_) && !AP_WS_Server()->IsSimEnabled()) { if (AP_WS_Server::IsSim(CN_) && !AP_WS_Server()->IsSimEnabled()) {
poco_warning(Logger(),fmt::format( poco_warning(
"CONNECTION({}): Sim Device {} is not allowed. Disconnecting.", CId_, CN_)); Logger_,
return delete this; fmt::format("TLS-CONNECTION({}): Session={} Sim Device {} is not allowed. Disconnecting.",
CId_, State_.sessionId , CN_));
EndConnection();
return false;
}
if (!CN_.empty() && StorageService()->IsBlackListed(SerialNumber_)) {
poco_warning(
Logger_,
fmt::format("TLS-CONNECTION({}): Session={} Device {} is black listed. Disconnecting.",
CId_, State_.sessionId , CN_));
EndConnection();
return false;
} }
SerialNumber_ = CN_; SerialNumber_ = CN_;
SerialNumberInt_ = Utils::SerialNumberToInt(SerialNumber_); SerialNumberInt_ = Utils::SerialNumberToInt(SerialNumber_);
if (!CN_.empty() && StorageService()->IsBlackListed(SerialNumber_)) { poco_debug(Logger_, fmt::format("TLS-CONNECTION({}): Session={} CN={} Completed. (t={})", CId_, State_.sessionId , CN_, ConcurrentStartingDevices_));
poco_warning(Logger(),fmt::format("CONNECTION({}): Device {} is black listed. Disconnecting.", DeviceValidated_ = true;
CId_, CN_)); return true;
return delete this;
} catch (const Poco::Net::CertificateValidationException &E) {
poco_error(Logger_,fmt::format("CONNECTION({}): Session:{} Poco::CertificateValidationException Certificate Validation failed during connection. Device will have to retry.",
CId_, State_.sessionId ));
Logger_.log(E);
} catch (const Poco::Net::WebSocketException &E) {
poco_error(Logger_,fmt::format("CONNECTION({}): Session:{} Poco::WebSocketException WebSocket error during connection. Device will have to retry.",
CId_, State_.sessionId ));
Logger_.log(E);
} catch (const Poco::Net::ConnectionAbortedException &E) {
poco_error(Logger_,fmt::format("CONNECTION({}):Session:{} Poco::ConnectionAbortedException Connection was aborted during connection. Device will have to retry.",
CId_, State_.sessionId ));
Logger_.log(E);
} catch (const Poco::Net::ConnectionResetException &E) {
poco_error(Logger_,fmt::format("CONNECTION({}): Session:{} Poco::ConnectionResetException Connection was reset during connection. Device will have to retry.",
CId_, State_.sessionId ));
Logger_.log(E);
} catch (const Poco::Net::InvalidCertificateException &E) {
poco_error(Logger_,fmt::format(
"CONNECTION({}): Session:{} Poco::InvalidCertificateException Invalid certificate. Device will have to retry.",
CId_, State_.sessionId ));
Logger_.log(E);
} catch (const Poco::Net::SSLException &E) {
poco_error(Logger_,fmt::format("CONNECTION({}): Session:{} Poco::SSLException SSL Exception during connection. Device will have to retry.",
CId_, State_.sessionId ));
Logger_.log(E);
} catch (const Poco::Exception &E) {
poco_error(Logger_,fmt::format("CONNECTION({}): Session:{} Poco::Exception caught during device connection. Device will have to retry.",
CId_, State_.sessionId ));
Logger_.log(E);
} catch (...) {
poco_error(Logger_,fmt::format("CONNECTION({}): Session:{} Exception caught during device connection. Device will have to retry. Unsecure connect denied.",
CId_, State_.sessionId ));
}
EndConnection();
return false;
}
void AP_WS_Connection::CompleteStartup() {
std::lock_guard Guard(Mutex_);
auto TC = ThreadedCounter(Threaded_,ConcurrentStartingDevices_);
try {
auto SockImpl = dynamic_cast<Poco::Net::WebSocketImpl *>(WS_->impl());
auto SS = dynamic_cast<Poco::Net::SecureStreamSocketImpl*>(SockImpl->streamSocketImpl());
/* while (true) {
auto V = SS->completeHandshake();
if (V == 1)
break;
} }
*/
PeerAddress_ = SS->peerAddress().host();
CId_ = Utils::FormatIPv6(SS->peerAddress().toString());
State_.started = OpenWifi::Now();
if (!SS->secure()) {
poco_warning(Logger_,fmt::format("CONNECTION({}): Session={} Connection is NOT secure. Device is not allowed.", CId_, State_.sessionId ));
return EndConnection();
}
poco_debug(Logger_,fmt::format("CONNECTION({}): Session={} Connection is secure.", CId_, State_.sessionId ));
if (!SS->havePeerCertificate()) {
State_.VerifiedCertificate = GWObjects::NO_CERTIFICATE;
poco_warning(Logger_,fmt::format("CONNECTION({}): Session={} No certificates available..", CId_, State_.sessionId ));
return EndConnection();
}
Poco::Crypto::X509Certificate PeerCert(SS->peerCertificate());
if (!AP_WS_Server()->ValidateCertificate(CId_, PeerCert)) {
State_.VerifiedCertificate = GWObjects::NO_CERTIFICATE;
poco_warning(Logger_, fmt::format("CONNECTION({}): Session={} Device certificate is not valid. Device is not allowed.",
CId_, State_.sessionId ));
return EndConnection();
}
CN_ = Poco::trim(Poco::toLower(PeerCert.commonName()));
State_.VerifiedCertificate = GWObjects::VALID_CERTIFICATE;
poco_debug(Logger_,
fmt::format("CONNECTION({}): Session={} Valid certificate: CN={}", CId_, State_.sessionId , CN_));
if (AP_WS_Server::IsSim(CN_) && !AP_WS_Server()->IsSimEnabled()) {
poco_warning(
Logger_,
fmt::format("CONNECTION({}): Session={} Sim Device {} is not allowed. Disconnecting.",
CId_, State_.sessionId , CN_));
return EndConnection();
}
if (!CN_.empty() && StorageService()->IsBlackListed(SerialNumber_)) {
poco_warning(
Logger_,
fmt::format("CONNECTION({}): Session={} Device {} is black listed. Disconnecting.",
CId_, State_.sessionId , CN_));
return EndConnection();
}
SerialNumber_ = CN_;
SerialNumberInt_ = Utils::SerialNumberToInt(SerialNumber_);
WS_->setMaxPayloadSize(BufSize); WS_->setMaxPayloadSize(BufSize);
auto TS = Poco::Timespan(360, 0); auto TS = Poco::Timespan(360, 0);
WS_->setReceiveTimeout(TS); WS_->setReceiveTimeout(TS);
WS_->setNoDelay(true); WS_->setNoDelay(true);
WS_->setKeepAlive(true); WS_->setKeepAlive(true);
WS_->setBlocking(false);
Reactor_.addEventHandler(*WS_, Reactor_.addEventHandler(
Poco::NObserver<AP_WS_Connection, Poco::Net::ReadableNotification>( *WS_, Poco::NObserver<AP_WS_Connection, Poco::Net::ReadableNotification>(
*this, &AP_WS_Connection::OnSocketReadable)); *this, &AP_WS_Connection::OnSocketReadable));
Reactor_.addEventHandler(*WS_, Reactor_.addEventHandler(
Poco::NObserver<AP_WS_Connection, Poco::Net::ShutdownNotification>( *WS_, Poco::NObserver<AP_WS_Connection, Poco::Net::ShutdownNotification>(
*this, &AP_WS_Connection::OnSocketShutdown)); *this, &AP_WS_Connection::OnSocketShutdown));
Reactor_.addEventHandler(*WS_, Poco::NObserver<AP_WS_Connection, Poco::Net::ErrorNotification>( Reactor_.addEventHandler(
*this, &AP_WS_Connection::OnSocketError)); *WS_, Poco::NObserver<AP_WS_Connection, Poco::Net::ErrorNotification>(
*this, &AP_WS_Connection::OnSocketError));
Registered_ = true; Registered_ = true;
poco_trace(Logger(),fmt::format("CONNECTION({}): completed.", CId_)); poco_debug(Logger_, fmt::format("CONNECTION({}): Session={} CN={} Completed. (t={})", CId_, State_.sessionId , CN_, ConcurrentStartingDevices_));
return; return;
} catch (const Poco::Net::CertificateValidationException &E) { } catch (const Poco::Net::CertificateValidationException &E) {
Logger().error(fmt::format("CONNECTION({}): Poco::CertificateValidationException Certificate Validation failed during connection. Device will have to retry.", poco_error(Logger_,fmt::format("CONNECTION({}): Session:{} Poco::CertificateValidationException Certificate Validation failed during connection. Device will have to retry.",
CId_)); CId_, State_.sessionId ));
Logger().log(E); Logger_.log(E);
} catch (const Poco::Net::WebSocketException &E) { } catch (const Poco::Net::WebSocketException &E) {
Logger().error(fmt::format("CONNECTION({}): Poco::WebSocketException WebSocket error during connection. Device will have to retry.", poco_error(Logger_,fmt::format("CONNECTION({}): Session:{} Poco::WebSocketException WebSocket error during connection. Device will have to retry.",
CId_)); CId_, State_.sessionId ));
Logger().log(E); Logger_.log(E);
} catch (const Poco::Net::ConnectionAbortedException &E) { } catch (const Poco::Net::ConnectionAbortedException &E) {
Logger().error(fmt::format("CONNECTION({}): Poco::ConnectionAbortedException Connection was aborted during connection. Device will have to retry.", poco_error(Logger_,fmt::format("CONNECTION({}):Session:{} Poco::ConnectionAbortedException Connection was aborted during connection. Device will have to retry.",
CId_)); CId_, State_.sessionId ));
Logger().log(E); Logger_.log(E);
} catch (const Poco::Net::ConnectionResetException &E) { } catch (const Poco::Net::ConnectionResetException &E) {
Logger().error(fmt::format("CONNECTION({}): Poco::ConnectionResetException Connection was reset during connection. Device will have to retry.", poco_error(Logger_,fmt::format("CONNECTION({}): Session:{} Poco::ConnectionResetException Connection was reset during connection. Device will have to retry.",
CId_)); CId_, State_.sessionId ));
Logger().log(E); Logger_.log(E);
} catch (const Poco::Net::InvalidCertificateException &E) { } catch (const Poco::Net::InvalidCertificateException &E) {
Logger().error(fmt::format( poco_error(Logger_,fmt::format(
"CONNECTION({}): Poco::InvalidCertificateException Invalid certificate. Device will have to retry.", "CONNECTION({}): Session:{} Poco::InvalidCertificateException Invalid certificate. Device will have to retry.",
CId_)); CId_, State_.sessionId ));
Logger().log(E); Logger_.log(E);
} catch (const Poco::Net::SSLException &E) { } catch (const Poco::Net::SSLException &E) {
Logger().error(fmt::format("CONNECTION({}): Poco::SSLException SSL Exception during connection. Device will have to retry.", poco_error(Logger_,fmt::format("CONNECTION({}): Session:{} Poco::SSLException SSL Exception during connection. Device will have to retry.",
CId_)); CId_, State_.sessionId ));
Logger().log(E); Logger_.log(E);
} catch (const Poco::Exception &E) { } catch (const Poco::Exception &E) {
Logger().error(fmt::format("CONNECTION({}): Poco::Exception caught during device connection. Device will have to retry.", poco_error(Logger_,fmt::format("CONNECTION({}): Session:{} Poco::Exception caught during device connection. Device will have to retry.",
CId_)); CId_, State_.sessionId ));
Logger().log(E); Logger_.log(E);
} catch (...) { } catch (...) {
Logger().error(fmt::format("CONNECTION({}): Exception caught during device connection. Device will have to retry. Unsecure connect denied.", poco_error(Logger_,fmt::format("CONNECTION({}): Session:{} Exception caught during device connection. Device will have to retry. Unsecure connect denied.",
CId_)); CId_, State_.sessionId ));
} }
return delete this; return EndConnection();
}
AP_WS_Connection::AP_WS_Connection(Poco::Net::HTTPServerRequest &request,
Poco::Net::HTTPServerResponse &response)
: Logger_(AP_WS_Server()->Logger()) ,
Reactor_(AP_WS_Server()->NextReactor())
{
WS_ = std::make_unique<Poco::Net::WebSocket>(request,response);
Session_ = DeviceRegistry()->StartSession(this);
CompleteStartup();
} }
static void NotifyKafkaDisconnect(const std::string & SerialNumber) { static void NotifyKafkaDisconnect(const std::string & SerialNumber) {
@@ -168,31 +324,36 @@ namespace OpenWifi {
} }
AP_WS_Connection::~AP_WS_Connection() { AP_WS_Connection::~AP_WS_Connection() {
if(!Dead_)
EndConnection();
}
poco_debug(Logger(),fmt::format("CONNECTION({}): Removing connection for {}.", CId_, SerialNumber_)); void AP_WS_Connection::EndConnection() {
DeviceRegistry()->EndSession(this); Dead_=true;
poco_information(Logger_,fmt::format("CONNECTION-CLOSING({}): Session={} Serial={}.", CId_, State_.sessionId, SerialNumber_));
auto SessionDeleted = DeviceRegistry()->EndSession(State_.sessionId, SerialNumberInt_);
if (Registered_ && WS_) { if (Registered_) {
Reactor_.removeEventHandler(*WS_, Reactor_.removeEventHandler(
Poco::NObserver<AP_WS_Connection, Poco::Net::ReadableNotification>( *WS_, Poco::NObserver<AP_WS_Connection, Poco::Net::ReadableNotification>(
*this, &AP_WS_Connection::OnSocketReadable)); *this, &AP_WS_Connection::OnSocketReadable));
Reactor_.removeEventHandler(*WS_, Reactor_.removeEventHandler(
Poco::NObserver<AP_WS_Connection, Poco::Net::ShutdownNotification>( *WS_, Poco::NObserver<AP_WS_Connection, Poco::Net::ShutdownNotification>(
*this, &AP_WS_Connection::OnSocketShutdown)); *this, &AP_WS_Connection::OnSocketShutdown));
Reactor_.removeEventHandler(*WS_, Reactor_.removeEventHandler(
Poco::NObserver<AP_WS_Connection, Poco::Net::ErrorNotification>( *WS_, Poco::NObserver<AP_WS_Connection, Poco::Net::ErrorNotification>(
*this, &AP_WS_Connection::OnSocketError)); *this, &AP_WS_Connection::OnSocketError));
(*WS_).close();
} else if (WS_) {
(*WS_).close();
} }
WS_->close();
if (KafkaManager()->Enabled() && !SerialNumber_.empty()) { if (KafkaManager()->Enabled() && !SerialNumber_.empty()) {
std::string s(SerialNumber_); std::string s(SerialNumber_);
std::thread t([s]() { NotifyKafkaDisconnect(s); }); std::thread t([s]() { NotifyKafkaDisconnect(s); });
t.detach(); t.detach();
} }
WebSocketClientNotificationDeviceDisconnected(SerialNumber_); if(SessionDeleted)
WebSocketClientNotificationDeviceDisconnected(SerialNumber_);
AP_WS_Server()->DeleteConnection(State_.sessionId);
} }
bool AP_WS_Connection::LookForUpgrade(const uint64_t UUID, uint64_t & UpgradedUUID) { bool AP_WS_Connection::LookForUpgrade(const uint64_t UUID, uint64_t & UpgradedUUID) {
@@ -202,7 +363,7 @@ namespace OpenWifi {
return false; return false;
uint64_t GoodConfig = ConfigurationCache().CurrentConfig(SerialNumberInt_); uint64_t GoodConfig = ConfigurationCache().CurrentConfig(SerialNumberInt_);
if (GoodConfig && (GoodConfig == UUID || GoodConfig == Session_->State_.PendingUUID)) { if (GoodConfig && (GoodConfig == UUID || GoodConfig == State_.PendingUUID)) {
UpgradedUUID = UUID; UpgradedUUID = UUID;
return false; return false;
} }
@@ -229,7 +390,7 @@ namespace OpenWifi {
} }
UpgradedUUID = D.UUID; UpgradedUUID = D.UUID;
Session_->State_.PendingUUID = D.UUID; State_.PendingUUID = D.UUID;
GWObjects::CommandDetails Cmd; GWObjects::CommandDetails Cmd;
Cmd.SerialNumber = SerialNumber_; Cmd.SerialNumber = SerialNumber_;
Cmd.UUID = MicroService::CreateUUID(); Cmd.UUID = MicroService::CreateUUID();
@@ -247,11 +408,11 @@ namespace OpenWifi {
std::ostringstream O; std::ostringstream O;
Poco::JSON::Stringifier::stringify(Params, O); Poco::JSON::Stringifier::stringify(Params, O);
Cmd.Details = O.str(); Cmd.Details = O.str();
poco_information(Logger(),fmt::format("CFG-UPGRADE({}): Current ID: {}, newer configuration {}.", poco_information(Logger_,fmt::format("CFG-UPGRADE({}): Current ID: {}, newer configuration {}.",
CId_, UUID, D.UUID)); CId_, UUID, D.UUID));
bool Sent; bool Sent;
StorageService()->AddCommand(SerialNumber_, Cmd, Storage::COMMAND_EXECUTED); StorageService()->AddCommand(SerialNumber_, Cmd, Storage::CommandExecutionType::COMMAND_EXECUTED);
CommandManager()->PostCommand(CommandManager()->NextRPCId(),SerialNumber_, Cmd.Command, Params, Cmd.UUID, Sent); CommandManager()->PostCommand(CommandManager()->NextRPCId(),SerialNumber_, Cmd.Command, Params, Cmd.UUID, Sent);
WebSocketClientNotificationDeviceConfigurationChange(D.SerialNumber, UUID, UpgradedUUID); WebSocketClientNotificationDeviceConfigurationChange(D.SerialNumber, UUID, UpgradedUUID);
@@ -262,21 +423,21 @@ namespace OpenWifi {
} }
void AP_WS_Connection::ProcessJSONRPCResult(Poco::JSON::Object::Ptr Doc) { void AP_WS_Connection::ProcessJSONRPCResult(Poco::JSON::Object::Ptr Doc) {
poco_debug(Logger_,fmt::format("RECEIVED-RPC({}): {}.", CId_, Doc->get(uCentralProtocol::ID).toString()));
CommandManager()->PostCommandResult(SerialNumber_, *Doc); CommandManager()->PostCommandResult(SerialNumber_, *Doc);
} }
void AP_WS_Connection::ProcessJSONRPCEvent(Poco::JSON::Object::Ptr &Doc) { void AP_WS_Connection::ProcessJSONRPCEvent(Poco::JSON::Object::Ptr &Doc) {
auto Method = Doc->get(uCentralProtocol::METHOD).toString(); auto Method = Doc->get(uCentralProtocol::METHOD).toString();
auto EventType = uCentralProtocol::Events::EventFromString(Method); auto EventType = uCentralProtocol::Events::EventFromString(Method);
if (EventType == uCentralProtocol::Events::ET_UNKNOWN) { if (EventType == uCentralProtocol::Events::ET_UNKNOWN) {
poco_warning(Logger(),fmt::format("ILLEGAL-PROTOCOL({}): Unknown message type '{}'", CId_, Method)); poco_warning(Logger_,fmt::format("ILLEGAL-PROTOCOL({}): Unknown message type '{}'", CId_, Method));
Errors_++; Errors_++;
return; return;
} }
if (!Doc->isObject(uCentralProtocol::PARAMS)) { if (!Doc->isObject(uCentralProtocol::PARAMS)) {
poco_warning(Logger(),fmt::format("MISSING-PARAMS({}): params must be an object.", CId_)); poco_warning(Logger_,fmt::format("MISSING-PARAMS({}): params must be an object.", CId_));
Errors_++; Errors_++;
return; return;
} }
@@ -293,26 +454,26 @@ namespace OpenWifi {
} }
if (Utils::ExtractBase64CompressedData(CompressedData, UncompressedData, compress_sz)) { if (Utils::ExtractBase64CompressedData(CompressedData, UncompressedData, compress_sz)) {
poco_trace(Logger(),fmt::format("EVENT({}): Found compressed payload expanded to '{}'.", poco_trace(Logger_,fmt::format("EVENT({}): Found compressed payload expanded to '{}'.",
CId_, UncompressedData)); CId_, UncompressedData));
Poco::JSON::Parser Parser; Poco::JSON::Parser Parser;
ParamsObj = Parser.parse(UncompressedData).extract<Poco::JSON::Object::Ptr>(); ParamsObj = Parser.parse(UncompressedData).extract<Poco::JSON::Object::Ptr>();
} else { } else {
poco_warning(Logger(),fmt::format("INVALID-COMPRESSED-DATA({}): Compressed cannot be uncompressed - content must be corrupt..: size={}", poco_warning(Logger_,fmt::format("INVALID-COMPRESSED-DATA({}): Compressed cannot be uncompressed - content must be corrupt..: size={}",
CId_, CompressedData.size())); CId_, CompressedData.size()));
Errors_++; Errors_++;
return; return;
} }
} catch (const Poco::Exception &E) { } catch (const Poco::Exception &E) {
poco_warning(Logger(),fmt::format("INVALID-COMPRESSED-JSON-DATA({}): Compressed cannot be parsed - JSON must be corrupt..", poco_warning(Logger_,fmt::format("INVALID-COMPRESSED-JSON-DATA({}): Compressed cannot be parsed - JSON must be corrupt..",
CId_)); CId_));
Logger().log(E); Logger_.log(E);
return; return;
} }
} }
if (!ParamsObj->has(uCentralProtocol::SERIAL)) { if (!ParamsObj->has(uCentralProtocol::SERIAL)) {
poco_warning(Logger(),fmt::format("MISSING-PARAMS({}): Serial number is missing in message.", CId_)); poco_warning(Logger_,fmt::format("MISSING-PARAMS({}): Serial number is missing in message.", CId_));
return; return;
} }
@@ -334,8 +495,6 @@ namespace OpenWifi {
E.rethrow(); E.rethrow();
} }
Session_->State_.LastContact = OpenWifi::Now();
switch (EventType) { switch (EventType) {
case uCentralProtocol::Events::ET_CONNECT: { case uCentralProtocol::Events::ET_CONNECT: {
Process_connect(ParamsObj, Serial); Process_connect(ParamsObj, Serial);
@@ -346,7 +505,7 @@ namespace OpenWifi {
} break; } break;
case uCentralProtocol::Events::ET_HEALTHCHECK: { case uCentralProtocol::Events::ET_HEALTHCHECK: {
Process_healthcheck(ParamsObj, Serial); Process_healthcheck(ParamsObj);
} break; } break;
case uCentralProtocol::Events::ET_LOG: { case uCentralProtocol::Events::ET_LOG: {
@@ -384,15 +543,14 @@ namespace OpenWifi {
// this will never be called but some compilers will complain if we do not have a case for // this will never be called but some compilers will complain if we do not have a case for
// every single values of an enum // every single values of an enum
case uCentralProtocol::Events::ET_UNKNOWN: { case uCentralProtocol::Events::ET_UNKNOWN: {
poco_warning(Logger(), fmt::format("ILLEGAL-EVENT({}): Event '{}' unknown. CN={}", CId_, Method, CN_)); poco_warning(Logger_, fmt::format("ILLEGAL-EVENT({}): Event '{}' unknown. CN={}", CId_, Method, CN_));
Errors_++; Errors_++;
} }
} }
} }
bool AP_WS_Connection::StartTelemetry() { bool AP_WS_Connection::StartTelemetry(std::uint64_t RPCID) {
// std::cout << "Start telemetry for " << SerialNumber_ << std::endl; poco_information(Logger_, fmt::format("TELEMETRY({}): Starting.", CId_));
poco_information(Logger(), fmt::format("TELEMETRY({}): Starting.", CId_));
Poco::JSON::Object StartMessage; Poco::JSON::Object StartMessage;
StartMessage.set("jsonrpc", "2.0"); StartMessage.set("jsonrpc", "2.0");
StartMessage.set("method", "telemetry"); StartMessage.set("method", "telemetry");
@@ -404,43 +562,40 @@ namespace OpenWifi {
Types.add("dhcp-snooping"); Types.add("dhcp-snooping");
Types.add("state"); Types.add("state");
Params.set(RESTAPI::Protocol::TYPES, Types); Params.set(RESTAPI::Protocol::TYPES, Types);
StartMessage.set("id", 1); StartMessage.set("id", RPCID);
StartMessage.set("params", Params); StartMessage.set("params", Params);
Poco::JSON::Stringifier Stringify; Poco::JSON::Stringifier Stringify;
std::ostringstream OS; std::ostringstream OS;
Stringify.condense(StartMessage, OS); Stringify.condense(StartMessage, OS);
Send(OS.str()); return Send(OS.str());
return true;
} }
bool AP_WS_Connection::StopTelemetry() { bool AP_WS_Connection::StopTelemetry(std::uint64_t RPCID) {
// std::cout << "Stop telemetry for " << SerialNumber_ << std::endl; poco_information(Logger_, fmt::format("TELEMETRY({}): Stopping.", CId_));
poco_information(Logger(), fmt::format("TELEMETRY({}): Stopping.", CId_));
Poco::JSON::Object StopMessage; Poco::JSON::Object StopMessage;
StopMessage.set("jsonrpc", "2.0"); StopMessage.set("jsonrpc", "2.0");
StopMessage.set("method", "telemetry"); StopMessage.set("method", "telemetry");
Poco::JSON::Object Params; Poco::JSON::Object Params;
Params.set("serial", SerialNumber_); Params.set("serial", SerialNumber_);
Params.set("interval", 0); Params.set("interval", 0);
StopMessage.set("id", 1); StopMessage.set("id", RPCID);
StopMessage.set("params", Params); StopMessage.set("params", Params);
Poco::JSON::Stringifier Stringify; Poco::JSON::Stringifier Stringify;
std::ostringstream OS; std::ostringstream OS;
Stringify.condense(StopMessage, OS); Stringify.condense(StopMessage, OS);
Send(OS.str());
TelemetryKafkaPackets_ = TelemetryWebSocketPackets_ = TelemetryInterval_ = TelemetryKafkaPackets_ = TelemetryWebSocketPackets_ = TelemetryInterval_ =
TelemetryKafkaTimer_ = TelemetryWebSocketTimer_ = 0; TelemetryKafkaTimer_ = TelemetryWebSocketTimer_ = 0;
return true; return Send(OS.str());
} }
void AP_WS_Connection::UpdateCounts() { void AP_WS_Connection::UpdateCounts() {
Session_->State_.kafkaClients = TelemetryKafkaRefCount_; State_.kafkaClients = TelemetryKafkaRefCount_;
Session_->State_.webSocketClients = TelemetryWebSocketRefCount_; State_.webSocketClients = TelemetryWebSocketRefCount_;
} }
bool AP_WS_Connection::SetWebSocketTelemetryReporting(uint64_t Interval, bool AP_WS_Connection::SetWebSocketTelemetryReporting(std::uint64_t RPCID, uint64_t Interval,
uint64_t LifeTime) { uint64_t LifeTime) {
std::lock_guard G(Mutex_); std::unique_lock Lock(TelemetryMutex_);
TelemetryWebSocketRefCount_++; TelemetryWebSocketRefCount_++;
TelemetryInterval_ = TelemetryInterval_ ? std::min(Interval, TelemetryInterval_) : Interval; TelemetryInterval_ = TelemetryInterval_ ? std::min(Interval, TelemetryInterval_) : Interval;
auto TelemetryWebSocketTimer = LifeTime + OpenWifi::Now(); auto TelemetryWebSocketTimer = LifeTime + OpenWifi::Now();
@@ -448,13 +603,13 @@ namespace OpenWifi {
UpdateCounts(); UpdateCounts();
if (!TelemetryReporting_) { if (!TelemetryReporting_) {
TelemetryReporting_ = true; TelemetryReporting_ = true;
return StartTelemetry(); return StartTelemetry(RPCID);
} }
return true; return true;
} }
bool AP_WS_Connection::SetKafkaTelemetryReporting(uint64_t Interval, uint64_t LifeTime) { bool AP_WS_Connection::SetKafkaTelemetryReporting(std::uint64_t RPCID, uint64_t Interval, uint64_t LifeTime) {
std::lock_guard G(Mutex_); std::unique_lock Lock(TelemetryMutex_);
TelemetryKafkaRefCount_++; TelemetryKafkaRefCount_++;
TelemetryInterval_ = TelemetryInterval_ ? std::min(Interval, TelemetryInterval_) : Interval; TelemetryInterval_ = TelemetryInterval_ ? std::min(Interval, TelemetryInterval_) : Interval;
auto TelemetryKafkaTimer = LifeTime + OpenWifi::Now(); auto TelemetryKafkaTimer = LifeTime + OpenWifi::Now();
@@ -462,61 +617,68 @@ namespace OpenWifi {
UpdateCounts(); UpdateCounts();
if (!TelemetryReporting_) { if (!TelemetryReporting_) {
TelemetryReporting_ = true; TelemetryReporting_ = true;
return StartTelemetry(); return StartTelemetry(RPCID);
} }
return true; return true;
} }
bool AP_WS_Connection::StopWebSocketTelemetry() { bool AP_WS_Connection::StopWebSocketTelemetry(std::uint64_t RPCID) {
std::lock_guard G(Mutex_); std::unique_lock Lock(TelemetryMutex_);
if (TelemetryWebSocketRefCount_) if (TelemetryWebSocketRefCount_)
TelemetryWebSocketRefCount_--; TelemetryWebSocketRefCount_--;
UpdateCounts(); UpdateCounts();
if (TelemetryWebSocketRefCount_ == 0 && TelemetryKafkaRefCount_ == 0) { if (TelemetryWebSocketRefCount_ == 0 && TelemetryKafkaRefCount_ == 0) {
TelemetryReporting_ = false; TelemetryReporting_ = false;
StopTelemetry(); StopTelemetry(RPCID);
} }
return true; return true;
} }
bool AP_WS_Connection::StopKafkaTelemetry() { bool AP_WS_Connection::StopKafkaTelemetry(std::uint64_t RPCID) {
std::lock_guard G(Mutex_); std::unique_lock Lock(TelemetryMutex_);
if (TelemetryKafkaRefCount_) if (TelemetryKafkaRefCount_)
TelemetryKafkaRefCount_--; TelemetryKafkaRefCount_--;
UpdateCounts(); UpdateCounts();
if (TelemetryWebSocketRefCount_ == 0 && TelemetryKafkaRefCount_ == 0) { if (TelemetryWebSocketRefCount_ == 0 && TelemetryKafkaRefCount_ == 0) {
TelemetryReporting_ = false; TelemetryReporting_ = false;
StopTelemetry(); StopTelemetry(RPCID);
} }
return true; return true;
} }
void AP_WS_Connection::OnSocketShutdown([[maybe_unused]] const Poco::AutoPtr<Poco::Net::ShutdownNotification> &pNf) { void AP_WS_Connection::OnSocketShutdown([[maybe_unused]] const Poco::AutoPtr<Poco::Net::ShutdownNotification> &pNf) {
std::lock_guard Guard(Mutex_); std::lock_guard Guard(Mutex_);
poco_trace(Logger(), fmt::format("SOCKET-SHUTDOWN({}): Closing.", CId_)); poco_trace(Logger_, fmt::format("SOCKET-SHUTDOWN({}): Closing.", CId_));
delete this; return EndConnection();
} }
void AP_WS_Connection::OnSocketError([[maybe_unused]] const Poco::AutoPtr<Poco::Net::ErrorNotification> &pNf) { void AP_WS_Connection::OnSocketError([[maybe_unused]] const Poco::AutoPtr<Poco::Net::ErrorNotification> &pNf) {
std::lock_guard Guard(Mutex_); std::lock_guard Guard(Mutex_);
poco_trace(Logger(), fmt::format("SOCKET-ERROR({}): Closing.", CId_)); poco_trace(Logger_, fmt::format("SOCKET-ERROR({}): Closing.", CId_));
delete this; return EndConnection();
} }
void AP_WS_Connection::OnSocketReadable([[maybe_unused]] const Poco::AutoPtr<Poco::Net::ReadableNotification> &pNf) { void AP_WS_Connection::OnSocketReadable([[maybe_unused]] const Poco::AutoPtr<Poco::Net::ReadableNotification> &pNf) {
std::lock_guard Guard(Mutex_); std::lock_guard Guard(Mutex_);
if(!AP_WS_Server()->Running())
return EndConnection();
if(!ValidatedDevice())
return;
try { try {
ProcessIncomingFrame(); return ProcessIncomingFrame();
} catch (const Poco::Exception &E) { } catch (const Poco::Exception &E) {
Logger().log(E); Logger_.log(E);
delete this; return EndConnection();
} catch (const std::exception &E) { } catch (const std::exception &E) {
std::string W = E.what(); std::string W = E.what();
poco_information(Logger(), fmt::format("std::exception caught: {}. Connection terminated with {}", W, CId_)); poco_information(Logger_, fmt::format("std::exception caught: {}. Connection terminated with {}", W, CId_));
delete this; return EndConnection();
} catch (...) { } catch (...) {
poco_information(Logger(), fmt::format("Unknown exception for {}. Connection terminated.", CId_)); poco_information(Logger_, fmt::format("Unknown exception for {}. Connection terminated.", CId_));
delete this; return EndConnection();
} }
} }
@@ -525,34 +687,37 @@ namespace OpenWifi {
try { try {
int Op, flags; int Op, flags;
auto IncomingSize = WS_->receiveFrame(IncomingFrame, flags); auto IncomingSize = WS_->receiveFrame(IncomingFrame, flags);
IncomingFrame.append(0);
Op = flags & Poco::Net::WebSocket::FRAME_OP_BITMASK; Op = flags & Poco::Net::WebSocket::FRAME_OP_BITMASK;
if (IncomingSize == 0 && flags == 0 && Op == 0) { if (IncomingSize == 0 && flags == 0 && Op == 0) {
poco_information(Logger(), fmt::format("DISCONNECT({}): device has disconnected.", CId_)); poco_information(Logger_, fmt::format("DISCONNECT({}): device has disconnected. Session={}", CId_, State_.sessionId));
return delete this; return EndConnection();
} else { }
Session_->State_.RX += IncomingSize;
Session_->State_.MessageCount++;
switch (Op) { IncomingFrame.append(0);
State_.RX += IncomingSize;
State_.MessageCount++;
State_.LastContact = OpenWifi::Now();
switch (Op) {
case Poco::Net::WebSocket::FRAME_OP_PING: { case Poco::Net::WebSocket::FRAME_OP_PING: {
poco_trace(Logger(), fmt::format("WS-PING({}): received. PONG sent back.", CId_)); poco_trace(Logger_, fmt::format("WS-PING({}): received. PONG sent back.", CId_));
WS_->sendFrame("", 0, WS_->sendFrame("", 0,
(int)Poco::Net::WebSocket::FRAME_OP_PONG | (int)Poco::Net::WebSocket::FRAME_OP_PONG |
(int)Poco::Net::WebSocket::FRAME_FLAG_FIN); (int)Poco::Net::WebSocket::FRAME_FLAG_FIN);
Session_->State_.MessageCount++; State_.MessageCount++;
if (KafkaManager()->Enabled()) { if (KafkaManager()->Enabled()) {
Poco::JSON::Object PingObject; Poco::JSON::Object PingObject;
Poco::JSON::Object PingDetails; Poco::JSON::Object PingDetails;
PingDetails.set(uCentralProtocol::FIRMWARE, Session_->State_.Firmware); PingDetails.set(uCentralProtocol::FIRMWARE, State_.Firmware);
PingDetails.set(uCentralProtocol::SERIALNUMBER, SerialNumber_); PingDetails.set(uCentralProtocol::SERIALNUMBER, SerialNumber_);
PingDetails.set(uCentralProtocol::COMPATIBLE, Compatible_); PingDetails.set(uCentralProtocol::COMPATIBLE, Compatible_);
PingDetails.set(uCentralProtocol::CONNECTIONIP, CId_); PingDetails.set(uCentralProtocol::CONNECTIONIP, CId_);
PingDetails.set(uCentralProtocol::TIMESTAMP, OpenWifi::Now()); PingDetails.set(uCentralProtocol::TIMESTAMP, OpenWifi::Now());
PingDetails.set("locale", Session_->State_.locale ); PingDetails.set("locale", State_.locale );
PingObject.set(uCentralProtocol::PING, PingDetails); PingObject.set(uCentralProtocol::PING, PingDetails);
Poco::JSON::Stringifier Stringify; Poco::JSON::Stringifier Stringify;
std::ostringstream OS; std::ostringstream OS;
@@ -563,12 +728,12 @@ namespace OpenWifi {
} break; } break;
case Poco::Net::WebSocket::FRAME_OP_PONG: { case Poco::Net::WebSocket::FRAME_OP_PONG: {
poco_trace(Logger(), fmt::format("PONG({}): received and ignored.", CId_)); poco_trace(Logger_, fmt::format("PONG({}): received and ignored.", CId_));
return; return;
} break; } break;
case Poco::Net::WebSocket::FRAME_OP_TEXT: { case Poco::Net::WebSocket::FRAME_OP_TEXT: {
poco_trace(Logger(), fmt::format("FRAME({}): Frame received (length={}, flags={}). Msg={}", CId_, poco_trace(Logger_, fmt::format("FRAME({}): Frame received (length={}, flags={}). Msg={}", CId_,
IncomingSize, flags, IncomingFrame.begin())); IncomingSize, flags, IncomingFrame.begin()));
Poco::JSON::Parser parser; Poco::JSON::Parser parser;
@@ -581,93 +746,121 @@ namespace OpenWifi {
ProcessJSONRPCEvent(IncomingJSON); ProcessJSONRPCEvent(IncomingJSON);
} else if (IncomingJSON->has(uCentralProtocol::RESULT) && } else if (IncomingJSON->has(uCentralProtocol::RESULT) &&
IncomingJSON->has(uCentralProtocol::ID)) { IncomingJSON->has(uCentralProtocol::ID)) {
poco_trace(Logger(), fmt::format("RPC-RESULT({}): payload: {}", CId_, IncomingFrame.begin())); poco_trace(Logger_, fmt::format("RPC-RESULT({}): payload: {}", CId_, IncomingFrame.begin()));
ProcessJSONRPCResult(IncomingJSON); ProcessJSONRPCResult(IncomingJSON);
} else { } else {
poco_warning(Logger(), poco_warning(Logger_,
fmt::format("INVALID-PAYLOAD({}): Payload is not JSON-RPC 2.0: {}", fmt::format("INVALID-PAYLOAD({}): Payload is not JSON-RPC 2.0: {}",
CId_, IncomingFrame.begin())); CId_, IncomingFrame.begin()));
} }
} else if (IncomingJSON->has(uCentralProtocol::RADIUS)) { } else if (IncomingJSON->has(uCentralProtocol::RADIUS)) {
ProcessIncomingRadiusData(IncomingJSON); ProcessIncomingRadiusData(IncomingJSON);
} else { } else {
std::ostringstream iS; std::ostringstream iS;
IncomingJSON->stringify(iS); IncomingJSON->stringify(iS);
std::cout << iS.str() << std::endl; std::cout << iS.str() << std::endl;
poco_warning(Logger(), fmt::format( poco_warning(Logger_, fmt::format(
"FRAME({}): illegal transaction header, missing 'jsonrpc'", CId_)); "FRAME({}): illegal transaction header, missing 'jsonrpc'", CId_));
Errors_++; Errors_++;
} }
return; return;
} break; } break;
case Poco::Net::WebSocket::FRAME_OP_CLOSE: { case Poco::Net::WebSocket::FRAME_OP_CLOSE: {
poco_information(Logger(), poco_information(Logger_,
fmt::format("CLOSE({}): Device is closing its connection.", CId_)); fmt::format("CLOSE({}): Device is closing its connection.", CId_));
return delete this; return EndConnection();
} break; } break;
default: { default: {
poco_warning(Logger(), fmt::format("UNKNOWN({}): unknown WS Frame operation: {}", CId_, poco_warning(Logger_, fmt::format("UNKNOWN({}): unknown WS Frame operation: {}", CId_,
std::to_string(Op))); std::to_string(Op)));
} break; } break;
}
} }
} catch (const Poco::Net::ConnectionResetException &E) { } catch (const Poco::Net::ConnectionResetException &E) {
poco_warning(Logger(), fmt::format("ConnectionResetException({}): Text:{} Payload:{}", poco_warning(Logger_, fmt::format("ConnectionResetException({}): Text:{} Payload:{} Session:{}",
CId_, CId_,
E.displayText(), E.displayText(),
IncomingFrame.begin())); IncomingFrame.begin()==nullptr ? "" : IncomingFrame.begin(),
return delete this; State_.sessionId));
return EndConnection();
} catch (const Poco::JSON::JSONException &E) { } catch (const Poco::JSON::JSONException &E) {
poco_warning(Logger(), fmt::format("JSONException({}): Text:{} Payload:{}", poco_warning(Logger_, fmt::format("JSONException({}): Text:{} Payload:{} Session:{}",
CId_, E.displayText(), IncomingFrame.begin())); CId_,
E.displayText(),
IncomingFrame.begin()==nullptr ? "" : IncomingFrame.begin(),
State_.sessionId));
return EndConnection();
} catch (const Poco::Net::WebSocketException &E) { } catch (const Poco::Net::WebSocketException &E) {
poco_warning(Logger(), fmt::format("WebSocketException({}): Text:{} Payload:{}", poco_warning(Logger_, fmt::format("WebSocketException({}): Text:{} Payload:{} Session:{}",
CId_, E.displayText(), IncomingFrame.begin())); CId_,
return delete this; E.displayText(),
IncomingFrame.begin()==nullptr ? "" : IncomingFrame.begin(),
State_.sessionId));
return EndConnection();
} catch (const Poco::Net::SSLConnectionUnexpectedlyClosedException &E) { } catch (const Poco::Net::SSLConnectionUnexpectedlyClosedException &E) {
poco_warning(Logger(), fmt::format("SSLConnectionUnexpectedlyClosedException({}): Text:{} Payload:{}", poco_warning(Logger_, fmt::format("SSLConnectionUnexpectedlyClosedException({}): Text:{} Payload:{} Session:{}",
CId_, E.displayText(), IncomingFrame.begin())); CId_,
return delete this; E.displayText(),
IncomingFrame.begin()==nullptr ? "" : IncomingFrame.begin(),
State_.sessionId));
return EndConnection();
} catch (const Poco::Net::SSLException &E) { } catch (const Poco::Net::SSLException &E) {
poco_warning(Logger(), fmt::format("SSLException({}): Text:{} Payload:{}", poco_warning(Logger_, fmt::format("SSLException({}): Text:{} Payload:{} Session:{}",
CId_, E.displayText(), IncomingFrame.begin())); CId_,
return delete this; E.displayText(),
IncomingFrame.begin()==nullptr ? "" : IncomingFrame.begin(),
State_.sessionId));
return EndConnection();
} catch (const Poco::Net::NetException &E) { } catch (const Poco::Net::NetException &E) {
poco_warning(Logger(), fmt::format("NetException({}): Text:{} Payload:{}", poco_warning(Logger_, fmt::format("NetException({}): Text:{} Payload:{} Session:{}",
CId_, E.displayText(), IncomingFrame.begin())); CId_,
return delete this; E.displayText(),
IncomingFrame.begin()==nullptr ? "" : IncomingFrame.begin(),
State_.sessionId));
return EndConnection();
} catch (const Poco::IOException &E) { } catch (const Poco::IOException &E) {
poco_warning(Logger(), fmt::format("IOException({}): Text:{} Payload:{}", poco_warning(Logger_, fmt::format("IOException({}): Text:{} Payload:{} Session:{}",
CId_, E.displayText(), IncomingFrame.begin())); CId_,
return delete this; E.displayText(),
IncomingFrame.begin()==nullptr ? "" : IncomingFrame.begin(),
State_.sessionId));
return EndConnection();
} catch (const Poco::Exception &E) { } catch (const Poco::Exception &E) {
poco_warning(Logger(), fmt::format("Exception({}): Text:{} Payload:{}", poco_warning(Logger_, fmt::format("Exception({}): Text:{} Payload:{} Session:{}",
CId_, E.displayText(), IncomingFrame.begin())); CId_,
return delete this; E.displayText(),
IncomingFrame.begin()==nullptr ? "" : IncomingFrame.begin(),
State_.sessionId));
return EndConnection();
} catch (const std::exception &E) { } catch (const std::exception &E) {
poco_warning(Logger(), fmt::format("std::exception({}): Text:{} Payload:{}", poco_warning(Logger_, fmt::format("std::exception({}): Text:{} Payload:{} Session:{}",
CId_, E.what(), IncomingFrame.begin())); CId_,
return delete this; E.what(),
IncomingFrame.begin()==nullptr ? "" : IncomingFrame.begin(),
State_.sessionId));
return EndConnection();
} catch (...) { } catch (...) {
poco_error(Logger(),fmt::format("UnknownException({}): Device must be disconnected. Unknown exception.", CId_)); poco_error(Logger_,fmt::format("UnknownException({}): Device must be disconnected. Unknown exception. Session:{}", CId_, State_.sessionId));
return delete this; return EndConnection();
} }
if (Errors_ < 10) if (Errors_ < 10)
return; return;
poco_warning(Logger(), fmt::format("DISCONNECTING({}): Too many errors", CId_)); poco_warning(Logger_, fmt::format("DISCONNECTING({}): Too many errors", CId_));
delete this; return EndConnection();
} }
bool AP_WS_Connection::Send(const std::string &Payload) { bool AP_WS_Connection::Send(const std::string &Payload) {
std::lock_guard Guard(Mutex_); try {
size_t BytesSent = WS_->sendFrame(Payload.c_str(), (int)Payload.size());
size_t BytesSent = WS_->sendFrame(Payload.c_str(), (int)Payload.size()); State_.TX += BytesSent;
Session_->State_.TX += BytesSent; return BytesSent == Payload.size();
return BytesSent == Payload.size(); } catch(const Poco::Exception &E) {
Logger_.log(E);
}
return false;
} }
std::string Base64Encode(const unsigned char *buffer, std::size_t size) { std::string Base64Encode(const unsigned char *buffer, std::size_t size) {

View File

@@ -15,15 +15,20 @@
#include "DeviceRegistry.h" #include "DeviceRegistry.h"
#include "RESTObjects/RESTAPI_GWobjects.h" #include "RESTObjects/RESTAPI_GWobjects.h"
namespace OpenWifi { namespace OpenWifi {
class AP_WS_Connection { class AP_WS_Connection {
static constexpr int BufSize = 128000; static constexpr int BufSize = 256000;
public: public:
explicit AP_WS_Connection(Poco::Net::HTTPServerRequest &request, explicit AP_WS_Connection( Poco::Net::HTTPServerRequest &request,
Poco::Net::HTTPServerResponse &response); Poco::Net::HTTPServerResponse &response,
std::uint64_t connection_id,
Poco::Logger &L,
Poco::Net::SocketReactor &R);
~AP_WS_Connection(); ~AP_WS_Connection();
void EndConnection();
void ProcessJSONRPCEvent(Poco::JSON::Object::Ptr & Doc); void ProcessJSONRPCEvent(Poco::JSON::Object::Ptr & Doc);
void ProcessJSONRPCResult(Poco::JSON::Object::Ptr Doc); void ProcessJSONRPCResult(Poco::JSON::Object::Ptr Doc);
void ProcessIncomingFrame(); void ProcessIncomingFrame();
@@ -42,14 +47,14 @@ namespace OpenWifi {
static bool ExtractBase64CompressedData(const std::string & CompressedData, std::string & UnCompressedData, uint64_t compress_sz); static bool ExtractBase64CompressedData(const std::string & CompressedData, std::string & UnCompressedData, uint64_t compress_sz);
void LogException(const Poco::Exception &E); void LogException(const Poco::Exception &E);
inline Poco::Logger & Logger() { return Logger_; } inline Poco::Logger & Logger() { return Logger_; }
bool SetWebSocketTelemetryReporting(uint64_t interval, uint64_t TelemetryWebSocketTimer); bool SetWebSocketTelemetryReporting(std::uint64_t RPCID, uint64_t interval, uint64_t TelemetryWebSocketTimer);
bool SetKafkaTelemetryReporting(uint64_t interval, uint64_t TelemetryKafkaTimer); bool SetKafkaTelemetryReporting(std::uint64_t RPCID, uint64_t interval, uint64_t TelemetryKafkaTimer);
bool StopWebSocketTelemetry(); bool StopWebSocketTelemetry(std::uint64_t RPCID);
bool StopKafkaTelemetry(); bool StopKafkaTelemetry(std::uint64_t RPCID);
void Process_connect(Poco::JSON::Object::Ptr ParamsObj, const std::string &Serial); void Process_connect(Poco::JSON::Object::Ptr ParamsObj, const std::string &Serial);
void Process_state(Poco::JSON::Object::Ptr ParamsObj); void Process_state(Poco::JSON::Object::Ptr ParamsObj);
void Process_healthcheck(Poco::JSON::Object::Ptr ParamsObj, const std::string &Serial); void Process_healthcheck(Poco::JSON::Object::Ptr ParamsObj);
void Process_log(Poco::JSON::Object::Ptr ParamsObj); void Process_log(Poco::JSON::Object::Ptr ParamsObj);
void Process_crashlog(Poco::JSON::Object::Ptr ParamsObj); void Process_crashlog(Poco::JSON::Object::Ptr ParamsObj);
void Process_ping(Poco::JSON::Object::Ptr ParamsObj); void Process_ping(Poco::JSON::Object::Ptr ParamsObj);
@@ -59,6 +64,8 @@ namespace OpenWifi {
void Process_telemetry(Poco::JSON::Object::Ptr ParamsObj); void Process_telemetry(Poco::JSON::Object::Ptr ParamsObj);
void Process_venuebroadcast(Poco::JSON::Object::Ptr ParamsObj); void Process_venuebroadcast(Poco::JSON::Object::Ptr ParamsObj);
bool ValidatedDevice();
inline bool GetTelemetryParameters(bool & Reporting, uint64_t & Interval, inline bool GetTelemetryParameters(bool & Reporting, uint64_t & Interval,
uint64_t & WebSocketTimer, uint64_t & KafkaTimer, uint64_t & WebSocketTimer, uint64_t & KafkaTimer,
uint64_t &WebSocketCount, uint64_t & KafkaCount, uint64_t &WebSocketCount, uint64_t & KafkaCount,
@@ -75,22 +82,21 @@ namespace OpenWifi {
return true; return true;
} }
friend class DeviceRegistry;
private: private:
std::recursive_mutex Mutex_; std::recursive_mutex Mutex_;
std::shared_mutex TelemetryMutex_;
Poco::Logger &Logger_; Poco::Logger &Logger_;
Poco::Net::SocketReactor &Reactor_; Poco::Net::SocketReactor &Reactor_;
std::unique_ptr<Poco::Net::WebSocket> WS_; std::unique_ptr<Poco::Net::WebSocket> WS_;
std::string SerialNumber_; std::string SerialNumber_;
uint64_t SerialNumberInt_=0; uint64_t SerialNumberInt_=0;
std::string Compatible_; std::string Compatible_;
std::shared_ptr<DeviceRegistry::RegistryConnectionEntry> Session_;
std::atomic_bool Registered_ = false ; std::atomic_bool Registered_ = false ;
std::string CId_; std::string CId_;
std::string CN_; std::string CN_;
GWObjects::CertificateValidation CertValidation_ = GWObjects::CertificateValidation::NO_CERTIFICATE;
uint64_t Errors_=0; uint64_t Errors_=0;
std::atomic_bool Connected_=false;
uint64_t ConnectionId_=0;
Poco::Net::IPAddress PeerAddress_; Poco::Net::IPAddress PeerAddress_;
std::atomic_bool TelemetryReporting_ = false; std::atomic_bool TelemetryReporting_ = false;
std::atomic_uint64_t TelemetryWebSocketRefCount_ = 0; std::atomic_uint64_t TelemetryWebSocketRefCount_ = 0;
@@ -100,10 +106,20 @@ namespace OpenWifi {
uint64_t TelemetryInterval_ = 0; uint64_t TelemetryInterval_ = 0;
std::atomic_uint64_t TelemetryWebSocketPackets_=0; std::atomic_uint64_t TelemetryWebSocketPackets_=0;
std::atomic_uint64_t TelemetryKafkaPackets_=0; std::atomic_uint64_t TelemetryKafkaPackets_=0;
GWObjects::ConnectionState State_;
std::string LastStats_;
GWObjects::HealthCheck LastHealthcheck_;
std::chrono::time_point<std::chrono::high_resolution_clock> ConnectionStart_ = std::chrono::high_resolution_clock::now();
std::chrono::duration<double, std::milli> ConnectionCompletionTime_{0.0};
bool Threaded_=false;
std::atomic_bool Dead_=false;
std::atomic_bool DeviceValidated_=false;
static inline std::atomic_uint64_t ConcurrentStartingDevices_=0;
void CompleteStartup(); void CompleteStartup();
bool StartTelemetry(); bool StartTelemetry(std::uint64_t RPCID);
bool StopTelemetry(); bool StopTelemetry(std::uint64_t RPCID);
void UpdateCounts(); void UpdateCounts();
}; };

View File

@@ -6,8 +6,8 @@
namespace OpenWifi { namespace OpenWifi {
void AP_WS_Connection::Process_cfgpending(Poco::JSON::Object::Ptr ParamsObj) { void AP_WS_Connection::Process_cfgpending(Poco::JSON::Object::Ptr ParamsObj) {
if (!Connected_) { if (!State_.Connected) {
poco_warning(Logger(), fmt::format( poco_warning(Logger_, fmt::format(
"INVALID-PROTOCOL({}): Device '{}' is not following protocol", CId_, CN_)); "INVALID-PROTOCOL({}): Device '{}' is not following protocol", CId_, CN_));
Errors_++; Errors_++;
return; return;
@@ -16,9 +16,9 @@ namespace OpenWifi {
[[maybe_unused]] uint64_t UUID = ParamsObj->get(uCentralProtocol::UUID); [[maybe_unused]] uint64_t UUID = ParamsObj->get(uCentralProtocol::UUID);
[[maybe_unused]] uint64_t Active = ParamsObj->get(uCentralProtocol::ACTIVE); [[maybe_unused]] uint64_t Active = ParamsObj->get(uCentralProtocol::ACTIVE);
poco_trace(Logger(), fmt::format("CFG-PENDING({}): Active: {} Target: {}", CId_, Active, UUID)); poco_trace(Logger_, fmt::format("CFG-PENDING({}): Active: {} Target: {}", CId_, Active, UUID));
} else { } else {
poco_warning(Logger(), fmt::format("CFG-PENDING({}): Missing some parameters", CId_)); poco_warning(Logger_, fmt::format("CFG-PENDING({}): Missing some parameters", CId_));
} }
} }
} }

View File

@@ -9,6 +9,8 @@
#include "framework/WebSocketClientNotifications.h" #include "framework/WebSocketClientNotifications.h"
#include "Daemon.h" #include "Daemon.h"
#include "CommandManager.h"
namespace OpenWifi { namespace OpenWifi {
void AP_WS_Connection::Process_connect(Poco::JSON::Object::Ptr ParamsObj, const std::string &Serial) { void AP_WS_Connection::Process_connect(Poco::JSON::Object::Ptr ParamsObj, const std::string &Serial) {
@@ -20,37 +22,26 @@ void AP_WS_Connection::Process_connect(Poco::JSON::Object::Ptr ParamsObj, const
auto Capabilities = ParamsObj->get(uCentralProtocol::CAPABILITIES).toString(); auto Capabilities = ParamsObj->get(uCentralProtocol::CAPABILITIES).toString();
//// change this //// change this
CN_ = SerialNumber_ = Serial; SerialNumber_ = Serial;
SerialNumberInt_ = Utils::SerialNumberToInt(SerialNumber_); SerialNumberInt_ = Utils::SerialNumberToInt(SerialNumber_);
DeviceRegistry()->SetSessionDetails(this,SerialNumberInt_, ConnectionId_);
Session_->State_.UUID = UUID; CommandManager()->ClearQueue(SerialNumberInt_);
Session_->State_.Firmware = Firmware;
Session_->State_.PendingUUID = 0; DeviceRegistry()->SetSessionDetails(State_.sessionId,SerialNumberInt_);
Session_->State_.LastContact = OpenWifi::Now(); State_.UUID = UUID;
Session_->State_.Address = Utils::FormatIPv6(WS_->peerAddress().toString()); State_.Firmware = Firmware;
State_.PendingUUID = 0;
State_.Address = Utils::FormatIPv6(WS_->peerAddress().toString());
CId_ = SerialNumber_ + "@" + CId_; CId_ = SerialNumber_ + "@" + CId_;
// We need to verify the certificate if we have one
if ((!CN_.empty() && Utils::SerialNumberMatch(CN_, SerialNumber_)) ||
AP_WS_Server()->IsSimSerialNumber(CN_)) {
CertValidation_ = GWObjects::VERIFIED;
poco_information(Logger(), fmt::format("CONNECT({}): Fully validated and authenticated device.", CId_));
} else {
if (CN_.empty())
poco_information(Logger(), fmt::format("CONNECT({}): Not authenticated or validated.", CId_));
else
poco_information(Logger(), fmt::format(
"CONNECT({}): Authenticated but not validated. Serial='{}' CN='{}'", CId_,
Serial, CN_));
}
Session_->State_.VerifiedCertificate = CertValidation_;
auto IP = PeerAddress_.toString(); auto IP = PeerAddress_.toString();
if(IP.substr(0,7)=="::ffff:") { if(IP.substr(0,7)=="::ffff:") {
IP = IP.substr(7); IP = IP.substr(7);
} }
Session_->State_.locale = FindCountryFromIP()->Get(IP);
State_.locale = FindCountryFromIP()->Get(IP);
GWObjects::Device DeviceInfo; GWObjects::Device DeviceInfo;
auto DeviceExists = StorageService()->GetDevice(SerialNumber_,DeviceInfo); auto DeviceExists = StorageService()->GetDevice(SerialNumber_,DeviceInfo);
// std::cout << "Connecting: " << SerialNumber_ << std::endl;
if (Daemon()->AutoProvisioning() && !DeviceExists) { if (Daemon()->AutoProvisioning() && !DeviceExists) {
StorageService()->CreateDefaultDevice(SerialNumber_, Capabilities, Firmware, StorageService()->CreateDefaultDevice(SerialNumber_, Capabilities, Firmware,
Compatible_, PeerAddress_); Compatible_, PeerAddress_);
@@ -64,8 +55,8 @@ void AP_WS_Connection::Process_connect(Poco::JSON::Object::Ptr ParamsObj, const
WebSocketClientNotificationDeviceFirmwareUpdated(SerialNumber_, Firmware); WebSocketClientNotificationDeviceFirmwareUpdated(SerialNumber_, Firmware);
} }
if(DeviceInfo.locale != Session_->State_.locale) { if(DeviceInfo.locale != State_.locale) {
DeviceInfo.locale = Session_->State_.locale; DeviceInfo.locale = State_.locale;
Updated = true; Updated = true;
} }
@@ -79,24 +70,52 @@ void AP_WS_Connection::Process_connect(Poco::JSON::Object::Ptr ParamsObj, const
} }
uint64_t UpgradedUUID=0; uint64_t UpgradedUUID=0;
LookForUpgrade(UUID,UpgradedUUID); LookForUpgrade(UUID,UpgradedUUID);
Session_->State_.UUID = UpgradedUUID; State_.UUID = UpgradedUUID;
}
State_.Compatible = Compatible_;
State_.Connected = true;
ConnectionCompletionTime_ = std::chrono::high_resolution_clock::now() - ConnectionStart_;
State_.connectionCompletionTime = ConnectionCompletionTime_.count();
if(State_.VerifiedCertificate == GWObjects::VALID_CERTIFICATE) {
if (( Utils::SerialNumberMatch(CN_, SerialNumber_, AP_WS_Server()->MismatchDepth())) ||
AP_WS_Server()->IsSimSerialNumber(CN_)) {
State_.VerifiedCertificate = GWObjects::VERIFIED;
poco_information(Logger_, fmt::format("CONNECT({}): Fully validated and authenticated device. Session={} ConnectionCompletion Time={}",
CId_,
State_.sessionId,
State_.connectionCompletionTime ));
} else {
State_.VerifiedCertificate = GWObjects::MISMATCH_SERIAL;
if(AP_WS_Server()->AllowSerialNumberMismatch()) {
poco_information(
Logger_, fmt::format("CONNECT({}): Serial number mismatch allowed. CN={} Serial={} Session={} ConnectionCompletion Time={}",
CId_, CN_, SerialNumber_, State_.sessionId,
State_.connectionCompletionTime));
} else {
poco_information(
Logger_, fmt::format("CONNECT({}): Serial number mismatch disallowed. Device rejected. CN={} Serial={} Session={} ConnectionCompletion Time={}",
CId_, CN_, SerialNumber_, State_.sessionId,
State_.connectionCompletionTime));
return EndConnection();
}
}
} }
Session_->State_.Compatible = Compatible_;
WebSocketClientNotificationDeviceConnected(SerialNumber_); WebSocketClientNotificationDeviceConnected(SerialNumber_);
if (KafkaManager()->Enabled()) { if (KafkaManager()->Enabled()) {
Poco::JSON::Stringifier Stringify; Poco::JSON::Stringifier Stringify;
ParamsObj->set(uCentralProtocol::CONNECTIONIP, CId_); ParamsObj->set(uCentralProtocol::CONNECTIONIP, CId_);
ParamsObj->set("locale", Session_->State_.locale ); ParamsObj->set("locale", State_.locale );
ParamsObj->set(uCentralProtocol::TIMESTAMP, OpenWifi::Now()); ParamsObj->set(uCentralProtocol::TIMESTAMP, OpenWifi::Now());
std::ostringstream OS; std::ostringstream OS;
Stringify.condense(ParamsObj, OS); Stringify.condense(ParamsObj, OS);
KafkaManager()->PostMessage(KafkaTopics::CONNECTION, SerialNumber_, OS.str()); KafkaManager()->PostMessage(KafkaTopics::CONNECTION, SerialNumber_, OS.str());
} }
Connected_ = true;
} else { } else {
poco_warning(Logger(),fmt::format("INVALID-PROTOCOL({}): Missing one of uuid, firmware, or capabilities", CId_)); poco_warning(Logger_,fmt::format("INVALID-PROTOCOL({}): Missing one of uuid, firmware, or capabilities", CId_));
Errors_++; Errors_++;
} }
} }

View File

@@ -8,7 +8,7 @@
namespace OpenWifi { namespace OpenWifi {
void AP_WS_Connection::Process_crashlog(Poco::JSON::Object::Ptr ParamsObj) { void AP_WS_Connection::Process_crashlog(Poco::JSON::Object::Ptr ParamsObj) {
if (ParamsObj->has(uCentralProtocol::UUID) && ParamsObj->has(uCentralProtocol::LOGLINES)) { if (ParamsObj->has(uCentralProtocol::UUID) && ParamsObj->has(uCentralProtocol::LOGLINES)) {
poco_trace(Logger(), fmt::format("CRASH-LOG({}): new entry.", CId_)); poco_trace(Logger_, fmt::format("CRASH-LOG({}): new entry.", CId_));
auto LogLines = ParamsObj->get(uCentralProtocol::LOGLINES); auto LogLines = ParamsObj->get(uCentralProtocol::LOGLINES);
std::string LogText; std::string LogText;
if (LogLines.isArray()) { if (LogLines.isArray()) {
@@ -27,7 +27,7 @@ namespace OpenWifi {
StorageService()->AddLog(DeviceLog); StorageService()->AddLog(DeviceLog);
} else { } else {
poco_warning(Logger(), fmt::format("LOG({}): Missing parameters.", CId_)); poco_warning(Logger_, fmt::format("LOG({}): Missing parameters.", CId_));
return; return;
} }
} }

View File

@@ -8,8 +8,8 @@
namespace OpenWifi { namespace OpenWifi {
void AP_WS_Connection::Process_deviceupdate(Poco::JSON::Object::Ptr ParamsObj, std::string &Serial) { void AP_WS_Connection::Process_deviceupdate(Poco::JSON::Object::Ptr ParamsObj, std::string &Serial) {
if (!Connected_) { if (!State_.Connected) {
poco_warning(Logger(), fmt::format( poco_warning(Logger_, fmt::format(
"INVALID-PROTOCOL({}): Device '{}' is not following protocol", CId_, CN_)); "INVALID-PROTOCOL({}): Device '{}' is not following protocol", CId_, CN_));
Errors_++; Errors_++;
return; return;
@@ -18,7 +18,7 @@ namespace OpenWifi {
auto Password = ParamsObj->get("currentPassword").toString(); auto Password = ParamsObj->get("currentPassword").toString();
StorageService()->SetDevicePassword(Serial, Password); StorageService()->SetDevicePassword(Serial, Password);
poco_trace(Logger(), fmt::format("DEVICEUPDATE({}): Device is updating its login password.", Serial)); poco_trace(Logger_, fmt::format("DEVICEUPDATE({}): Device is updating its login password.", Serial));
} }
} }

View File

@@ -7,9 +7,9 @@
namespace OpenWifi { namespace OpenWifi {
void AP_WS_Connection::Process_healthcheck(Poco::JSON::Object::Ptr ParamsObj, const std::string &Serial) { void AP_WS_Connection::Process_healthcheck(Poco::JSON::Object::Ptr ParamsObj) {
if (!Connected_) { if (!State_.Connected) {
poco_warning(Logger(), fmt::format( poco_warning(Logger_, fmt::format(
"INVALID-PROTOCOL({}): Device '{}' is not following protocol", CId_, CN_)); "INVALID-PROTOCOL({}): Device '{}' is not following protocol", CId_, CN_));
Errors_++; Errors_++;
return; return;
@@ -27,17 +27,17 @@ void AP_WS_Connection::Process_healthcheck(Poco::JSON::Object::Ptr ParamsObj, co
request_uuid = ParamsObj->get(uCentralProtocol::REQUEST_UUID).toString(); request_uuid = ParamsObj->get(uCentralProtocol::REQUEST_UUID).toString();
if (request_uuid.empty()) { if (request_uuid.empty()) {
poco_trace(Logger(), poco_trace(Logger_,
fmt::format("HEALTHCHECK({}): UUID={} Updating.", CId_, UUID)); fmt::format("HEALTHCHECK({}): UUID={} Updating.", CId_, UUID));
} else { } else {
poco_trace(Logger(), poco_trace(Logger_,
fmt::format("HEALTHCHECK({}): UUID={} Updating for CMD={}.", CId_, fmt::format("HEALTHCHECK({}): UUID={} Updating for CMD={}.", CId_,
UUID, request_uuid)); UUID, request_uuid));
} }
uint64_t UpgradedUUID; uint64_t UpgradedUUID;
LookForUpgrade(UUID,UpgradedUUID); LookForUpgrade(UUID,UpgradedUUID);
Session_->State_.UUID = UpgradedUUID; State_.UUID = UpgradedUUID;
GWObjects::HealthCheck Check; GWObjects::HealthCheck Check;
@@ -53,7 +53,7 @@ void AP_WS_Connection::Process_healthcheck(Poco::JSON::Object::Ptr ParamsObj, co
StorageService()->SetCommandResult(request_uuid, CheckData); StorageService()->SetCommandResult(request_uuid, CheckData);
} }
DeviceRegistry()->SetHealthcheck(Serial, Check); LastHealthcheck_ = Check;
if (KafkaManager()->Enabled()) { if (KafkaManager()->Enabled()) {
Poco::JSON::Stringifier Stringify; Poco::JSON::Stringifier Stringify;
std::ostringstream OS; std::ostringstream OS;
@@ -62,7 +62,7 @@ void AP_WS_Connection::Process_healthcheck(Poco::JSON::Object::Ptr ParamsObj, co
KafkaManager()->PostMessage(KafkaTopics::HEALTHCHECK, SerialNumber_, OS.str()); KafkaManager()->PostMessage(KafkaTopics::HEALTHCHECK, SerialNumber_, OS.str());
} }
} else { } else {
poco_warning(Logger(), fmt::format("HEALTHCHECK({}): Missing parameter", CId_)); poco_warning(Logger_, fmt::format("HEALTHCHECK({}): Missing parameter", CId_));
return; return;
} }
} }

View File

@@ -7,15 +7,15 @@
namespace OpenWifi { namespace OpenWifi {
void AP_WS_Connection::Process_log(Poco::JSON::Object::Ptr ParamsObj) { void AP_WS_Connection::Process_log(Poco::JSON::Object::Ptr ParamsObj) {
if (!Connected_) { if (!State_.Connected) {
poco_warning( poco_warning(
Logger(), Logger_,
fmt::format("INVALID-PROTOCOL({}): Device '{}' is not following protocol", CId_, CN_)); fmt::format("INVALID-PROTOCOL({}): Device '{}' is not following protocol", CId_, CN_));
Errors_++; Errors_++;
return; return;
} }
if (ParamsObj->has(uCentralProtocol::LOG) && ParamsObj->has(uCentralProtocol::SEVERITY)) { if (ParamsObj->has(uCentralProtocol::LOG) && ParamsObj->has(uCentralProtocol::SEVERITY)) {
poco_trace(Logger(), fmt::format("LOG({}): new entry.", CId_)); poco_trace(Logger_, fmt::format("LOG({}): new entry.", CId_));
auto Log = ParamsObj->get(uCentralProtocol::LOG).toString(); auto Log = ParamsObj->get(uCentralProtocol::LOG).toString();
auto Severity = ParamsObj->get(uCentralProtocol::SEVERITY); auto Severity = ParamsObj->get(uCentralProtocol::SEVERITY);
std::string DataStr = uCentralProtocol::EMPTY_JSON_DOC; std::string DataStr = uCentralProtocol::EMPTY_JSON_DOC;
@@ -31,10 +31,10 @@ namespace OpenWifi {
.Severity = Severity, .Severity = Severity,
.Recorded = (uint64_t)time(nullptr), .Recorded = (uint64_t)time(nullptr),
.LogType = 0, .LogType = 0,
.UUID = Session_->State_.UUID}; .UUID = State_.UUID};
StorageService()->AddLog(DeviceLog); StorageService()->AddLog(DeviceLog);
} else { } else {
poco_warning(Logger(), fmt::format("LOG({}): Missing parameters.", CId_)); poco_warning(Logger_, fmt::format("LOG({}): Missing parameters.", CId_));
return; return;
} }
} }

View File

@@ -8,9 +8,9 @@ namespace OpenWifi {
void AP_WS_Connection::Process_ping(Poco::JSON::Object::Ptr ParamsObj) { void AP_WS_Connection::Process_ping(Poco::JSON::Object::Ptr ParamsObj) {
if (ParamsObj->has(uCentralProtocol::UUID)) { if (ParamsObj->has(uCentralProtocol::UUID)) {
[[maybe_unused]] uint64_t UUID = ParamsObj->get(uCentralProtocol::UUID); [[maybe_unused]] uint64_t UUID = ParamsObj->get(uCentralProtocol::UUID);
poco_trace(Logger(), fmt::format("PING({}): Current config is {}", CId_, UUID)); poco_trace(Logger_, fmt::format("PING({}): Current config is {}", CId_, UUID));
} else { } else {
poco_warning(Logger(), fmt::format("PING({}): Missing parameter.", CId_)); poco_warning(Logger_, fmt::format("PING({}): Missing parameter.", CId_));
} }
} }
} }

View File

@@ -48,14 +48,14 @@ namespace OpenWifi {
Cmd.Details = O.str(); Cmd.Details = O.str();
bool Sent; bool Sent;
CommandManager()->PostCommand(CommandManager()->NextRPCId(),SerialNumber_, Cmd.Command, Params, Cmd.UUID, Sent); CommandManager()->PostCommand(CommandManager()->NextRPCId(),SerialNumber_, Cmd.Command, Params, Cmd.UUID, Sent);
StorageService()->AddCommand(SerialNumber_, Cmd, Storage::COMMAND_EXECUTED); StorageService()->AddCommand(SerialNumber_, Cmd, Storage::CommandExecutionType::COMMAND_EXECUTED);
poco_information(Logger(), fmt::format("RECOVERY({}): Recovery mode received, need for a reboot.", CId_)); poco_information(Logger_, fmt::format("RECOVERY({}): Recovery mode received, need for a reboot.", CId_));
} else { } else {
poco_information(Logger(), fmt::format( poco_information(Logger_, fmt::format(
"RECOVERY({}): Recovery mode received, no need for a reboot.", CId_)); "RECOVERY({}): Recovery mode received, no need for a reboot.", CId_));
} }
} else { } else {
poco_warning(Logger(), fmt::format("RECOVERY({}): Recovery missing one of serialnumber, firmware, uuid, loglines, reboot", poco_warning(Logger_, fmt::format("RECOVERY({}): Recovery missing one of serialnumber, firmware, uuid, loglines, reboot",
CId_)); CId_));
} }
} }

View File

@@ -9,12 +9,13 @@
namespace OpenWifi { namespace OpenWifi {
void AP_WS_Connection::Process_state(Poco::JSON::Object::Ptr ParamsObj) { void AP_WS_Connection::Process_state(Poco::JSON::Object::Ptr ParamsObj) {
if (!Connected_) { if (!State_.Connected) {
poco_warning(Logger(), fmt::format( poco_warning(Logger_, fmt::format(
"INVALID-PROTOCOL({}): Device '{}' is not following protocol", CId_, CN_)); "INVALID-PROTOCOL({}): Device '{}' is not following protocol", CId_, CN_));
Errors_++; Errors_++;
return; return;
} }
if (ParamsObj->has(uCentralProtocol::UUID) && ParamsObj->has(uCentralProtocol::STATE)) { if (ParamsObj->has(uCentralProtocol::UUID) && ParamsObj->has(uCentralProtocol::STATE)) {
uint64_t UUID = ParamsObj->get(uCentralProtocol::UUID); uint64_t UUID = ParamsObj->get(uCentralProtocol::UUID);
auto StateStr = ParamsObj->get(uCentralProtocol::STATE).toString(); auto StateStr = ParamsObj->get(uCentralProtocol::STATE).toString();
@@ -25,16 +26,16 @@ namespace OpenWifi {
request_uuid = ParamsObj->get(uCentralProtocol::REQUEST_UUID).toString(); request_uuid = ParamsObj->get(uCentralProtocol::REQUEST_UUID).toString();
if (request_uuid.empty()) { if (request_uuid.empty()) {
poco_trace(Logger(), fmt::format("STATE({}): UUID={} Updating.", CId_, UUID)); poco_trace(Logger_, fmt::format("STATE({}): UUID={} Updating.", CId_, UUID));
} else { } else {
poco_trace(Logger(), fmt::format("STATE({}): UUID={} Updating for CMD={}.", poco_trace(Logger_, fmt::format("STATE({}): UUID={} Updating for CMD={}.",
CId_, UUID, request_uuid)); CId_, UUID, request_uuid));
} }
uint64_t UpgradedUUID; uint64_t UpgradedUUID;
LookForUpgrade(UUID,UpgradedUUID); LookForUpgrade(UUID,UpgradedUUID);
Session_->State_.UUID = UpgradedUUID; State_.UUID = UpgradedUUID;
Session_->LastStats = StateStr; LastStats_ = StateStr;
GWObjects::Statistics Stats{ GWObjects::Statistics Stats{
.SerialNumber = SerialNumber_, .UUID = UUID, .Data = StateStr}; .SerialNumber = SerialNumber_, .UUID = UUID, .Data = StateStr};
@@ -44,8 +45,8 @@ namespace OpenWifi {
StorageService()->SetCommandResult(request_uuid, StateStr); StorageService()->SetCommandResult(request_uuid, StateStr);
} }
StateUtils::ComputeAssociations(StateObj, Session_->State_.Associations_2G, StateUtils::ComputeAssociations(StateObj, State_.Associations_2G,
Session_->State_.Associations_5G); State_.Associations_5G);
if (KafkaManager()->Enabled()) { if (KafkaManager()->Enabled()) {
Poco::JSON::Stringifier Stringify; Poco::JSON::Stringifier Stringify;
@@ -60,7 +61,7 @@ namespace OpenWifi {
WebSocketClientServer()->SendNotification(N); WebSocketClientServer()->SendNotification(N);
} else { } else {
poco_warning(Logger(), fmt::format("STATE({}): Invalid request. Missing serial, uuid, or state", CId_)); poco_warning(Logger_, fmt::format("STATE({}): Invalid request. Missing serial, uuid, or state", CId_));
} }
} }
} }

View File

@@ -4,11 +4,12 @@
#include "AP_WS_Connection.h" #include "AP_WS_Connection.h"
#include "TelemetryStream.h" #include "TelemetryStream.h"
#include "CommandManager.h"
namespace OpenWifi { namespace OpenWifi {
void AP_WS_Connection::Process_telemetry(Poco::JSON::Object::Ptr ParamsObj) { void AP_WS_Connection::Process_telemetry(Poco::JSON::Object::Ptr ParamsObj) {
if (!Connected_) { if (!State_.Connected) {
poco_warning(Logger(), fmt::format( poco_warning(Logger_, fmt::format(
"INVALID-PROTOCOL({}): Device '{}' is not following protocol", CId_, CN_)); "INVALID-PROTOCOL({}): Device '{}' is not following protocol", CId_, CN_));
Errors_++; Errors_++;
return; return;
@@ -24,30 +25,30 @@ namespace OpenWifi {
if(now<TelemetryWebSocketTimer_) { if(now<TelemetryWebSocketTimer_) {
// std::cout << SerialNumber_ << ": Updating WebSocket telemetry" << std::endl; // std::cout << SerialNumber_ << ": Updating WebSocket telemetry" << std::endl;
TelemetryWebSocketPackets_++; TelemetryWebSocketPackets_++;
Session_->State_.websocketPackets = TelemetryWebSocketPackets_; State_.websocketPackets = TelemetryWebSocketPackets_;
TelemetryStream()->UpdateEndPoint(SerialNumberInt_, SS.str()); TelemetryStream()->UpdateEndPoint(SerialNumberInt_, SS.str());
} else { } else {
StopWebSocketTelemetry(); StopWebSocketTelemetry(CommandManager()->NextRPCId());
} }
} }
if (TelemetryKafkaRefCount_) { if (TelemetryKafkaRefCount_) {
if(KafkaManager()->Enabled() && now<TelemetryKafkaTimer_) { if(KafkaManager()->Enabled() && now<TelemetryKafkaTimer_) {
// std::cout << SerialNumber_ << ": Updating Kafka telemetry" << std::endl; // std::cout << SerialNumber_ << ": Updating Kafka telemetry" << std::endl;
TelemetryKafkaPackets_++; TelemetryKafkaPackets_++;
Session_->State_.kafkaPackets = TelemetryKafkaPackets_; State_.kafkaPackets = TelemetryKafkaPackets_;
KafkaManager()->PostMessage(KafkaTopics::DEVICE_TELEMETRY, SerialNumber_, KafkaManager()->PostMessage(KafkaTopics::DEVICE_TELEMETRY, SerialNumber_,
SS.str()); SS.str());
} else { } else {
StopKafkaTelemetry(); StopKafkaTelemetry(CommandManager()->NextRPCId());
} }
} }
} else { } else {
poco_debug(Logger(),fmt::format("TELEMETRY({}): Invalid telemetry packet.",SerialNumber_)); poco_debug(Logger_,fmt::format("TELEMETRY({}): Invalid telemetry packet.",SerialNumber_));
} }
} else { } else {
// if we are ignoring telemetry, then close it down on the device. // if we are ignoring telemetry, then close it down on the device.
poco_debug(Logger(),fmt::format("TELEMETRY({}): Stopping runaway telemetry.",SerialNumber_)); poco_debug(Logger_,fmt::format("TELEMETRY({}): Stopping runaway telemetry.",SerialNumber_));
StopTelemetry(); StopTelemetry(CommandManager()->NextRPCId());
} }
} }
} }

View File

@@ -5,6 +5,8 @@
#pragma once #pragma once
#include <string> #include <string>
#include <shared_mutex>
#include "Poco/Net/SocketAcceptor.h" #include "Poco/Net/SocketAcceptor.h"
#include "Poco/Environment.h" #include "Poco/Environment.h"
@@ -12,10 +14,9 @@ namespace OpenWifi {
class AP_WS_ReactorThreadPool { class AP_WS_ReactorThreadPool {
public: public:
explicit AP_WS_ReactorThreadPool() { explicit AP_WS_ReactorThreadPool() {
if(Poco::Environment::processorCount()>8) NumberOfThreads_ = Poco::Environment::processorCount()*2;
NumberOfThreads_ = Poco::Environment::processorCount()/2; if(NumberOfThreads_==0)
else NumberOfThreads_=4;
NumberOfThreads_ = 2;
} }
~ AP_WS_ReactorThreadPool() { ~ AP_WS_ReactorThreadPool() {
@@ -45,14 +46,14 @@ namespace OpenWifi {
} }
Poco::Net::SocketReactor &NextReactor() { Poco::Net::SocketReactor &NextReactor() {
std::lock_guard G(Mutex_); std::shared_lock Lock(Mutex_);
NextReactor_++; NextReactor_++;
NextReactor_ %= NumberOfThreads_; NextReactor_ %= NumberOfThreads_;
return *Reactors_[NextReactor_]; return *Reactors_[NextReactor_];
} }
private: private:
std::mutex Mutex_; std::shared_mutex Mutex_;
uint64_t NumberOfThreads_; uint64_t NumberOfThreads_;
uint64_t NextReactor_ = 0; uint64_t NextReactor_ = 0;
std::vector<std::unique_ptr<Poco::Net::SocketReactor>> Reactors_; std::vector<std::unique_ptr<Poco::Net::SocketReactor>> Reactors_;

View File

@@ -19,9 +19,9 @@ namespace OpenWifi {
void AP_WS_RequestHandler::handleRequest(Poco::Net::HTTPServerRequest &request, void AP_WS_RequestHandler::handleRequest(Poco::Net::HTTPServerRequest &request,
Poco::Net::HTTPServerResponse &response) { Poco::Net::HTTPServerResponse &response) {
try { try {
new AP_WS_Connection(request,response); AP_WS_Server()->AddConnection(id_,std::make_shared<AP_WS_Connection>(request,response,id_, Logger_, AP_WS_Server()->NextReactor()));
} catch (...) { } catch (...) {
Logger_.warning("Exception during WS creation"); poco_warning(Logger_,"Exception during WS creation");
} }
}; };
@@ -38,8 +38,15 @@ namespace OpenWifi {
int AP_WS_Server::Start() { int AP_WS_Server::Start() {
AllowSerialNumberMismatch_ = MicroService::instance().ConfigGetBool("openwifi.certificates.allowmismatch",true);
MismatchDepth_ = MicroService::instance().ConfigGetInt("openwifi.certificates.mismatchdepth",2);
Reactor_pool_ = std::make_unique<AP_WS_ReactorThreadPool>();
Reactor_pool_->Start();
for(const auto & Svr : ConfigServersList_ ) { for(const auto & Svr : ConfigServersList_ ) {
Logger().notice(fmt::format("Starting: {}:{} Keyfile:{} CertFile: {}", Svr.Address(),
poco_notice(Logger(),fmt::format("Starting: {}:{} Keyfile:{} CertFile: {}", Svr.Address(),
Svr.Port(), Svr.KeyFile(), Svr.CertFile())); Svr.Port(), Svr.KeyFile(), Svr.CertFile()));
Svr.LogCert(Logger()); Svr.LogCert(Logger());
@@ -48,7 +55,7 @@ namespace OpenWifi {
if (!IsCertOk()) { if (!IsCertOk()) {
IssuerCert_ = std::make_unique<Poco::Crypto::X509Certificate>(Svr.IssuerCertFile()); IssuerCert_ = std::make_unique<Poco::Crypto::X509Certificate>(Svr.IssuerCertFile());
Logger().information( poco_information(Logger(),
fmt::format("Certificate Issuer Name:{}", IssuerCert_->issuerName())); fmt::format("Certificate Issuer Name:{}", IssuerCert_->issuerName()));
} }
@@ -62,7 +69,6 @@ namespace OpenWifi {
P.caLocation = Svr.Cas(); P.caLocation = Svr.Cas();
auto Context = Poco::AutoPtr<Poco::Net::Context>(new Poco::Net::Context(Poco::Net::Context::TLS_SERVER_USE, P)); auto Context = Poco::AutoPtr<Poco::Net::Context>(new Poco::Net::Context(Poco::Net::Context::TLS_SERVER_USE, P));
Context->enableExtendedCertificateVerification(false);
if(!Svr.KeyFilePassword().empty()) { if(!Svr.KeyFilePassword().empty()) {
auto PassphraseHandler = Poco::SharedPtr<MyPrivateKeyPassphraseHandler>( new MyPrivateKeyPassphraseHandler(Svr.KeyFilePassword(),Logger())); auto PassphraseHandler = Poco::SharedPtr<MyPrivateKeyPassphraseHandler>( new MyPrivateKeyPassphraseHandler(Svr.KeyFilePassword(),Logger()));
@@ -83,11 +89,13 @@ namespace OpenWifi {
Poco::Crypto::RSAKey Key("", Svr.KeyFile(), Svr.KeyFilePassword()); Poco::Crypto::RSAKey Key("", Svr.KeyFile(), Svr.KeyFilePassword());
Context->usePrivateKey(Key); Context->usePrivateKey(Key);
Context->enableSessionCache();
Context->setSessionCacheSize(0); Context->setSessionCacheSize(0);
Context->setSessionTimeout(60); Context->setSessionTimeout(120);
Context->flushSessionCache();
Context->enableSessionCache(true);
Context->enableExtendedCertificateVerification(false); Context->enableExtendedCertificateVerification(false);
Context->disableStatelessSessionResumption(); // Context->disableStatelessSessionResumption();
Context->disableProtocols(Poco::Net::Context::PROTO_TLSV1 | Poco::Net::Context::PROTO_TLSV1_1);
auto WebServerHttpParams = new Poco::Net::HTTPServerParams; auto WebServerHttpParams = new Poco::Net::HTTPServerParams;
WebServerHttpParams->setMaxThreads(50); WebServerHttpParams->setMaxThreads(50);
@@ -117,8 +125,6 @@ namespace OpenWifi {
} }
ReactorThread_.start(Reactor_); ReactorThread_.start(Reactor_);
Reactor_pool_ = std::make_unique<AP_WS_ReactorThreadPool>();
Reactor_pool_->Start();
auto ProvString = MicroService::instance().ConfigGetString("autoprovisioning.process","default"); auto ProvString = MicroService::instance().ConfigGetString("autoprovisioning.process","default");
if(ProvString!="default") { if(ProvString!="default") {
@@ -137,11 +143,13 @@ namespace OpenWifi {
SimulatorEnabled_ = !SimulatorId_.empty(); SimulatorEnabled_ = !SimulatorId_.empty();
Utils::SetThreadName(ReactorThread_,"dev:react:head"); Utils::SetThreadName(ReactorThread_,"dev:react:head");
Running_ = true;
return 0; return 0;
} }
void AP_WS_Server::Stop() { void AP_WS_Server::Stop() {
Logger().notice("Stopping reactors..."); poco_information(Logger(),"Stopping...");
Running_ = false;
for(auto &server:WebServers_) { for(auto &server:WebServers_) {
server->stopAll(); server->stopAll();
@@ -149,6 +157,7 @@ namespace OpenWifi {
Reactor_pool_->Stop(); Reactor_pool_->Stop();
Reactor_.stop(); Reactor_.stop();
ReactorThread_.join(); ReactorThread_.join();
poco_information(Logger(),"Stopped...");
} }
} //namespace } //namespace

View File

@@ -27,14 +27,16 @@ namespace OpenWifi {
class AP_WS_RequestHandler : public Poco::Net::HTTPRequestHandler { class AP_WS_RequestHandler : public Poco::Net::HTTPRequestHandler {
public: public:
explicit AP_WS_RequestHandler(Poco::Logger &L) explicit AP_WS_RequestHandler(Poco::Logger &L, std::uint64_t id)
: Logger_(L) { : Logger_(L),
id_(id){
}; };
void handleRequest(Poco::Net::HTTPServerRequest &request, void handleRequest(Poco::Net::HTTPServerRequest &request,
Poco::Net::HTTPServerResponse &response) override; Poco::Net::HTTPServerResponse &response) override;
private: private:
Poco::Logger &Logger_; Poco::Logger &Logger_;
std::uint64_t id_=0;
}; };
class AP_WS_RequestHandlerFactory : public Poco::Net::HTTPRequestHandlerFactory { class AP_WS_RequestHandlerFactory : public Poco::Net::HTTPRequestHandlerFactory {
@@ -48,13 +50,14 @@ namespace OpenWifi {
if (request.find("Upgrade") != request.end() && if (request.find("Upgrade") != request.end() &&
Poco::icompare(request["Upgrade"], "websocket") == 0) { Poco::icompare(request["Upgrade"], "websocket") == 0) {
Utils::SetThreadName("ws:conn-init"); Utils::SetThreadName("ws:conn-init");
return new AP_WS_RequestHandler(Logger_); return new AP_WS_RequestHandler(Logger_,id_++);
} else { } else {
return nullptr; return nullptr;
} }
} }
private: private:
Poco::Logger &Logger_; Poco::Logger &Logger_;
inline static std::uint64_t id_=1;
}; };
class AP_WS_Server : public SubSystemServer { class AP_WS_Server : public SubSystemServer {
@@ -71,7 +74,7 @@ namespace OpenWifi {
// Poco::Net::SocketReactor & GetNextReactor() { return ReactorPool_.NextReactor(); } // Poco::Net::SocketReactor & GetNextReactor() { return ReactorPool_.NextReactor(); }
inline bool IsSimSerialNumber(const std::string & SerialNumber) const { inline bool IsSimSerialNumber(const std::string & SerialNumber) const {
return IsSim(SerialNumber) && SerialNumber == SimulatorId_; return IsSim(Poco::toLower(SerialNumber)) && Poco::toLower(SerialNumber) == Poco::toLower(SimulatorId_);
} }
inline static bool IsSim(const std::string & SerialNumber) { inline static bool IsSim(const std::string & SerialNumber) {
@@ -82,22 +85,55 @@ namespace OpenWifi {
return SimulatorEnabled_; return SimulatorEnabled_;
} }
inline bool AllowSerialNumberMismatch() const {
return AllowSerialNumberMismatch_;
}
inline std::uint64_t MismatchDepth() const {
return MismatchDepth_;
}
inline bool UseProvisioning() const { return LookAtProvisioning_; } inline bool UseProvisioning() const { return LookAtProvisioning_; }
inline bool UseDefaults() const { return UseDefaultConfig_; } inline bool UseDefaults() const { return UseDefaultConfig_; }
[[nodiscard]] inline Poco::Net::SocketReactor & NextReactor() { return Reactor_pool_->NextReactor(); } [[nodiscard]] inline Poco::Net::SocketReactor & NextReactor() { return Reactor_pool_->NextReactor(); }
[[nodiscard]] inline bool Running() const { return Running_; }
private: inline void AddConnection(std::uint64_t session_id, std::shared_ptr<AP_WS_Connection> Connection ) {
std::unique_ptr<Poco::Crypto::X509Certificate> IssuerCert_; std::unique_lock Lock(LocalMutex_);
std::list<std::unique_ptr<Poco::Net::HTTPServer>> WebServers_; Connections_[session_id] = Connection;
Poco::Net::SocketReactor Reactor_; }
Poco::Thread ReactorThread_;
std::string SimulatorId_; inline void DeleteConnection(std::uint64_t session_id) {
Poco::ThreadPool DeviceConnectionPool_{"ws:dev-pool", 2, 32}; std::unique_lock Lock(LocalMutex_);
bool LookAtProvisioning_ = false; Connections_.erase(session_id);
bool UseDefaultConfig_ = true; }
bool SimulatorEnabled_=false;
std::unique_ptr<AP_WS_ReactorThreadPool> Reactor_pool_; inline std::shared_ptr<AP_WS_Connection> FindConnection(std::uint64_t session_id) const {
std::shared_lock Lock(LocalMutex_);
auto Connection = Connections_.find(session_id);
if(Connection!=end(Connections_))
return Connection->second;
return nullptr;
}
private:
mutable std::shared_mutex LocalMutex_;
std::unique_ptr<Poco::Crypto::X509Certificate> IssuerCert_;
std::list<std::unique_ptr<Poco::Net::HTTPServer>> WebServers_;
Poco::Net::SocketReactor Reactor_;
Poco::Thread ReactorThread_;
std::string SimulatorId_;
Poco::ThreadPool DeviceConnectionPool_{"ws:dev-pool", 2, 32};
bool LookAtProvisioning_ = false;
bool UseDefaultConfig_ = true;
bool SimulatorEnabled_=false;
std::unique_ptr<AP_WS_ReactorThreadPool> Reactor_pool_;
std::atomic_bool Running_=false;
std::map<std::uint64_t, std::shared_ptr<AP_WS_Connection>> Connections_;
std::atomic_bool AllowSerialNumberMismatch_=true;
std::atomic_uint64_t MismatchDepth_=2;
AP_WS_Server() noexcept: AP_WS_Server() noexcept:
SubSystemServer("WebSocketServer", "WS-SVR", "ucentral.websocket") { SubSystemServer("WebSocketServer", "WS-SVR", "ucentral.websocket") {

View File

@@ -5,6 +5,7 @@
#pragma once #pragma once
#include "framework/MicroService.h" #include "framework/MicroService.h"
#include "nlohmann/json.hpp" #include "nlohmann/json.hpp"
namespace OpenWifi { namespace OpenWifi {

View File

@@ -7,115 +7,148 @@
// //
#include <fstream> #include <fstream>
#include "framework/MicroService.h"
#include "Poco/JSON/Object.h" #include "Poco/JSON/Object.h"
#include "Poco/JSON/Parser.h" #include "Poco/JSON/Parser.h"
#include "Poco/File.h" #include "Poco/File.h"
#include "CentralConfig.h" #include "CentralConfig.h"
#include "framework/MicroService.h"
#include "Daemon.h" #include "Daemon.h"
namespace OpenWifi::Config { namespace OpenWifi::Config {
const static std::string BasicConfig { const static std::string BasicConfig {
R"lit({ R"lit(
"uuid": 1, {
"radios": [ "interfaces": [
{ {
"band": "5G", "ethernet": [
"country": "CA", {
"channel-mode": "HE", "select-ports": [
"channel-width": 80, "WAN*"
"channel": 32 ]
} }
], ],
"ipv4": {
"interfaces": [ "addressing": "dynamic"
{ },
"name": "WAN", "name": "WAN",
"role": "upstream", "role": "upstream",
"services": [ "lldp" ], "services": [
"ethernet": [ "ssh",
{ "lldp",
"select-ports": [ "dhcp-snooping"
"WAN*" ],
] "ssids": [
} {
], "bss-mode": "ap",
"ipv4": { "encryption": {
"addressing": "dynamic" "ieee80211w": "optional",
}, "key": "OpenWifi",
"ssids": [ "proto": "psk2"
{ },
"name": "OpenWifi", "name": "OpenWifi",
"wifi-bands": [ "services": [
"5G" "wifi-frames"
], ],
"bss-mode": "ap", "wifi-bands": [
"encryption": { "2G","5G"
"proto": "psk2", ]
"key": "OpenWifi", }
"ieee80211w": "optional" ]
} },
} {
] "ethernet": [
}, {
{ "select-ports": [
"name": "LAN", "LAN*"
"role": "downstream", ]
"services": [ "ssh", "lldp" ], }
"ethernet": [ ],
{ "ipv4": {
"select-ports": [ "addressing": "static",
"LAN*" "dhcp": {
] "lease-count": 10000,
} "lease-first": 10,
], "lease-time": "6h"
"ipv4": { },
"addressing": "static", "subnet": "192.168.1.1/16"
"subnet": "192.168.1.1/24", },
"dhcp": { "name": "LAN",
"lease-first": 10, "role": "downstream",
"lease-count": 100, "services": [
"lease-time": "6h" "ssh",
} "lldp",
}, "dhcp-snooping"
"ssids": [ ]
{ }
"name": "OpenWifi", ],
"wifi-bands": [ "metrics": {
"5G" "dhcp-snooping": {
], "filters": [
"bss-mode": "ap", "ack",
"encryption": { "discover",
"proto": "psk2", "offer",
"key": "OpenWifi", "request",
"ieee80211w": "optional" "solicit",
} "reply",
} "renew"
] ]
},
} "health": {
], "interval": 120
"metrics": { },
"statistics": { "statistics": {
"interval": 120, "interval": 60,
"types": [ "ssids", "lldp", "clients" ] "types": [
}, "ssids",
"health": { "lldp",
"interval": 120 "clients"
} ]
}, },
"services": { "wifi-frames": {
"lldp": { "filters": [
"describe": "uCentral", "probe",
"location": "universe" "auth",
}, "assoc",
"ssh": { "disassoc",
"port": 22 "deauth",
} "local-deauth",
} "inactive-deauth",
})lit"}; "key-mismatch",
"beacon-report",
"radar-detected"
]
}
},
"radios": [
{
"band": "2G",
"channel": "auto",
"channel-mode": "HE",
"country": "CA"
},
{
"allow-dfs": true,
"band": "5G",
"channel": "auto",
"channel-mode": "HE",
"country": "CA"
}
],
"services": {
"lldp": {
"describe": "TIP OpenWiFi",
"location": "QA"
},
"ssh": {
"port": 22
}
},
"uuid": 2
}
)lit"};
void Config::SetBasicConfigFile() { void Config::SetBasicConfigFile() {
try { try {

View File

@@ -8,12 +8,13 @@
#include <algorithm> #include <algorithm>
#include "framework/MicroService.h"
#include "Poco/JSON/Parser.h" #include "Poco/JSON/Parser.h"
#include "CommandManager.h" #include "CommandManager.h"
#include "DeviceRegistry.h" #include "DeviceRegistry.h"
#include "StorageService.h" #include "StorageService.h"
#include "framework/MicroService.h"
#include "framework/ow_constants.h" #include "framework/ow_constants.h"
namespace OpenWifi { namespace OpenWifi {
@@ -21,54 +22,61 @@ namespace OpenWifi {
void CommandManager::run() { void CommandManager::run() {
Utils::SetThreadName("cmd:mgr"); Utils::SetThreadName("cmd:mgr");
Running_ = true; Running_ = true;
Poco::AutoPtr<Poco::Notification> NextMsg(ResponseQueue_.waitDequeueNotification());
while(NextMsg && Running_) { Poco::AutoPtr<Poco::Notification> NextMsg(ResponseQueue_.waitDequeueNotification());
auto Resp = dynamic_cast<RPCResponseNotification*>(NextMsg.get()); while (NextMsg && Running_) {
auto Resp = dynamic_cast<RPCResponseNotification *>(NextMsg.get());
if(Resp!= nullptr) { try {
const Poco::JSON::Object & Payload = Resp->Payload_; if (Resp != nullptr) {
const std::string & SerialNumber = Resp->SerialNumber_; const Poco::JSON::Object &Payload = Resp->Payload_;
const std::string &SerialNumber = Resp->SerialNumber_;
std::ostringstream SS; std::ostringstream SS;
Payload.stringify(SS); Payload.stringify(SS);
Logger().debug(fmt::format("({}): RPC Response received.", SerialNumber)); if (!Payload.has(uCentralProtocol::ID)) {
if(!Payload.has(uCentralProtocol::ID)){ poco_error(Logger(), fmt::format("({}): Invalid RPC response.", SerialNumber));
Logger().error(fmt::format("({}): Invalid RPC response.", SerialNumber));
} else {
uint64_t ID = Payload.get(uCentralProtocol::ID);
if (ID < 2) {
Logger().debug(fmt::format("({}): Ignoring RPC response.", SerialNumber));
} else { } else {
auto Idx = CommandTagIndex{.Id = ID, .SerialNumber = SerialNumber}; uint64_t ID = Payload.get(uCentralProtocol::ID);
std::lock_guard G(Mutex_); poco_debug(Logger(),fmt::format("({}): Processing {} response.", SerialNumber, ID));
auto RPC = OutStandingRequests_.find(Idx); if (ID > 1) {
if (RPC == OutStandingRequests_.end()) { std::unique_lock Lock(LocalMutex_);
Logger().warning( auto RPC = OutStandingRequests_.find(ID);
fmt::format("({}): Outdated RPC {}", SerialNumber, ID)); if (RPC == OutStandingRequests_.end() ||
} else { RPC->second.SerialNumber !=
std::chrono::duration<double, std::milli> rpc_execution_time = Utils::SerialNumberToInt(Resp->SerialNumber_)) {
std::chrono::high_resolution_clock::now() - RPC->second->submitted; poco_debug(Logger(),
StorageService()->CommandCompleted(RPC->second->uuid, Payload, fmt::format("({}): RPC {} completed.", SerialNumber, ID));
rpc_execution_time, true); } else {
if (RPC->second->rpc_entry) { std::chrono::duration<double, std::milli> rpc_execution_time =
RPC->second->rpc_entry->set_value(Payload); std::chrono::high_resolution_clock::now() -
RPC->second.submitted;
StorageService()->CommandCompleted(RPC->second.UUID, Payload,
rpc_execution_time, true);
if (RPC->second.rpc_entry) {
RPC->second.rpc_entry->set_value(Payload);
}
poco_debug(Logger(),
fmt::format("({}): Received RPC answer {}. Command={}",
SerialNumber, ID, RPC->second.Command));
OutStandingRequests_.erase(ID);
} }
OutstandingUUIDs_.erase(RPC->second->uuid);
OutStandingRequests_.erase(Idx);
Logger().information(
fmt::format("({}): Received RPC answer {}", SerialNumber, ID));
} }
} }
} }
} catch (const Poco::Exception &E) {
Logger().log(E);
} catch (...) {
poco_warning(Logger(),"Exception occurred during run.");
} }
NextMsg = ResponseQueue_.waitDequeueNotification(); NextMsg = ResponseQueue_.waitDequeueNotification();
} }
poco_information(Logger(),"RPC Command processor stopping.");
} }
int CommandManager::Start() { int CommandManager::Start() {
Logger().notice("Starting..."); poco_notice(Logger(),"Starting...");
ManagerThread.start(*this); ManagerThread.start(*this);
@@ -86,141 +94,191 @@ namespace OpenWifi {
} }
void CommandManager::Stop() { void CommandManager::Stop() {
Logger().notice("Stopping..."); poco_notice(Logger(),"Stopping...");
Running_ = false; Running_ = false;
JanitorTimer_.stop(); JanitorTimer_.stop();
CommandRunnerTimer_.stop(); CommandRunnerTimer_.stop();
ResponseQueue_.wakeUpAll(); ResponseQueue_.wakeUpAll();
ManagerThread.wakeUp(); ManagerThread.wakeUp();
ManagerThread.join(); ManagerThread.join();
poco_notice(Logger(),"Stopped...");
} }
void CommandManager::WakeUp() { void CommandManager::WakeUp() {
Logger().notice("Waking up..."); poco_notice(Logger(),"Waking up...");
ManagerThread.wakeUp(); ManagerThread.wakeUp();
} }
void CommandManager::onJanitorTimer([[maybe_unused]] Poco::Timer & timer) { void CommandManager::onJanitorTimer([[maybe_unused]] Poco::Timer & timer) {
std::lock_guard G(Mutex_); std::unique_lock Lock(LocalMutex_);
Utils::SetThreadName("cmd:janitor"); Utils::SetThreadName("cmd:janitor");
Poco::Logger & MyLogger = Poco::Logger::get("CMD-MGR-JANITOR"); Poco::Logger & MyLogger = Poco::Logger::get("CMD-MGR-JANITOR");
auto now = std::chrono::high_resolution_clock::now(); auto now = std::chrono::high_resolution_clock::now();
for(auto i=OutStandingRequests_.begin();i!=OutStandingRequests_.end();) { for(auto request=OutStandingRequests_.begin();request!=OutStandingRequests_.end();) {
std::chrono::duration<double, std::milli> delta = now - i->second->submitted; std::chrono::duration<double, std::milli> delta = now - request->second.submitted;
if(delta > 6000000ms) { if(delta > 10min) {
MyLogger.debug(fmt::format("{}: Timed out.", i->second->uuid)); MyLogger.debug(fmt::format("{}: Command={} for {} Timed out.",
OutstandingUUIDs_.erase(i->second->uuid); request->second.UUID,
i = OutStandingRequests_.erase(i); request->second.Command,
Utils::IntToSerialNumber(request->second.SerialNumber)));
request = OutStandingRequests_.erase(request);
} else { } else {
++i; ++request;
} }
} }
MyLogger.information( poco_information(MyLogger,
fmt::format("Removing expired commands: start. {} outstanding-requests {} outstanding-uuids commands.", fmt::format("Outstanding-requests {}", OutStandingRequests_.size()));
OutStandingRequests_.size(), OutstandingUUIDs_.size() )); }
bool CommandManager::IsCommandRunning(const std::string &C) {
std::shared_lock Lock(LocalMutex_);
for (const auto &request : OutStandingRequests_) {
if (request.second.UUID == C) {
return true;
}
}
return false;
} }
void CommandManager::onCommandRunnerTimer([[maybe_unused]] Poco::Timer &timer) { void CommandManager::onCommandRunnerTimer([[maybe_unused]] Poco::Timer &timer) {
Utils::SetThreadName("cmd:schdlr"); Utils::SetThreadName("cmd:schdlr");
Poco::Logger & MyLogger = Poco::Logger::get("CMD-MGR-SCHEDULER"); Poco::Logger &MyLogger = Poco::Logger::get("CMD-MGR-SCHEDULER");
std::vector<GWObjects::CommandDetails> Commands; poco_trace(MyLogger,"Scheduler starting.");
if(StorageService()->GetReadyToExecuteCommands(0,200,Commands))
{ try {
for(auto & Cmd: Commands)
{ StorageService()->RemovedExpiredCommands();
if(!Running_) StorageService()->RemoveTimedOutCommands();
break;
try { std::vector<GWObjects::CommandDetails> Commands;
{ if (StorageService()->GetReadyToExecuteCommands(0, 200, Commands)) {
std::lock_guard M(Mutex_); poco_trace(MyLogger,fmt::format("Scheduler about to process {} commands.", Commands.size()));
if(OutstandingUUIDs_.find(Cmd.UUID)!=OutstandingUUIDs_.end()) for (auto &Cmd : Commands) {
if (!Running_) {
poco_warning(MyLogger,"Scheduler quitting because service is stopping.");
break;
}
poco_trace(
MyLogger, fmt::format("{}: Serial={} Command={} Starting processing.",
Cmd.UUID, Cmd.SerialNumber, Cmd.Command));
try {
// Skip an already running command
if(IsCommandRunning(Cmd.UUID))
continue; continue;
}
Poco::JSON::Parser P; auto now = OpenWifi::Now();
bool Sent; // 2 hour timeout for commands
MyLogger.information(fmt::format("{}: Preparing execution of {} for {}.", Cmd.UUID, Cmd.Command, Cmd.SerialNumber)); if ((now - Cmd.Submitted) > (1 * 60 * 60)) {
auto Params = P.parse(Cmd.Details).extract<Poco::JSON::Object::Ptr>(); poco_information(
auto Result = PostCommandDisk( NextRPCId(), MyLogger, fmt::format("{}: Serial={} Command={} has expired.",
Cmd.SerialNumber, Cmd.UUID, Cmd.SerialNumber, Cmd.Command));
Cmd.Command, StorageService()->SetCommandTimedOut(Cmd.UUID);
*Params, continue;
Cmd.UUID, }
Sent);
if(Sent) { if (!DeviceRegistry()->Connected(
Utils::SerialNumberToInt(Cmd.SerialNumber))) {
poco_trace(
MyLogger,
fmt::format(
"{}: Serial={} Command={} Device is not connected.",
Cmd.UUID, Cmd.SerialNumber, Cmd.Command));
continue;
}
std::string ExecutingCommand, ExecutingUUID;
if (CommandRunningForDevice(Utils::SerialNumberToInt(Cmd.SerialNumber),
ExecutingUUID, ExecutingCommand)) {
poco_trace(
MyLogger,
fmt::format(
"{}: Serial={} Command={} Device is already busy with command {} (Command={})."
, Cmd.UUID, Cmd.SerialNumber, Cmd.Command,ExecutingUUID, ExecutingCommand));
continue;
}
Poco::JSON::Parser P;
bool Sent;
poco_information(MyLogger, fmt::format("{}: Serial={} Command={} Preparing execution.",
Cmd.UUID, Cmd.SerialNumber, Cmd.Command));
auto Params = P.parse(Cmd.Details).extract<Poco::JSON::Object::Ptr>();
auto Result = PostCommandDisk(NextRPCId(), Cmd.SerialNumber, Cmd.Command,
*Params, Cmd.UUID, Sent);
if (Sent) {
StorageService()->SetCommandExecuted(Cmd.UUID);
poco_debug(MyLogger,
fmt::format("{}: Serial={} Command={} Sent.",
Cmd.UUID, Cmd.SerialNumber, Cmd.Command));
} else {
poco_debug(MyLogger,
fmt::format("{}: Serial={} Command={} Re-queued command.",
Cmd.UUID, Cmd.SerialNumber, Cmd.Command));
}
} catch (const Poco::Exception &E) {
poco_debug(MyLogger,
fmt::format("{}: Serial={} Command={} Failed. Command marked as completed.",
Cmd.UUID, Cmd.SerialNumber, Cmd.Command));
MyLogger.log(E);
StorageService()->SetCommandExecuted(Cmd.UUID);
} catch (...) {
poco_debug(MyLogger,
fmt::format("{}: Serial={} Command={} Hard failure. Command marked as completed.",
Cmd.UUID, Cmd.SerialNumber, Cmd.Command));
StorageService()->SetCommandExecuted(Cmd.UUID); StorageService()->SetCommandExecuted(Cmd.UUID);
std::lock_guard M(Mutex_);
OutstandingUUIDs_.insert(Cmd.UUID);
MyLogger.information(fmt::format("{}: Queued command.", Cmd.UUID));
} else {
MyLogger.information(fmt::format("{}: Could queue command.", Cmd.UUID));
} }
} catch (const Poco::Exception &E) {
MyLogger.information(fmt::format("{}: Failed. Command marked as completed.", Cmd.UUID));
MyLogger.log(E);
StorageService()->SetCommandExecuted(Cmd.UUID);
} catch (...) {
MyLogger.information(fmt::format("{}: Hard failure.", Cmd.UUID));
StorageService()->SetCommandExecuted(Cmd.UUID);
} }
} }
} catch (Poco::Exception &E) {
MyLogger.log(E);
} catch (...) {
poco_warning(MyLogger,"Exception during command processing.");
} }
poco_trace(MyLogger,"Scheduler done.");
} }
std::shared_ptr<CommandManager::promise_type_t> CommandManager::PostCommand( std::shared_ptr<CommandManager::promise_type_t> CommandManager::PostCommand(
uint64_t RPCID, uint64_t RPCID,
const std::string &SerialNumber, const std::string &SerialNumber,
const std::string &Method, const std::string &Command,
const Poco::JSON::Object &Params, const Poco::JSON::Object &Params,
const std::string &UUID, const std::string &UUID,
bool oneway_rpc, bool oneway_rpc,
bool disk_only, bool disk_only,
bool & Sent) { bool & Sent) {
auto SerialNumberInt = Utils::SerialNumberToInt(SerialNumber);
Sent=false; Sent=false;
if(!DeviceRegistry()->Connected(SerialNumber)) {
return nullptr;
}
std::stringstream ToSend; std::stringstream ToSend;
auto Object = std::make_shared<RpcObject>();
CommandTagIndex Idx; CommandInfo Idx;
{ Idx.Id = oneway_rpc ? 1 : RPCID;
std::lock_guard M(Mutex_); Idx.SerialNumber = SerialNumberInt;
if (oneway_rpc) Idx.Command = Command;
Idx.Id = 1; Idx.UUID = UUID;
else
Idx.Id = RPCID;
Idx.SerialNumber = SerialNumber;
Poco::JSON::Object CompleteRPC; Poco::JSON::Object CompleteRPC;
CompleteRPC.set(uCentralProtocol::JSONRPC, uCentralProtocol::JSONRPC_VERSION); CompleteRPC.set(uCentralProtocol::JSONRPC, uCentralProtocol::JSONRPC_VERSION);
CompleteRPC.set(uCentralProtocol::ID, RPCID); CompleteRPC.set(uCentralProtocol::ID, RPCID);
CompleteRPC.set(uCentralProtocol::METHOD, Method); CompleteRPC.set(uCentralProtocol::METHOD, Command);
CompleteRPC.set(uCentralProtocol::PARAMS, Params); CompleteRPC.set(uCentralProtocol::PARAMS, Params);
Poco::JSON::Stringifier::stringify(CompleteRPC, ToSend); Poco::JSON::Stringifier::stringify(CompleteRPC, ToSend);
Object->submitted = std::chrono::high_resolution_clock::now(); Idx.rpc_entry = disk_only ? nullptr : std::make_shared<CommandManager::promise_type_t>();
Object->uuid = UUID;
if(disk_only) {
Object->rpc_entry = nullptr;
} else {
Object->rpc_entry = std::make_shared<CommandManager::promise_type_t>();
}
if(!oneway_rpc) {
OutStandingRequests_[Idx] = Object;
OutstandingUUIDs_.insert(UUID);
}
}
Logger().information(fmt::format("{}: Sending command. ID: {}", UUID, RPCID)); poco_debug(Logger(), fmt::format("{}: Sending command. ID: {}", UUID, RPCID));
if(DeviceRegistry()->SendFrame(SerialNumber, ToSend.str())) { if(DeviceRegistry()->SendFrame(SerialNumber, ToSend.str())) {
Logger().information(fmt::format("{}: Sent command. ID: {}", UUID, RPCID)); if(!oneway_rpc) {
std::lock_guard M(Mutex_);
OutStandingRequests_[RPCID] = Idx;
}
poco_debug(Logger(), fmt::format("{}: Sent command. ID: {}", UUID, RPCID));
Sent=true; Sent=true;
return Object->rpc_entry; return Idx.rpc_entry;
} }
Logger().information(fmt::format("{}: Failed to send command. ID: {}", UUID, RPCID));
poco_warning(Logger(), fmt::format("{}: Failed to send command. ID: {}", UUID, RPCID));
return nullptr; return nullptr;
} }
} // namespace } // namespace

View File

@@ -13,6 +13,9 @@
#include <map> #include <map>
#include <utility> #include <utility>
#include <functional> #include <functional>
#include <shared_mutex>
#include "framework/MicroService.h"
#include "Poco/JSON/Object.h" #include "Poco/JSON/Object.h"
#include "Poco/Net/HTTPServerRequest.h" #include "Poco/Net/HTTPServerRequest.h"
@@ -20,29 +23,9 @@
#include "Poco/Timer.h" #include "Poco/Timer.h"
#include "RESTObjects/RESTAPI_GWobjects.h" #include "RESTObjects/RESTAPI_GWobjects.h"
#include "framework/MicroService.h"
namespace OpenWifi { namespace OpenWifi {
struct CommandTagIndex {
uint64_t Id=0;
std::string SerialNumber;
};
inline bool operator <(const CommandTagIndex& lhs, const CommandTagIndex& rhs) {
if(lhs.Id<rhs.Id)
return true;
if(lhs.Id>rhs.Id)
return false;
return lhs.SerialNumber<rhs.SerialNumber;
}
inline bool operator ==(const CommandTagIndex& lhs, const CommandTagIndex& rhs) {
if(lhs.Id == rhs.Id && lhs.SerialNumber == rhs.SerialNumber)
return true;
return false;
}
class RPCResponseNotification: public Poco::Notification { class RPCResponseNotification: public Poco::Notification {
public: public:
RPCResponseNotification(const std::string &ser, RPCResponseNotification(const std::string &ser,
@@ -61,8 +44,12 @@ namespace OpenWifi {
public: public:
typedef Poco::JSON::Object objtype_t; typedef Poco::JSON::Object objtype_t;
typedef std::promise<objtype_t> promise_type_t; typedef std::promise<objtype_t> promise_type_t;
struct RpcObject {
std::string uuid; struct CommandInfo {
std::uint64_t Id=0;
std::uint64_t SerialNumber=0;
std::string Command;
std::string UUID;
std::chrono::time_point<std::chrono::high_resolution_clock> submitted = std::chrono::high_resolution_clock::now(); std::chrono::time_point<std::chrono::high_resolution_clock> submitted = std::chrono::high_resolution_clock::now();
std::shared_ptr<promise_type_t> rpc_entry; std::shared_ptr<promise_type_t> rpc_entry;
}; };
@@ -82,7 +69,6 @@ namespace OpenWifi {
void Stop() override; void Stop() override;
void WakeUp(); void WakeUp();
inline void PostCommandResult(const std::string &SerialNumber, const Poco::JSON::Object &Obj) { inline void PostCommandResult(const std::string &SerialNumber, const Poco::JSON::Object &Obj) {
std::lock_guard G(Mutex_);
// RPCResponseQueue_->Write(RPCResponse{.serialNumber=SerialNumber, .payload = Obj}); // RPCResponseQueue_->Write(RPCResponse{.serialNumber=SerialNumber, .payload = Obj});
ResponseQueue_.enqueueNotification(new RPCResponseNotification(SerialNumber,Obj)); ResponseQueue_.enqueueNotification(new RPCResponseNotification(SerialNumber,Obj));
} }
@@ -146,6 +132,8 @@ namespace OpenWifi {
false, Sent ); false, Sent );
} }
bool IsCommandRunning(const std::string &C);
void run() override; void run() override;
static auto instance() { static auto instance() {
@@ -159,12 +147,40 @@ namespace OpenWifi {
void onRPCAnswer(bool& b); void onRPCAnswer(bool& b);
inline uint64_t NextRPCId() { return ++Id_; } inline uint64_t NextRPCId() { return ++Id_; }
void RemovePendingCommand(std::uint64_t Id) {
std::unique_lock Lock(LocalMutex_);
OutStandingRequests_.erase(Id);
}
inline bool CommandRunningForDevice(std::uint64_t SerialNumber, std::string & uuid, std::string &command) {
std::shared_lock Lock(LocalMutex_);
for(const auto &[Request,Command]:OutStandingRequests_) {
if(Command.SerialNumber==SerialNumber) {
uuid = Command.UUID;
command = Command.Command;
return true;
}
}
return false;
}
inline void ClearQueue(std::uint64_t SerialNumber) {
std::unique_lock Lock(LocalMutex_);
for(auto Request = OutStandingRequests_.begin(); Request != OutStandingRequests_.end() ; ) {
if(Request->second.SerialNumber==SerialNumber)
Request = OutStandingRequests_.erase(Request);
else
++Request;
}
}
private: private:
mutable std::shared_mutex LocalMutex_;
std::atomic_bool Running_ = false; std::atomic_bool Running_ = false;
Poco::Thread ManagerThread; Poco::Thread ManagerThread;
std::atomic_uint64_t Id_=3; // do not start @1. We ignore ID=1 & 0 is illegal.. std::atomic_uint64_t Id_=3; // do not start @1. We ignore ID=1 & 0 is illegal..
std::map<CommandTagIndex,std::shared_ptr<RpcObject>> OutStandingRequests_; std::map<std::uint64_t , CommandInfo> OutStandingRequests_;
std::set<std::string> OutstandingUUIDs_;
Poco::Timer JanitorTimer_; Poco::Timer JanitorTimer_;
std::unique_ptr<Poco::TimerCallback<CommandManager>> JanitorCallback_; std::unique_ptr<Poco::TimerCallback<CommandManager>> JanitorCallback_;
Poco::Timer CommandRunnerTimer_; Poco::Timer CommandRunnerTimer_;

View File

@@ -6,11 +6,14 @@
// Arilia Wireless Inc. // Arilia Wireless Inc.
// //
#include "framework/MicroService.h"
#include "Poco/Util/Application.h" #include "Poco/Util/Application.h"
#include "Poco/Util/Option.h" #include "Poco/Util/Option.h"
#include "Poco/Environment.h" #include "Poco/Environment.h"
#include "Poco/Net/SSLManager.h" #include "Poco/Net/SSLManager.h"
#include "AP_WS_Server.h" #include "AP_WS_Server.h"
#include "CommandManager.h" #include "CommandManager.h"
#include "Daemon.h" #include "Daemon.h"
@@ -25,7 +28,6 @@
#include "TelemetryStream.h" #include "TelemetryStream.h"
#include "VenueBroadcaster.h" #include "VenueBroadcaster.h"
#include "framework/ConfigurationValidator.h" #include "framework/ConfigurationValidator.h"
#include "framework/MicroService.h"
#include "rttys/RTTYS_server.h" #include "rttys/RTTYS_server.h"
namespace OpenWifi { namespace OpenWifi {
@@ -48,9 +50,9 @@ namespace OpenWifi {
StorageArchiver(), StorageArchiver(),
TelemetryStream(), TelemetryStream(),
RTTYS_server(), RTTYS_server(),
AP_WS_Server(),
RADIUS_proxy_server(), RADIUS_proxy_server(),
VenueBroadcaster() VenueBroadcaster(),
AP_WS_Server()
}); });
return &instance; return &instance;
} }
@@ -106,15 +108,25 @@ namespace OpenWifi {
} }
int main(int argc, char **argv) { int main(int argc, char **argv) {
int ExitCode;
try { try {
Poco::Net::SSLManager::instance().initializeServer(nullptr, nullptr, nullptr);
auto App = OpenWifi::Daemon::instance(); auto App = OpenWifi::Daemon::instance();
auto ExitCode = App->run(argc, argv); ExitCode = App->run(argc, argv);
Poco::Net::SSLManager::instance().shutdown(); Poco::Net::SSLManager::instance().shutdown();
return ExitCode;
} catch (Poco::Exception &exc) { } catch (Poco::Exception &exc) {
std::cerr << exc.displayText() << std::endl; ExitCode = Poco::Util::Application::EXIT_SOFTWARE;
return Poco::Util::Application::EXIT_SOFTWARE; std::cout << exc.displayText() << std::endl;
} catch (std::exception &exc) {
ExitCode = Poco::Util::Application::EXIT_TEMPFAIL;
std::cout << exc.what() << std::endl;
} catch (...) {
ExitCode = Poco::Util::Application::EXIT_TEMPFAIL;
std::cout << "Exception on closure" << std::endl;
} }
std::cout << "Exitcode: " << ExitCode << std::endl;
return ExitCode;
} }
// end of namespace // end of namespace

View File

@@ -14,6 +14,8 @@
#include <vector> #include <vector>
#include <set> #include <set>
#include "framework/MicroService.h"
#include "Poco/Util/Application.h" #include "Poco/Util/Application.h"
#include "Poco/Util/ServerApplication.h" #include "Poco/Util/ServerApplication.h"
#include "Poco/Util/Option.h" #include "Poco/Util/Option.h"
@@ -25,7 +27,6 @@
#include "Poco/Crypto/Cipher.h" #include "Poco/Crypto/Cipher.h"
#include "Dashboard.h" #include "Dashboard.h"
#include "framework/MicroService.h"
#include "framework/OpenWifiTypes.h" #include "framework/OpenWifiTypes.h"
#include "GwWebSocketClient.h" #include "GwWebSocketClient.h"

View File

@@ -9,137 +9,190 @@
#include "Poco/JSON/Object.h" #include "Poco/JSON/Object.h"
#include "AP_WS_Server.h" #include "AP_WS_Server.h"
#include "DeviceRegistry.h" #include "DeviceRegistry.h"
#include "CommandManager.h"
#include "framework/WebSocketClientNotifications.h"
namespace OpenWifi { namespace OpenWifi {
int DeviceRegistry::Start() { int DeviceRegistry::Start() {
std::lock_guard Guard(Mutex_); std::lock_guard Guard(Mutex_);
Logger().notice("Starting "); poco_notice(Logger(),"Starting");
return 0;
ArchiverCallback_ = std::make_unique<Poco::TimerCallback<DeviceRegistry>>(*this,&DeviceRegistry::onConnectionJanitor);
Timer_.setStartInterval(60 * 1000);
Timer_.setPeriodicInterval(20 * 1000); // every minute
Timer_.start(*ArchiverCallback_, MicroService::instance().TimerPool());
return 0;
} }
void DeviceRegistry::Stop() { void DeviceRegistry::Stop() {
poco_notice(Logger(),"Stopping...");
std::lock_guard Guard(Mutex_); std::lock_guard Guard(Mutex_);
Logger().notice("Stopping..."); Timer_.stop();
poco_notice(Logger(),"Stopped...");
} }
bool DeviceRegistry::GetStatistics(uint64_t SerialNumber, std::string & Statistics) { void DeviceRegistry::onConnectionJanitor([[maybe_unused]] Poco::Timer &timer) {
std::shared_lock Guard(M_);
static std::uint64_t last_log = OpenWifi::Now();
std::shared_lock Guard(LocalMutex_);
NumberOfConnectedDevices_ = 0;
NumberOfConnectingDevices_ = 0;
AverageDeviceConnectionTime_ = 0;
std::uint64_t total_connected_time=0;
auto now = OpenWifi::Now();
for (auto connection=SerialNumbers_.begin(); connection!=SerialNumbers_.end();) {
if(connection->second.second== nullptr) {
connection++;
continue;
}
if (connection->second.second->State_.Connected) {
NumberOfConnectedDevices_++;
total_connected_time += (now - connection->second.second->State_.started);
connection++;
} else {
NumberOfConnectingDevices_++;
connection++;
}
}
AverageDeviceConnectionTime_ = (NumberOfConnectedDevices_!=0) ? total_connected_time/NumberOfConnectedDevices_ : 0;
if((now-last_log)>120) {
last_log = now;
poco_information(Logger(),
fmt::format("Active AP connections: {} Connecting: {} Average connection time: {} seconds",
NumberOfConnectedDevices_, NumberOfConnectingDevices_, AverageDeviceConnectionTime_));
}
WebSocketClientNotificationNumberOfConnections(NumberOfConnectedDevices_,
AverageDeviceConnectionTime_,
NumberOfConnectingDevices_);
}
bool DeviceRegistry::GetStatistics(uint64_t SerialNumber, std::string & Statistics) const {
std::shared_lock Guard(LocalMutex_);
auto Device = SerialNumbers_.find(SerialNumber); auto Device = SerialNumbers_.find(SerialNumber);
if(Device == SerialNumbers_.end()) if(Device == SerialNumbers_.end() || Device->second.second==nullptr)
return false; return false;
Statistics = Device->second.first->LastStats; Statistics = Device->second.second->LastStats_;
return true; return true;
} }
void DeviceRegistry::SetStatistics(uint64_t SerialNumber, const std::string &Statistics) { bool DeviceRegistry::GetState(uint64_t SerialNumber, GWObjects::ConnectionState & State) const {
std::unique_lock Guard(M_); std::shared_lock Guard(LocalMutex_);
auto Device = SerialNumbers_.find(SerialNumber); auto Device = SerialNumbers_.find(SerialNumber);
if(Device == SerialNumbers_.end()) if(Device == SerialNumbers_.end() || Device->second.second==nullptr)
return;
Device->second.first->State_.LastContact = time(nullptr);
Device->second.first->LastStats = Statistics;
}
bool DeviceRegistry::GetState(uint64_t SerialNumber, GWObjects::ConnectionState & State) {
std::unique_lock Guard(M_);
auto Device = SerialNumbers_.find(SerialNumber);
if(Device == SerialNumbers_.end())
return false; return false;
State = Device->second.second->State_;
State = Device->second.first->State_;
return true; return true;
} }
void DeviceRegistry::SetState(uint64_t SerialNumber, const GWObjects::ConnectionState & State) { bool DeviceRegistry::GetHealthcheck(uint64_t SerialNumber, GWObjects::HealthCheck & CheckData) const {
std::unique_lock Guard(M_); std::shared_lock Guard(LocalMutex_);
auto Device = SerialNumbers_.find(SerialNumber);
if(Device == SerialNumbers_.end())
return;
Device->second.first->State_.LastContact = time(nullptr);
Device->second.first->State_ = State;
}
bool DeviceRegistry::GetHealthcheck(uint64_t SerialNumber, GWObjects::HealthCheck & CheckData) {
std::shared_lock Guard(M_);
auto Device = SerialNumbers_.find(SerialNumber); auto Device = SerialNumbers_.find(SerialNumber);
if(Device == SerialNumbers_.end()) if(Device == SerialNumbers_.end() || Device->second.second==nullptr)
return false; return false;
CheckData = Device->second.first->LastHealthcheck; CheckData = Device->second.second->LastHealthcheck_;
return true; return true;
} }
void DeviceRegistry::SetHealthcheck(uint64_t SerialNumber, const GWObjects::HealthCheck & CheckData) { bool DeviceRegistry::EndSession(std::uint64_t connection_id, std::uint64_t serial_number) {
std::unique_lock Guard(M_); std::unique_lock G(LocalMutex_);
auto Device = SerialNumbers_.find(SerialNumber); auto Connection = SerialNumbers_.find(serial_number);
if(Device == SerialNumbers_.end()) if(Connection==end(SerialNumbers_)) {
return false;
}
if(Connection->second.first!=connection_id) {
return false;
}
SerialNumbers_.erase(Connection);
return true;
}
void DeviceRegistry::SetSessionDetails(std::uint64_t connection_id, uint64_t SerialNumber) {
auto Connection = AP_WS_Server()->FindConnection(connection_id);
if(Connection== nullptr)
return; return;
Device->second.first->LastHealthcheck = CheckData; std::unique_lock G(LocalMutex_);
auto CurrentSerialNumber = SerialNumbers_.find(SerialNumber);
if( (CurrentSerialNumber==SerialNumbers_.end()) ||
(CurrentSerialNumber->second.first<connection_id)) {
SerialNumbers_[SerialNumber] = std::make_pair(connection_id, Connection);
return;
}
} }
bool DeviceRegistry::Connected(uint64_t SerialNumber) { bool DeviceRegistry::Connected(uint64_t SerialNumber) const {
std::shared_lock Guard(M_); std::shared_lock Guard(LocalMutex_);
return SerialNumbers_.find(SerialNumber) != SerialNumbers_.end();
}
bool DeviceRegistry::SendFrame(uint64_t SerialNumber, const std::string & Payload) {
std::shared_lock Guard(M_);
auto Device = SerialNumbers_.find(SerialNumber); auto Device = SerialNumbers_.find(SerialNumber);
if(Device==SerialNumbers_.end()) if(Device==end(SerialNumbers_) || Device->second.second== nullptr)
return false;
return Device->second.second->State_.Connected;
}
bool DeviceRegistry::SendFrame(uint64_t SerialNumber, const std::string & Payload) const {
std::shared_lock Guard(LocalMutex_);
auto Device = SerialNumbers_.find(SerialNumber);
if(Device==SerialNumbers_.end() || Device->second.second== nullptr)
return false; return false;
try { try {
// std::cout << "Device connection pointer: " << (std::uint64_t) Device->second.second << std::endl;
return Device->second.second->Send(Payload); return Device->second.second->Send(Payload);
} catch (...) { } catch (...) {
Logger().debug(fmt::format("Could not send data to device '{}'", SerialNumber)); poco_debug(Logger(),fmt::format(": SendFrame: Could not send data to device '{}'", Utils::IntToSerialNumber(SerialNumber)));
Device->second.first->State_.Address = "";
Device->second.first->State_.Connected = false;
Device->second.first->State_.VerifiedCertificate = GWObjects::NO_CERTIFICATE;
} }
return false; return false;
} }
void DeviceRegistry::StopWebSocketTelemetry(uint64_t SerialNumber) { void DeviceRegistry::StopWebSocketTelemetry(std::uint64_t RPCID, uint64_t SerialNumber) {
std::shared_lock Guard(M_); std::shared_lock Guard(LocalMutex_);
auto Device = SerialNumbers_.find(SerialNumber); auto Device = SerialNumbers_.find(SerialNumber);
if(Device==end(SerialNumbers_)) if(Device==end(SerialNumbers_) || Device->second.second==nullptr)
return; return;
Device->second.second->StopWebSocketTelemetry(); Device->second.second->StopWebSocketTelemetry(RPCID);
} }
void DeviceRegistry::SetWebSocketTelemetryReporting(uint64_t SerialNumber, uint64_t Interval, uint64_t Lifetime) { void DeviceRegistry::SetWebSocketTelemetryReporting(std::uint64_t RPCID, uint64_t SerialNumber, uint64_t Interval, uint64_t Lifetime) {
std::shared_lock Guard(M_); std::shared_lock Guard(LocalMutex_);
auto Device = SerialNumbers_.find(SerialNumber); auto Device = SerialNumbers_.find(SerialNumber);
if(Device==end(SerialNumbers_)) if(Device==end(SerialNumbers_) || Device->second.second==nullptr)
return; return;
Device->second.second->SetWebSocketTelemetryReporting(Interval, Lifetime); Device->second.second->SetWebSocketTelemetryReporting(RPCID, Interval, Lifetime);
} }
void DeviceRegistry::SetKafkaTelemetryReporting(uint64_t SerialNumber, uint64_t Interval, uint64_t Lifetime) { void DeviceRegistry::SetKafkaTelemetryReporting(std::uint64_t RPCID, uint64_t SerialNumber, uint64_t Interval, uint64_t Lifetime) {
std::shared_lock Guard(M_); std::shared_lock Guard(LocalMutex_);
auto Device = SerialNumbers_.find(SerialNumber); auto Device = SerialNumbers_.find(SerialNumber);
if(Device==end(SerialNumbers_)) if(Device==end(SerialNumbers_) || Device->second.second== nullptr)
return; return;
Device->second.second->SetKafkaTelemetryReporting(Interval, Lifetime); Device->second.second->SetKafkaTelemetryReporting(RPCID, Interval, Lifetime);
} }
void DeviceRegistry::StopKafkaTelemetry(uint64_t SerialNumber) { void DeviceRegistry::StopKafkaTelemetry(std::uint64_t RPCID, uint64_t SerialNumber) {
std::shared_lock Guard(M_); std::shared_lock Guard(LocalMutex_);
auto Device = SerialNumbers_.find(SerialNumber); auto Device = SerialNumbers_.find(SerialNumber);
if(Device==end(SerialNumbers_)) if(Device==end(SerialNumbers_) || Device->second.second== nullptr)
return; return;
Device->second.second->StopKafkaTelemetry(); Device->second.second->StopKafkaTelemetry(RPCID);
} }
void DeviceRegistry::GetTelemetryParameters(uint64_t SerialNumber , bool & TelemetryRunning, void DeviceRegistry::GetTelemetryParameters(uint64_t SerialNumber , bool & TelemetryRunning,
@@ -150,10 +203,10 @@ namespace OpenWifi {
uint64_t & TelemetryKafkaCount, uint64_t & TelemetryKafkaCount,
uint64_t & TelemetryWebSocketPackets, uint64_t & TelemetryWebSocketPackets,
uint64_t & TelemetryKafkaPackets) { uint64_t & TelemetryKafkaPackets) {
std::shared_lock Guard(M_); std::shared_lock Guard(LocalMutex_);
auto Device = SerialNumbers_.find(SerialNumber); auto Device = SerialNumbers_.find(SerialNumber);
if(Device==end(SerialNumbers_)) if(Device==end(SerialNumbers_)|| Device->second.second== nullptr)
return; return;
Device->second.second->GetTelemetryParameters(TelemetryRunning, Device->second.second->GetTelemetryParameters(TelemetryRunning,
TelemetryInterval, TelemetryInterval,
@@ -165,79 +218,46 @@ namespace OpenWifi {
TelemetryKafkaPackets); TelemetryKafkaPackets);
} }
bool DeviceRegistry::SendRadiusAccountingData(const std::string & SerialNumber, const unsigned char * buffer, std::size_t size) { bool DeviceRegistry::SendRadiusAccountingData(const std::string & SerialNumber, const unsigned char * buffer, std::size_t size) {
std::shared_lock Guard(M_); std::shared_lock Guard(LocalMutex_);
auto Device = SerialNumbers_.find(Utils::SerialNumberToInt(SerialNumber)); auto Device = SerialNumbers_.find(Utils::SerialNumberToInt(SerialNumber));
if(Device==SerialNumbers_.end()) if(Device==SerialNumbers_.end() || Device->second.second== nullptr)
return false; return false;
try { try {
return Device->second.second->SendRadiusAccountingData(buffer,size); return Device->second.second->SendRadiusAccountingData(buffer,size);
} catch (...) { } catch (...) {
Logger().debug(fmt::format("Could not send data to device '{}'", SerialNumber)); poco_debug(Logger(),fmt::format(": SendRadiusAuthenticationData: Could not send data to device '{}'", SerialNumber));
Device->second.first->State_.Address = "";
Device->second.first->State_.Connected = false;
Device->second.first->State_.VerifiedCertificate = GWObjects::NO_CERTIFICATE;
} }
return false; return false;
} }
bool DeviceRegistry::SendRadiusAuthenticationData(const std::string & SerialNumber, const unsigned char * buffer, std::size_t size) { bool DeviceRegistry::SendRadiusAuthenticationData(const std::string & SerialNumber, const unsigned char * buffer, std::size_t size) {
std::shared_lock Guard(M_); std::shared_lock Guard(LocalMutex_);
auto Device = SerialNumbers_.find(Utils::SerialNumberToInt(SerialNumber)); auto Device = SerialNumbers_.find(Utils::SerialNumberToInt(SerialNumber));
if(Device==SerialNumbers_.end()) if(Device==SerialNumbers_.end() || Device->second.second== nullptr)
return false; return false;
try { try {
return Device->second.second->SendRadiusAuthenticationData(buffer,size); return Device->second.second->SendRadiusAuthenticationData(buffer,size);
} catch (...) { } catch (...) {
Logger().debug(fmt::format("Could not send data to device '{}'", SerialNumber)); poco_debug(Logger(),fmt::format(": SendRadiusAuthenticationData: Could not send data to device '{}'", SerialNumber));
Device->second.first->State_.Address = "";
Device->second.first->State_.Connected = false;
Device->second.first->State_.VerifiedCertificate = GWObjects::NO_CERTIFICATE;
} }
return false; return false;
} }
bool DeviceRegistry::SendRadiusCoAData(const std::string & SerialNumber, const unsigned char * buffer, std::size_t size) { bool DeviceRegistry::SendRadiusCoAData(const std::string & SerialNumber, const unsigned char * buffer, std::size_t size) {
std::shared_lock Guard(M_); std::shared_lock Guard(LocalMutex_);
auto Device = SerialNumbers_.find(Utils::SerialNumberToInt(SerialNumber)); auto Device = SerialNumbers_.find(Utils::SerialNumberToInt(SerialNumber));
if(Device==SerialNumbers_.end()) if(Device==SerialNumbers_.end() || Device->second.second== nullptr)
return false; return false;
try { try {
return Device->second.second->SendRadiusCoAData(buffer,size); return Device->second.second->SendRadiusCoAData(buffer,size);
} catch (...) { } catch (...) {
Logger().debug(fmt::format("Could not send data to device '{}'", SerialNumber)); poco_debug(Logger(),fmt::format(": SendRadiusCoAData: Could not send data to device '{}'", SerialNumber));
Device->second.first->State_.Address = "";
Device->second.first->State_.Connected = false;
Device->second.first->State_.VerifiedCertificate = GWObjects::NO_CERTIFICATE;
} }
return false; return false;
} }
void DeviceRegistry::SetPendingUUID(uint64_t SerialNumber, uint64_t PendingUUID) {
std::unique_lock Guard(M_);
auto Device = SerialNumbers_.find(SerialNumber);
if(Device==SerialNumbers_.end())
return;
Device->second.first->State_.PendingUUID = PendingUUID;
}
} // namespace } // namespace

View File

@@ -10,22 +10,21 @@
#include <shared_mutex> #include <shared_mutex>
#include "Poco/JSON/Object.h"
#include "RESTObjects//RESTAPI_GWobjects.h"
#include "framework/MicroService.h" #include "framework/MicroService.h"
#include "Poco/JSON/Object.h"
#include "Poco/Timer.h"
#include "RESTObjects//RESTAPI_GWobjects.h"
namespace OpenWifi { namespace OpenWifi {
class AP_WS_Connection; class AP_WS_Connection;
class DeviceRegistry : public SubSystemServer { class DeviceRegistry : public SubSystemServer {
public: public:
struct RegistryConnectionEntry {
GWObjects::ConnectionState State_; DeviceRegistry() noexcept:
std::string LastStats; SubSystemServer("DeviceRegistry", "DevStatus", "devicestatus") {
GWObjects::HealthCheck LastHealthcheck; }
uint64_t ConnectionId=0;
uint64_t SerialNumber_=0;
};
static auto instance() { static auto instance() {
static auto instance_ = new DeviceRegistry; static auto instance_ = new DeviceRegistry;
@@ -35,108 +34,40 @@ namespace OpenWifi {
int Start() override; int Start() override;
void Stop() override; void Stop() override;
inline bool GetStatistics(const std::string &SerialNumber, std::string & Statistics) { inline bool GetStatistics(const std::string &SerialNumber, std::string & Statistics) const {
return GetStatistics(Utils::SerialNumberToInt(SerialNumber),Statistics); return GetStatistics(Utils::SerialNumberToInt(SerialNumber),Statistics);
} }
bool GetStatistics(uint64_t SerialNumber, std::string & Statistics); bool GetStatistics(std::uint64_t SerialNumber, std::string & Statistics) const;
inline void SetStatistics(const std::string &SerialNumber, const std::string &Statistics) { inline bool GetState(const std::string & SerialNumber, GWObjects::ConnectionState & State) const {
return SetStatistics(Utils::SerialNumberToInt(SerialNumber),Statistics);
}
void SetStatistics(uint64_t SerialNumber, const std::string &stats);
inline bool GetState(const std::string & SerialNumber, GWObjects::ConnectionState & State) {
return GetState(Utils::SerialNumberToInt(SerialNumber), State); return GetState(Utils::SerialNumberToInt(SerialNumber), State);
} }
bool GetState(uint64_t SerialNumber, GWObjects::ConnectionState & State); bool GetState(std::uint64_t SerialNumber, GWObjects::ConnectionState & State) const;
inline void SetState(const std::string & SerialNumber, const GWObjects::ConnectionState & State) { inline bool GetHealthcheck(const std::string &SerialNumber, GWObjects::HealthCheck & CheckData) const {
return SetState(Utils::SerialNumberToInt(SerialNumber), State);
}
void SetState(uint64_t SerialNumber, const GWObjects::ConnectionState & State);
inline bool GetHealthcheck(const std::string &SerialNumber, GWObjects::HealthCheck & CheckData) {
return GetHealthcheck(Utils::SerialNumberToInt(SerialNumber), CheckData); return GetHealthcheck(Utils::SerialNumberToInt(SerialNumber), CheckData);
} }
bool GetHealthcheck(uint64_t SerialNumber, GWObjects::HealthCheck & CheckData); bool GetHealthcheck(std::uint64_t SerialNumber, GWObjects::HealthCheck & CheckData) const ;
inline void SetHealthcheck(const std::string &SerialNumber, const GWObjects::HealthCheck &H) { bool Connected(uint64_t SerialNumber) const ;
return SetHealthcheck(Utils::SerialNumberToInt(SerialNumber),H);
}
void SetHealthcheck(uint64_t SerialNumber, const GWObjects::HealthCheck &H);
inline bool Connected(const std::string & SerialNumber) { inline bool SendFrame(const std::string & SerialNumber, const std::string & Payload) const {
return Connected(Utils::SerialNumberToInt(SerialNumber));
}
bool Connected(uint64_t SerialNumber);
inline bool SendFrame(const std::string & SerialNumber, const std::string & Payload) {
return SendFrame(Utils::SerialNumberToInt(SerialNumber), Payload); return SendFrame(Utils::SerialNumberToInt(SerialNumber), Payload);
} }
bool SendFrame(uint64_t SerialNumber, const std::string & Payload); bool SendFrame(std::uint64_t SerialNumber, const std::string & Payload) const ;
inline void SetPendingUUID(const std::string & SerialNumber, uint64_t PendingUUID) {
return SetPendingUUID(Utils::SerialNumberToInt(SerialNumber), PendingUUID);
}
void SetPendingUUID(uint64_t SerialNumber, uint64_t PendingUUID);
[[nodiscard]] inline std::shared_ptr<RegistryConnectionEntry> GetDeviceConnection(const std::string & SerialNumber) {
return GetDeviceConnection(Utils::SerialNumberToInt(SerialNumber));
}
[[nodiscard]] inline std::shared_ptr<RegistryConnectionEntry> GetDeviceConnection(uint64_t SerialNumber) {
std::lock_guard Guard(Mutex_);
auto Device = SerialNumbers_.find(SerialNumber);
if(Device!=SerialNumbers_.end()) {
return Device->second.first;
}
return nullptr;
}
bool SendRadiusAuthenticationData(const std::string & SerialNumber, const unsigned char * buffer, std::size_t size); bool SendRadiusAuthenticationData(const std::string & SerialNumber, const unsigned char * buffer, std::size_t size);
bool SendRadiusAccountingData(const std::string & SerialNumber, const unsigned char * buffer, std::size_t size); bool SendRadiusAccountingData(const std::string & SerialNumber, const unsigned char * buffer, std::size_t size);
bool SendRadiusCoAData(const std::string & SerialNumber, const unsigned char * buffer, std::size_t size); bool SendRadiusCoAData(const std::string & SerialNumber, const unsigned char * buffer, std::size_t size);
[[nodiscard]] inline std::shared_ptr<RegistryConnectionEntry> StartSession( AP_WS_Connection * connection ) { void SetSessionDetails(std::uint64_t connection_id, uint64_t SerialNumber);
std::unique_lock G(M_); bool EndSession(std::uint64_t connection_id, std::uint64_t serial_number);
auto NewSession = std::make_shared<RegistryConnectionEntry>();
Sessions_[connection] = NewSession;
return NewSession;
}
inline void SetSessionDetails(AP_WS_Connection * connection, uint64_t SerialNumber, uint64_t & ConnectionId ) { void SetWebSocketTelemetryReporting(std::uint64_t RPCID, uint64_t SerialNumber, uint64_t Interval, uint64_t Lifetime);
std::unique_lock G(M_); void StopWebSocketTelemetry(std::uint64_t RPCID, uint64_t SerialNumber);
auto Hint = Sessions_.find(connection); void SetKafkaTelemetryReporting(std::uint64_t RPCID, uint64_t SerialNumber, uint64_t Interval, uint64_t Lifetime);
if(Hint!=Sessions_.end()) { void StopKafkaTelemetry(std::uint64_t RPCID, uint64_t SerialNumber);
Hint->second->SerialNumber_ = SerialNumber;
ConnectionId = Hint->second->ConnectionId = Id_++;
Hint->second->State_.Connected = true;
Hint->second->State_.LastContact = OpenWifi::Now();
Hint->second->State_.VerifiedCertificate = GWObjects::CertificateValidation::NO_CERTIFICATE;
SerialNumbers_[SerialNumber]= std::make_pair(Hint->second,connection);
}
}
inline void EndSession(AP_WS_Connection * connection) {
std::unique_lock G(M_);
auto Session = Sessions_.find(connection);
if(Session==Sessions_.end()) {
return;
}
if(Session->second->SerialNumber_) {
SerialNumbers_.erase(Session->second->SerialNumber_);
}
Sessions_.erase(Session);
}
void SetWebSocketTelemetryReporting(uint64_t SerialNumber, uint64_t Interval, uint64_t Lifetime);
void StopWebSocketTelemetry(uint64_t SerialNumber);
void SetKafkaTelemetryReporting(uint64_t SerialNumber, uint64_t Interval, uint64_t Lifetime);
void StopKafkaTelemetry(uint64_t SerialNumber);
void GetTelemetryParameters(uint64_t SerialNumber , bool & TelemetryRunning, void GetTelemetryParameters(uint64_t SerialNumber , bool & TelemetryRunning,
uint64_t & TelemetryInterval, uint64_t & TelemetryInterval,
uint64_t & TelemetryWebSocketTimer, uint64_t & TelemetryWebSocketTimer,
@@ -146,15 +77,25 @@ namespace OpenWifi {
uint64_t & TelemetryWebSocketPackets, uint64_t & TelemetryWebSocketPackets,
uint64_t & TelemetryKafkaPackets); uint64_t & TelemetryKafkaPackets);
private: void onConnectionJanitor(Poco::Timer & timer);
std::shared_mutex M_;
inline static std::atomic_uint64_t Id_=1;
std::map<AP_WS_Connection * ,std::shared_ptr<RegistryConnectionEntry>> Sessions_;
std::map<uint64_t, std::pair<std::shared_ptr<RegistryConnectionEntry>,AP_WS_Connection *>> SerialNumbers_;
DeviceRegistry() noexcept: inline void AverageDeviceStatistics( std::uint64_t & Connections, std::uint64_t & AverageConnectionTime, std::uint64_t & NumberOfConnectingDevices) const {
SubSystemServer("DeviceRegistry", "DevStatus", "devicestatus") { Connections = NumberOfConnectedDevices_;
AverageConnectionTime = AverageDeviceConnectionTime_;
NumberOfConnectingDevices = NumberOfConnectingDevices_;
} }
private:
mutable std::shared_mutex LocalMutex_;
std::map<std::uint64_t, std::pair<std::uint64_t,std::shared_ptr<AP_WS_Connection>>> SerialNumbers_;
std::unique_ptr<Poco::TimerCallback<DeviceRegistry>> ArchiverCallback_;
Poco::Timer Timer_;
Poco::Thread ConnectionJanitor_;
std::atomic_uint64_t NumberOfConnectedDevices_=0;
std::atomic_uint64_t AverageDeviceConnectionTime_=0;
std::atomic_uint64_t NumberOfConnectingDevices_=0;
}; };
inline auto DeviceRegistry() { return DeviceRegistry::instance(); } inline auto DeviceRegistry() { return DeviceRegistry::instance(); }

View File

@@ -8,6 +8,8 @@
#include <iostream> #include <iostream>
#include "framework/MicroService.h"
#include "Poco/Net/HTTPServerParams.h" #include "Poco/Net/HTTPServerParams.h"
#include "Poco/Net/HTTPServerResponse.h" #include "Poco/Net/HTTPServerResponse.h"
#include "Poco/DynamicAny.h" #include "Poco/DynamicAny.h"
@@ -20,14 +22,13 @@
#include "FileUploader.h" #include "FileUploader.h"
#include "StorageService.h" #include "StorageService.h"
#include "framework/MicroService.h"
namespace OpenWifi { namespace OpenWifi {
static const std::string URI_BASE{"/v1/upload/"}; static const std::string URI_BASE{"/v1/upload/"};
int FileUploader::Start() { int FileUploader::Start() {
Logger().notice("Starting."); poco_notice(Logger(),"Starting.");
Poco::File UploadsDir(MicroService::instance().ConfigPath("openwifi.fileuploader.path","/tmp")); Poco::File UploadsDir(MicroService::instance().ConfigPath("openwifi.fileuploader.path","/tmp"));
Path_ = UploadsDir.path(); Path_ = UploadsDir.path();
@@ -42,13 +43,14 @@ namespace OpenWifi {
for(const auto & Svr: ConfigServersList_) { for(const auto & Svr: ConfigServersList_) {
if(MicroService::instance().NoAPISecurity()) { if(MicroService::instance().NoAPISecurity()) {
Logger().information(fmt::format("Starting: {}:{}",Svr.Address(),Svr.Port())); poco_notice(Logger(), fmt::format("Starting: {}:{}",Svr.Address(),Svr.Port()));
auto Sock{Svr.CreateSocket(Logger())}; auto Sock{Svr.CreateSocket(Logger())};
auto Params = new Poco::Net::HTTPServerParams; auto Params = new Poco::Net::HTTPServerParams;
Params->setMaxThreads(16); Params->setMaxThreads(16);
Params->setMaxQueued(100); Params->setMaxQueued(100);
Params->setName("ws:upldr");
if (FullName_.empty()) { if (FullName_.empty()) {
std::string TmpName = std::string TmpName =
@@ -59,7 +61,7 @@ namespace OpenWifi {
} else { } else {
FullName_ = TmpName + URI_BASE; FullName_ = TmpName + URI_BASE;
} }
Logger().information(fmt::format("Uploader URI base is '{}'", FullName_)); poco_information(Logger(),fmt::format("Uploader URI base is '{}'", FullName_));
} }
auto NewServer = std::make_unique<Poco::Net::HTTPServer>( auto NewServer = std::make_unique<Poco::Net::HTTPServer>(
@@ -70,7 +72,7 @@ namespace OpenWifi {
} else { } else {
std::string l{"Starting: " + Svr.Address() + ":" + std::to_string(Svr.Port()) + std::string l{"Starting: " + Svr.Address() + ":" + std::to_string(Svr.Port()) +
" key:" + Svr.KeyFile() + " cert:" + Svr.CertFile()}; " key:" + Svr.KeyFile() + " cert:" + Svr.CertFile()};
Logger().information(l); poco_information(Logger(),l);
auto Sock{Svr.CreateSecureSocket(Logger())}; auto Sock{Svr.CreateSecureSocket(Logger())};
@@ -92,7 +94,7 @@ namespace OpenWifi {
} else { } else {
FullName_ = TmpName + URI_BASE; FullName_ = TmpName + URI_BASE;
} }
Logger().information(fmt::format("Uploader URI base is '{}'", FullName_)); poco_information(Logger(), fmt::format("Uploader URI base is '{}'", FullName_));
} }
auto NewServer = std::make_unique<Poco::Net::HTTPServer>( auto NewServer = std::make_unique<Poco::Net::HTTPServer>(
@@ -109,7 +111,7 @@ namespace OpenWifi {
void FileUploader::reinitialize([[maybe_unused]] Poco::Util::Application &self) { void FileUploader::reinitialize([[maybe_unused]] Poco::Util::Application &self) {
MicroService::instance().LoadConfigurationFile(); MicroService::instance().LoadConfigurationFile();
Logger().information("Reinitializing."); poco_information(Logger(),"Reinitializing.");
Stop(); Stop();
Start(); Start();
} }
@@ -198,7 +200,7 @@ namespace OpenWifi {
const auto ContentType = Request.getContentType(); const auto ContentType = Request.getContentType();
const auto Tokens = Poco::StringTokenizer(ContentType,";",Poco::StringTokenizer::TOK_TRIM); const auto Tokens = Poco::StringTokenizer(ContentType,";",Poco::StringTokenizer::TOK_TRIM);
Logger().debug(fmt::format("{}: Preparing to upload trace file.",UUID_)); poco_debug(Logger(),fmt::format("{}: Preparing to upload trace file.",UUID_));
Poco::JSON::Object Answer; Poco::JSON::Object Answer;
try { try {
@@ -223,7 +225,7 @@ namespace OpenWifi {
Poco::StreamCopier::copyStream(Reader.stream(), FileContent); Poco::StreamCopier::copyStream(Reader.stream(), FileContent);
Answer.set("filename", UUID_); Answer.set("filename", UUID_);
Answer.set("error", 0); Answer.set("error", 0);
Logger().debug(fmt::format("{}: Trace file uploaded.", UUID_)); poco_debug(Logger(),fmt::format("{}: Trace file uploaded.", UUID_));
StorageService()->AttachFileDataToCommand(UUID_, FileContent); StorageService()->AttachFileDataToCommand(UUID_, FileContent);
std::ostream &ResponseStream = Response.send(); std::ostream &ResponseStream = Response.send();
Poco::JSON::Stringifier::stringify(Answer, ResponseStream); Poco::JSON::Stringifier::stringify(Answer, ResponseStream);
@@ -241,10 +243,10 @@ namespace OpenWifi {
} catch (const Poco::Exception &E) { } catch (const Poco::Exception &E) {
Logger().log(E); Logger().log(E);
} catch (...) { } catch (...) {
Logger().debug("Exception while receiving trace file."); poco_debug(Logger(),"Exception while receiving trace file.");
} }
Logger().debug(fmt::format("{}: Failed to upload trace file.",UUID_)); poco_debug(Logger(),fmt::format("{}: Failed to upload trace file.",UUID_));
std::string Error{"Trace file rejected"}; std::string Error{"Trace file rejected"};
StorageService()->CancelWaitFile(UUID_, Error); StorageService()->CancelWaitFile(UUID_, Error);
Answer.set("filename", UUID_); Answer.set("filename", UUID_);
@@ -264,7 +266,13 @@ namespace OpenWifi {
Poco::Net::HTTPRequestHandler *FileUpLoaderRequestHandlerFactory::createRequestHandler(const Poco::Net::HTTPServerRequest & Request) { Poco::Net::HTTPRequestHandler *FileUpLoaderRequestHandlerFactory::createRequestHandler(const Poco::Net::HTTPServerRequest & Request) {
Logger().debug(fmt::format("REQUEST({}): {} {}", Utils::FormatIPv6(Request.clientAddress().toString()), Request.getMethod(), Request.getURI())); poco_debug(Logger(),fmt::format("REQUEST({}): {} {}", Utils::FormatIPv6(Request.clientAddress().toString()), Request.getMethod(), Request.getURI()));
if(Request.getMethod()!=Poco::Net::HTTPRequest::HTTP_POST ||
Request.getURI().size()<(URI_BASE.size()+36)) {
poco_warning(Logger(),fmt::format("ILLEGAL-REQUEST({}): {} {}. Dropped.", Utils::FormatIPv6(Request.clientAddress().toString()), Request.getMethod(), Request.getURI()));
return nullptr;
}
// The UUID should be after the /v1/upload/ part... // The UUID should be after the /v1/upload/ part...
auto UUIDLocation = Request.getURI().find_first_of(URI_BASE); auto UUIDLocation = Request.getURI().find_first_of(URI_BASE);
@@ -280,17 +288,18 @@ namespace OpenWifi {
} }
else else
{ {
Logger().warning(fmt::format("Unknown UUID={}",UUID)); poco_warning(Logger(),fmt::format("Unknown UUID={}",UUID));
} }
} }
return nullptr; return nullptr;
} }
void FileUploader::Stop() { void FileUploader::Stop() {
Logger().notice("Stopping..."); poco_notice(Logger(),"Stopping...");
for( const auto & svr : Servers_ ) for( const auto & svr : Servers_ )
svr->stop(); svr->stopAll(true);
Servers_.clear(); Servers_.clear();
poco_notice(Logger(),"Stopped...");
} }
} // Namespace } // Namespace

View File

@@ -8,12 +8,13 @@
#pragma once #pragma once
#include "framework/MicroService.h"
#include "Poco/Net/HTTPRequestHandler.h" #include "Poco/Net/HTTPRequestHandler.h"
#include "Poco/Net/HTTPRequestHandlerFactory.h" #include "Poco/Net/HTTPRequestHandlerFactory.h"
#include "Poco/Net/HTTPServer.h" #include "Poco/Net/HTTPServer.h"
#include "Poco/Net/HTTPServerRequest.h" #include "Poco/Net/HTTPServerRequest.h"
#include "framework/MicroService.h"
namespace OpenWifi { namespace OpenWifi {

View File

@@ -5,6 +5,7 @@
#pragma once #pragma once
#include "framework/MicroService.h" #include "framework/MicroService.h"
#include "Poco/Net/IPAddress.h" #include "Poco/Net/IPAddress.h"
#include "nlohmann/json.hpp" #include "nlohmann/json.hpp"
@@ -133,6 +134,7 @@ namespace OpenWifi {
} }
inline int Start() final { inline int Start() final {
poco_notice(Logger(),"Starting...");
ProviderName_ = MicroService::instance().ConfigGetString("iptocountry.provider",""); ProviderName_ = MicroService::instance().ConfigGetString("iptocountry.provider","");
if(!ProviderName_.empty()) { if(!ProviderName_.empty()) {
Provider_ = IPLocationProvider<IPToCountryProvider, IPInfo, IPData, IP2Location>(ProviderName_); Provider_ = IPLocationProvider<IPToCountryProvider, IPInfo, IPData, IP2Location>(ProviderName_);
@@ -145,6 +147,9 @@ namespace OpenWifi {
} }
inline void Stop() final { inline void Stop() final {
poco_notice(Logger(),"Stopping...");
// Nothing to do - just to provide the same look at the others.
poco_notice(Logger(),"Stopped...");
} }
[[nodiscard]] static inline std::string ReformatAddress(const std::string & I ) [[nodiscard]] static inline std::string ReformatAddress(const std::string & I )

View File

@@ -37,7 +37,6 @@ namespace OpenWifi {
bool &Done, std::string &Answer) { bool &Done, std::string &Answer) {
Done = false; Done = false;
auto Prefix = O->get("serial_prefix").toString(); auto Prefix = O->get("serial_prefix").toString();
Logger().information(Poco::format("serial_number_search: %s", Prefix));
if (!Prefix.empty() && Prefix.length() < 13) { if (!Prefix.empty() && Prefix.length() < 13) {
std::vector<uint64_t> Numbers; std::vector<uint64_t> Numbers;
SerialNumberCache()->FindNumbers(Prefix, 50, Numbers); SerialNumberCache()->FindNumbers(Prefix, 50, Numbers);

View File

@@ -29,13 +29,15 @@ namespace OpenWifi {
} }
void OUIServer::Stop() { void OUIServer::Stop() {
poco_notice(Logger(),"Stopping...");
Running_=false; Running_=false;
Timer_.stop(); Timer_.stop();
poco_notice(Logger(),"Stopped...");
} }
void OUIServer::reinitialize([[maybe_unused]] Poco::Util::Application &self) { void OUIServer::reinitialize([[maybe_unused]] Poco::Util::Application &self) {
MicroService::instance().LoadConfigurationFile(); MicroService::instance().LoadConfigurationFile();
Logger().information("Reinitializing."); poco_information(Logger(),"Reinitializing.");
Stop(); Stop();
Start(); Start();
} }
@@ -43,14 +45,14 @@ namespace OpenWifi {
bool OUIServer::GetFile(const std::string &FileName) { bool OUIServer::GetFile(const std::string &FileName) {
try { try {
LastUpdate_ = OpenWifi::Now(); LastUpdate_ = OpenWifi::Now();
Logger().information(fmt::format("Start: Retrieving OUI file: {}",MicroService::instance().ConfigGetString("oui.download.uri"))); poco_information(Logger(), fmt::format("Start: Retrieving OUI file: {}",MicroService::instance().ConfigGetString("oui.download.uri")));
std::unique_ptr<std::istream> pStr( std::unique_ptr<std::istream> pStr(
Poco::URIStreamOpener::defaultOpener().open(MicroService::instance().ConfigGetString("oui.download.uri"))); Poco::URIStreamOpener::defaultOpener().open(MicroService::instance().ConfigGetString("oui.download.uri")));
std::ofstream OS; std::ofstream OS;
OS.open(FileName); OS.open(FileName);
Poco::StreamCopier::copyStream(*pStr, OS); Poco::StreamCopier::copyStream(*pStr, OS);
OS.close(); OS.close();
Logger().information(fmt::format("Done: Retrieving OUI file: {}",MicroService::instance().ConfigGetString("oui.download.uri"))); poco_information(Logger(), fmt::format("Done: Retrieving OUI file: {}",MicroService::instance().ConfigGetString("oui.download.uri")));
return true; return true;
} catch (const Poco::Exception &E) { } catch (const Poco::Exception &E) {
Logger().log(E); Logger().log(E);
@@ -108,7 +110,7 @@ namespace OpenWifi {
if(ProcessFile(CurrentOUIFileName_, OUIs_)) { if(ProcessFile(CurrentOUIFileName_, OUIs_)) {
Initialized_ = true; Initialized_ = true;
Updating_=false; Updating_=false;
Logger().information("Using cached file."); poco_information(Logger(), "Using cached file.");
return; return;
} }
} else { } else {
@@ -128,7 +130,7 @@ namespace OpenWifi {
F1.remove(); F1.remove();
Poco::File F2(LatestOUIFileName_); Poco::File F2(LatestOUIFileName_);
F2.renameTo(CurrentOUIFileName_); F2.renameTo(CurrentOUIFileName_);
Logger().information(fmt::format("New OUI file {} downloaded.",LatestOUIFileName_)); poco_information(Logger(), fmt::format("New OUI file {} downloaded.",LatestOUIFileName_));
} else if(OUIs_.empty()) { } else if(OUIs_.empty()) {
if(ProcessFile(CurrentOUIFileName_, TmpOUIs)) { if(ProcessFile(CurrentOUIFileName_, TmpOUIs)) {
LastUpdate_ = OpenWifi::Now(); LastUpdate_ = OpenWifi::Now();

View File

@@ -1711,7 +1711,7 @@ namespace OpenWifi {
nlohmann::json new_ie; nlohmann::json new_ie;
nlohmann::json content; nlohmann::json content;
std::cout << BufferToHex(&data[0],data.size()) << std::endl; // std::cout << BufferToHex(&data[0],data.size()) << std::endl;
uint offset=0; uint offset=0;
auto sub_ie = data[offset++]; auto sub_ie = data[offset++];
switch (sub_ie) { switch (sub_ie) {
@@ -1745,7 +1745,7 @@ namespace OpenWifi {
try { try {
nlohmann::json D = nlohmann::json::parse(ofs.str()); nlohmann::json D = nlohmann::json::parse(ofs.str());
std::cout << "Start of parsing wifi" << std::endl; // std::cout << "Start of parsing wifi" << std::endl;
if (D.contains("status")) { if (D.contains("status")) {
auto Status = D["status"]; auto Status = D["status"];
if (Status.contains("scan") && Status["scan"].is_array()) { if (Status.contains("scan") && Status["scan"].is_array()) {
@@ -1814,17 +1814,17 @@ namespace OpenWifi {
} else if (ie_type == ieee80211_eid::WLAN_EID_EXTENSION) { } else if (ie_type == ieee80211_eid::WLAN_EID_EXTENSION) {
new_ies.push_back(WFS_WLAN_EID_EXTENSION(data)); new_ies.push_back(WFS_WLAN_EID_EXTENSION(data));
} else { } else {
std::cout // std::cout
<< "Skipping IE: no parsing available: " << ie_type // << "Skipping IE: no parsing available: " << ie_type
<< std::endl; // << std::endl;
new_ies.push_back(ie); new_ies.push_back(ie);
} }
} else { } else {
std::cout << "Skipping IE: no data and type" << std::endl; // std::cout << "Skipping IE: no data and type" << std::endl;
new_ies.push_back(ie); new_ies.push_back(ie);
} }
} catch (...) { } catch (...) {
std::cout << "Skipping IE: exception" << std::endl; // std::cout << "Skipping IE: exception" << std::endl;
Logger.information(fmt::format("Error parsing IEs")); Logger.information(fmt::format("Error parsing IEs"));
new_ies.push_back(ie); new_ies.push_back(ie);
} }
@@ -1832,7 +1832,7 @@ namespace OpenWifi {
scan_entry["ies"] = new_ies; scan_entry["ies"] = new_ies;
ParsedScan.push_back(scan_entry); ParsedScan.push_back(scan_entry);
} else { } else {
std::cout << "Skipping scan" << std::endl; // std::cout << "Skipping scan" << std::endl;
ParsedScan.push_back(scan_entry); ParsedScan.push_back(scan_entry);
} }
} }
@@ -1841,7 +1841,7 @@ namespace OpenWifi {
} }
} }
Result << to_string(D); Result << to_string(D);
std::cout << "End of parsing wifi" << std::endl; // std::cout << "End of parsing wifi" << std::endl;
return true; return true;
} catch (const Poco::Exception &E) { } catch (const Poco::Exception &E) {
Logger.log(E); Logger.log(E);

View File

@@ -9,8 +9,255 @@
#include <iostream> #include <iostream>
#include <iomanip> #include <iomanip>
#include "Poco/HMACEngine.h"
#include "Poco/MD5Engine.h"
namespace OpenWifi::RADIUS { namespace OpenWifi::RADIUS {
#define RADCMD_ACCESS_REQ 1 /* Access-Request */
#define RADCMD_ACCESS_ACC 2 /* Access-Accept */
#define RADCMD_ACCESS_REJ 3 /* Access-Reject */
#define RADCMD_ACCOUN_REQ 4 /* Accounting-Request */
#define RADCMD_ACCOUN_RES 5 /* Accounting-Response */
#define RADCMD_ACCOUN_STATUS 6 /* Accounting-Status */
#define RADCMD_PASSWORD_REQUEST 7 /* Password-Request [RFC3575] */
#define RADCMD_PASSWORD_ACK 8 /* Password-Ack [RFC3575] */
#define RADCMD_PASSWORD_REJECT 9 /* Password-Reject [RFC3575] */
#define RADCMD_ACCOUN_MESSAGE 10 /* Accounting-Message [RFC3575] */
#define RADCMD_RES_FREE_REQ 21 /* Resource-Free-Request [RFC3575] */
#define RADCMD_RES_FREE_RES 22 /* Resource-Free-Response [RFC3575] */
#define RADCMD_RES_QUERY_REQ 23 /* Resource-Query-Request [RFC3575] */
#define RADCMD_RES_QUERY_RES 24 /* Resource-Query-Response [RFC3575] */
#define RADCMD_RES_ALT_RECLAIM_REQ 25 /* Alternate-Resource-Reclaim-Request [RFC3575] */
#define RADCMD_ACCESS_CHA 11 /* Access-Challenge */
#define RADCMD_STATUS_SER 12 /* Status-Server */
#define RADCMD_STATUS_CLI 13 /* Status-Client */
#define RADCMD_DISCON_REQ 40 /* Disconnect-Request */
#define RADCMD_DISCON_ACK 41 /* Disconnect-ACK */
#define RADCMD_DISCON_NAK 42 /* Disconnect-NAK */
#define RADCMD_COA_REQ 43 /* CoA-Request */
#define RADCMD_COA_ACK 44 /* CoA-ACK */
#define RADCMD_COA_NAK 45 /* CoA-NAK */
#define RADCMD_RESERVED 255 /* Reserved */
/*
21 Resource-Free-Request [RFC3575]
22 Resource-Free-Response [RFC3575]
23 Resource-Query-Request [RFC3575]
24 Resource-Query-Response [RFC3575]
25 Alternate-Resource-Reclaim-Request [RFC3575]
26 NAS-Reboot-Request [RFC3575]
27 NAS-Reboot-Response [RFC3575]
28 Reserved
29 Next-Passcode [RFC3575]
30 New-Pin [RFC3575]
31 Terminate-Session [RFC3575]
32 Password-Expired [RFC3575]
33 Event-Request [RFC3575]
34 Event-Response [RFC3575]
35-39 Unassigned
40 Disconnect-Request [RFC3575][RFC5176]
41 Disconnect-ACK [RFC3575][RFC5176]
42 Disconnect-NAK [RFC3575][RFC5176]
43 CoA-Request [RFC3575][RFC5176]
44 CoA-ACK [RFC3575][RFC5176]
45 CoA-NAK [RFC3575][RFC5176]
46-49 Unassigned
50 IP-Address-Allocate [RFC3575]
51 IP-Address-Release [RFC3575]
52 Protocol-Error [RFC7930]
53-249 Unassigned
250-253 Experimental Use [RFC3575]
254 Reserved [RFC3575]
255 Reserved [RFC3575]
*/
struct tok {
uint cmd;
const char * name;
};
/*
Radius commands
char const *fr_packet_codes[FR_MAX_PACKET_CODE] = {
"", //!< 0
"Access-Request",
"Access-Accept",
"Access-Reject",
"Accounting-Request",
"Accounting-Response",
"Accounting-Status",
"Password-Request",
"Password-Accept",
"Password-Reject",
"Accounting-Message", //!< 10
"Access-Challenge",
"Status-Server",
"Status-Client",
"14",
"15",
"16",
"17",
"18",
"19",
"20", //!< 20
"Resource-Free-Request",
"Resource-Free-Response",
"Resource-Query-Request",
"Resource-Query-Response",
"Alternate-Resource-Reclaim-Request",
"NAS-Reboot-Request",
"NAS-Reboot-Response",
"28",
"Next-Passcode",
"New-Pin", //!< 30
"Terminate-Session",
"Password-Expired",
"Event-Request",
"Event-Response",
"35",
"36",
"37",
"38",
"39",
"Disconnect-Request", //!< 40
"Disconnect-ACK",
"Disconnect-NAK",
"CoA-Request",
"CoA-ACK",
"CoA-NAK",
"46",
"47",
"48",
"49",
"IP-Address-Allocate",
"IP-Address-Release", //!< 50
};
*/
static const struct tok radius_command_values[] = {
{ RADCMD_ACCESS_REQ, "Access-Request" },
{ RADCMD_ACCESS_ACC, "Access-Accept" },
{ RADCMD_ACCESS_REJ, "Access-Reject" },
{ RADCMD_ACCOUN_REQ, "Accounting-Request" },
{ RADCMD_ACCOUN_RES, "Accounting-Response" },
{ RADCMD_ACCESS_CHA, "Access-Challenge" },
{ RADCMD_STATUS_SER, "Status-Server" },
{ RADCMD_STATUS_CLI, "Status-Client" },
{ RADCMD_DISCON_REQ, "Disconnect-Request" },
{ RADCMD_DISCON_ACK, "Disconnect-ACK" },
{ RADCMD_DISCON_NAK, "Disconnect-NAK" },
{ RADCMD_COA_REQ, "CoA-Request" },
{ RADCMD_COA_ACK, "CoA-ACK" },
{ RADCMD_COA_NAK, "CoA-NAK" },
{ RADCMD_RESERVED, "Reserved" },
{ RADCMD_ACCOUN_STATUS, "Accounting-Status"},
{ RADCMD_PASSWORD_REQUEST, "Password-Request"},
{ RADCMD_PASSWORD_ACK, "Password-Ack"},
{ RADCMD_PASSWORD_REJECT, "Password-Reject"},
{ RADCMD_ACCOUN_MESSAGE, "Accounting-Message"},
{ RADCMD_RES_FREE_REQ, "Resource-Free-Request"},
{ RADCMD_RES_FREE_RES, "Resource-Free-Response"},
{ RADCMD_RES_QUERY_REQ, "Resource-Query-Request"},
{ RADCMD_RES_QUERY_RES, "Resource-Query-Response"},
{ RADCMD_RES_ALT_RECLAIM_REQ, "Alternate-Resource-Reclaim-Request"},
{ 0, nullptr}
};
static const struct tok radius_attribute_names[] = {
{1,"User-Name"},
{2,"User-Password"},
{3,"CHAP-Password"},
{4,"NAS-IP Address"},
{5,"NAS-Port"},
{6,"Service-Type"},
{7,"Framed-Protocol"},
{8,"Framed-IP-Address"},
{9,"Framed-IP-Netmask"},
{10,"Framed-Routing"},
{11,"Filter-Id"},
{12,"Framed-MTU"},
{13,"Framed-Compression"},
{14,"Login-IP-Host"},
{15,"Login-Service"},
{16,"Login-TCP-Port"},
{18,"Reply-Message"},
{19,"Callback-Number"},
{20,"Callback-ID"},
{22,"Framed-Route"},
{23,"Framed-IPX-Network"},
{24,"State"},
{25,"Class"},
{26,"Vendor-Specific"},
{27,"Session-Timeout"},
{28,"Idle-Timeout"},
{29,"Termination-Action"},
{30,"Called-Station-Id"},
{31,"Calling-Station-Id"},
{32,"NAS-Identifier"},
{33,"Proxy-State"},
{34,"Login-LAT-Service"},
{35,"Login-LAT-Node"},
{36,"Login-LAT-Group"},
{37,"Framed-AppleTalk-Link"},
{38,"Framed-AppleTalk-Network"},
{39,"Framed-AppleTalk-Zone"},
{40,"Acct-Status-Type"},
{41,"Acct-Delay-Time"},
{42,"Acct-Input-Octets"},
{43,"Acct-Output-Octets"},
{44,"Acct-Session-Id"},
{45,"Acct-Authentic"},
{46,"Acct-Session-Time"},
{47,"Acct-Input-Packets"},
{48,"Acct-Output-Packets"},
{49,"Acct-Terminate-Cause"},
{50,"Acct-Multi-Session-Id"},
{51,"Acct-Link-Count"},
{52,"Acct-Input-Gigawords"},
{53,"Acct-Output-Gigawords"},
{55,"Event-Timestamp"},
{60,"CHAP-Challenge"},
{61,"NAS-Port-Type"},
{62,"Port-Limit"},
{63,"Login-LAT-Port"},
{64,"Tunnel-Type3"},
{65,"Tunnel-Medium-Type1"},
{66,"Tunnel-Client-Endpoint"},
{67,"Tunnel-Server-Endpoint1"},
{68,"Acct-Tunnel-Connection-ID"},
{69,"Tunnel-Password1"},
{70,"ARAP-Password"},
{71,"ARAP-Features"},
{72,"ARAP-Zone-Access"},
{73,"ARAP-Security"},
{74,"ARAP-Security-Data"},
{75,"Password-Retry"},
{76,"Prompt"},
{77,"Connect-Info"},
{78,"Configuration-Token"},
{79,"EAP-Message"},
{80,"Message-Authenticator"},
{81,"Tunnel-Private-Group-ID"},
{82,"Tunnel-Assignment-ID1"},
{83,"Tunnel-Preference"},
{84,"ARAP-Challenge-Response"},
{85,"Acct-Interim-Interval"},
{86,"Acct-Tunnel-Packets-Lost"},
{87,"NAS-Port-ID"},
{88,"Framed-Pool"},
{90,"Tunnel-Client-Auth-ID"},
{91,"Tunnel-Server-Auth-ID"},
{0, nullptr}
};
#pragma pack(push,1) #pragma pack(push,1)
struct RadiusAttribute { struct RadiusAttribute {
unsigned char type{0}; unsigned char type{0};
@@ -20,12 +267,68 @@ namespace OpenWifi::RADIUS {
struct RawRadiusPacket { struct RawRadiusPacket {
unsigned char code{1}; unsigned char code{1};
unsigned char identifier{0}; unsigned char identifier{0};
uint16_t len{0}; uint16_t rawlen{0};
unsigned char authenticator[16]{0}; unsigned char authenticator[16]{0};
unsigned char attributes[4096]{0}; unsigned char attributes[4096]{0};
}; };
#pragma pack(pop) #pragma pack(pop)
constexpr unsigned char Access_Request = 1;
constexpr unsigned char Access_Accept = 2;
constexpr unsigned char Access_Reject = 3;
constexpr unsigned char Access_Challenge = 11;
constexpr unsigned char Accounting_Request = 4;
constexpr unsigned char Accounting_Response = 5;
constexpr unsigned char Accounting_Status = 6;
constexpr unsigned char Accounting_Message = 10;
constexpr unsigned char Disconnect_Request = 40;
constexpr unsigned char Disconnect_ACK = 41;
constexpr unsigned char Disconnect_NAK = 42;
constexpr unsigned char CoA_Request = 43;
constexpr unsigned char CoA_ACK = 44;
constexpr unsigned char CoA_NAK = 45;
inline bool IsAuthentication(unsigned char t) {
return (t == RADIUS::Access_Request ||
t == RADIUS::Access_Accept ||
t == RADIUS::Access_Challenge ||
t == RADIUS::Access_Reject);
}
inline bool IsAccounting(unsigned char t) {
return (t == RADIUS::Accounting_Request ||
t == RADIUS::Accounting_Response ||
t == RADIUS::Accounting_Status ||
t == RADIUS::Accounting_Message);
}
inline bool IsAuthority(unsigned char t) {
return (t == RADIUS::Disconnect_Request ||
t == RADIUS::Disconnect_ACK ||
t == RADIUS::Disconnect_NAK ||
t == RADIUS::CoA_Request ||
t == RADIUS::CoA_ACK ||
t == RADIUS::CoA_NAK);
}
inline const char * CommandName(uint cmd) {
auto cmds = radius_command_values;
while(cmds->cmd && (cmds->cmd!=cmd))
cmds++;
if(cmds->cmd==cmd) return cmds->name;
return "Unknown";
}
inline const char * AttributeName(uint cmd) {
auto cmds = radius_attribute_names;
while(cmds->cmd && (cmds->cmd!=cmd))
cmds++;
if(cmds->cmd==cmd) return cmds->name;
return "Unknown";
}
// //
// From: https://github.com/Telecominfraproject/wlan-dictionary/blob/main/dictionary.tip // From: https://github.com/Telecominfraproject/wlan-dictionary/blob/main/dictionary.tip
// //
@@ -34,23 +337,21 @@ namespace OpenWifi::RADIUS {
static const unsigned char TIP_AAAipaddr = 2; static const unsigned char TIP_AAAipaddr = 2;
static const unsigned char TIP_AAAipv6addr = 3; static const unsigned char TIP_AAAipv6addr = 3;
using AttributeList = std::list<RadiusAttribute>; using AttributeList = std::list<RadiusAttribute>;
std::ostream &operator<<(std::ostream &os, AttributeList const &P) { inline std::ostream &operator<<(std::ostream &os, AttributeList const &P) {
for(const auto &attr:P) { for(const auto &attr:P) {
os << "\tAttr: " << (uint16_t) attr.type << " Size: " << (uint16_t) attr.len << std::endl; os << "\tAttr: " << (uint16_t) attr.type << " Size: " << (uint16_t) attr.len << std::endl;
} }
return os; return os;
} }
bool ParseRadius(uint32_t offset, const unsigned char *Buffer, uint16_t Size, AttributeList &Attrs) { inline bool ParseRadius(uint32_t offset, const unsigned char *Buffer, uint16_t Size, AttributeList &Attrs) {
Attrs.clear(); Attrs.clear();
uint16_t pos=0; uint16_t pos=0;
auto x=25; auto x=25;
while(pos<Size && x) { while(pos<Size && x) {
RadiusAttribute Attr{ .type=Buffer[pos], .pos=(uint16_t)(pos+2+offset), .len=Buffer[pos+1]}; RadiusAttribute Attr{ .type=Buffer[pos], .pos=(uint16_t)(pos+2+offset), .len=(unsigned int)(Buffer[pos+1]-2)};
// std::cout << "POS: " << pos << " P:" << (uint32_t) Attr.pos << " T:" << (uint32_t) Attr.type << " L:" << (uint32_t) Attr.len << " S:" << (uint32_t) Size << std::endl;
if(pos+Attr.len<=Size) { if(pos+Attr.len<=Size) {
Attrs.emplace_back(Attr); Attrs.emplace_back(Attr);
} else { } else {
@@ -64,25 +365,55 @@ namespace OpenWifi::RADIUS {
pos+=Buffer[pos+1]; pos+=Buffer[pos+1];
x--; x--;
} }
// std::cout << "Good parse" << std::endl;
return true; return true;
} }
class RadiusPacket { class RadiusPacket {
public: public:
explicit RadiusPacket(const Poco::Buffer<char> & Buf) {
if(Buf.size() >= sizeof(RawRadiusPacket)) {
Valid_ = false;
return;
}
memcpy((void *)&P_,Buf.begin(), Buf.size());
Size_=Buf.size();
Valid_ = (Size_== htons(P_.rawlen));
if(Valid_)
Valid_ = ParseRadius(0,(unsigned char *)&P_.attributes[0],Size_-20,Attrs_);
}
explicit RadiusPacket(const unsigned char *buffer, uint16_t size) { explicit RadiusPacket(const unsigned char *buffer, uint16_t size) {
if(size >= sizeof(RawRadiusPacket)) {
Valid_ = false;
return;
}
memcpy((void *)&P_,buffer, size); memcpy((void *)&P_,buffer, size);
Size_=size; Size_=size;
Valid_ = ParseRadius(0,(unsigned char *)&P_.attributes[0],Size_-20,Attrs_); Valid_ = (Size_== htons(P_.rawlen));
if(Valid_)
Valid_ = ParseRadius(0,(unsigned char *)&P_.attributes[0],Size_-20,Attrs_);
} }
explicit RadiusPacket(const std::string &p) { explicit RadiusPacket(const std::string &p) {
if(p.size() >= sizeof(RawRadiusPacket)) {
Valid_ = false;
return;
}
memcpy((void *)&P_,(const unsigned char*) p.c_str(), p.size()); memcpy((void *)&P_,(const unsigned char*) p.c_str(), p.size());
Size_=p.size(); Size_=p.size();
Valid_ = ParseRadius(0,(unsigned char *)&P_.attributes[0],Size_-20,Attrs_); Valid_ = (Size_== htons(P_.rawlen));
if(Valid_)
Valid_ = ParseRadius(0,(unsigned char *)&P_.attributes[0],Size_-20,Attrs_);
} }
RadiusPacket() = default; explicit RadiusPacket(const RadiusPacket &P) {
Valid_ = P.Valid_;
Size_ = P.Size_;
P_ = P.P_;
Attrs_ = P.Attrs_;
}
explicit RadiusPacket() = default;
unsigned char * Buffer() { return (unsigned char *)&P_; } unsigned char * Buffer() { return (unsigned char *)&P_; }
[[nodiscard]] uint16_t BufferLen() const { return sizeof(P_);} [[nodiscard]] uint16_t BufferLen() const { return sizeof(P_);}
@@ -92,11 +423,39 @@ namespace OpenWifi::RADIUS {
Valid_ = ParseRadius(0,(unsigned char *)&P_.attributes[0],Size_-20,Attrs_); Valid_ = ParseRadius(0,(unsigned char *)&P_.attributes[0],Size_-20,Attrs_);
} }
[[nodiscard]] uint16_t Len() const { return htons(P_.len); } [[nodiscard]] uint16_t Len() const { return htons(P_.rawlen); }
[[nodiscard]] uint16_t Size() const { return Size_; } [[nodiscard]] uint16_t Size() const { return Size_; }
friend std::ostream &operator<<(std::ostream &os, RadiusPacket const &P); friend std::ostream &operator<<(std::ostream &os, RadiusPacket const &P);
inline bool IsAuthentication() {
return (P_.code == RADIUS::Access_Request ||
P_.code == RADIUS::Access_Accept ||
P_.code == RADIUS::Access_Challenge ||
P_.code == RADIUS::Access_Reject ||
P_.code == RADCMD_RES_FREE_REQ ||
P_.code == RADCMD_RES_FREE_RES ||
P_.code == RADCMD_RES_QUERY_REQ ||
P_.code == RADCMD_RES_QUERY_RES ||
P_.code == RADCMD_RES_ALT_RECLAIM_REQ);
}
inline bool IsAccounting() {
return (P_.code == RADIUS::Accounting_Request ||
P_.code == RADIUS::Accounting_Response ||
P_.code == RADIUS::Accounting_Status ||
P_.code == RADIUS::Accounting_Message);
}
inline bool IsAuthority() {
return (P_.code == RADIUS::Disconnect_Request ||
P_.code == RADIUS::Disconnect_ACK ||
P_.code == RADIUS::Disconnect_NAK ||
P_.code == RADIUS::CoA_Request ||
P_.code == RADIUS::CoA_ACK ||
P_.code == RADIUS::CoA_NAK);
}
void Log(std::ostream &os) { void Log(std::ostream &os) {
uint16_t p = 0; uint16_t p = 0;
@@ -110,9 +469,102 @@ namespace OpenWifi::RADIUS {
os << std::endl; os << std::endl;
p+=16; p+=16;
} }
os << std::dec << std::endl; os << std::dec << std::endl << std::endl;
Print(os);
} }
inline const char * PacketType() {
return CommandName(P_.code);
}
inline int PacketTypeInt() {
return (int)(P_.code);
}
void ComputeMessageAuthenticator(const std::string &secret) {
RawRadiusPacket P = P_;
if(P_.code==1) {
unsigned char OldAuthenticator[16]{0};
for (const auto &attr : Attrs_) {
if (attr.type == 80) {
memcpy(OldAuthenticator, &P_.attributes[attr.pos], 16);
memset(&P.attributes[attr.pos], 0, 16);
}
}
unsigned char NewAuthenticator[16]{0};
Poco::HMACEngine<Poco::MD5Engine> H(secret);
H.update((const unsigned char *)&P, Size_);
auto digest = H.digest();
int p = 0;
for (const auto &i : digest)
NewAuthenticator[p++] = i;
if (memcmp(OldAuthenticator, NewAuthenticator, 16) == 0) {
std::cout << "Authenticator match..." << std::endl;
} else {
std::cout << "Authenticator MIS-match..." << std::endl;
for (const auto &attr : Attrs_) {
if (attr.type == 80) {
memcpy(&P_.attributes[attr.pos], NewAuthenticator, 16);
}
}
}
}
}
bool VerifyMessageAuthenticator(const std::string &secret) {
RawRadiusPacket P = P_;
if(P_.code==1) {
unsigned char OldAuthenticator[16]{0};
for (const auto &attr : Attrs_) {
if (attr.type == 80) {
memcpy(OldAuthenticator, &P_.attributes[attr.pos], 16);
memset(&P.attributes[attr.pos], 0, 16);
}
}
unsigned char NewAuthenticator[16]{0};
Poco::HMACEngine<Poco::MD5Engine> H(secret);
H.update((const unsigned char *)&P, Size_);
auto digest = H.digest();
int p = 0;
for (const auto &i : digest)
NewAuthenticator[p++] = i;
return memcmp(OldAuthenticator, NewAuthenticator, 16) == 0;
}
return true;
}
static void BufLog(std::ostream & os, const char * pre, const unsigned char *b, uint s) {
uint16_t p = 0;
while(p<s) {
os << pre << std::setfill('0') << std::setw(4) << p << ": ";
uint16_t v=0;
while(v<16 && p+v<s) {
os << std::setfill('0') << std::setw(2) << std::right << std::hex << (uint16_t )b[p+v] << " ";
v++;
}
os << std::endl;
p+=16;
}
os << std::dec ;
}
inline void Print(std::ostream &os) {
os << "Packet type: (" << (uint) P_.code << ") " << CommandName(P_.code) << std::endl;
os << " Identifier: " << (uint) P_.identifier << std::endl;
os << " Length: " << Size_ << std::endl;
os << " Authenticator: " ;
BufLog(os, "", P_.authenticator, sizeof(P_.authenticator));
os << " Attributes: " << std::endl;
for(const auto &attr:Attrs_) {
os << " " << std::setfill(' ') << "(" << std::setw(4) << (uint) attr.type << ") " << AttributeName(attr.type) << " Len:" << attr.len << std::endl;
BufLog(os, " " , &P_.attributes[attr.pos], attr.len);
}
os << std::dec << std::endl << std::endl;
}
std::string ExtractSerialNumberTIP() { std::string ExtractSerialNumberTIP() {
std::string R; std::string R;
@@ -139,7 +591,6 @@ namespace OpenWifi::RADIUS {
} }
} }
} }
return R; return R;
} }
@@ -197,6 +648,16 @@ namespace OpenWifi::RADIUS {
return Result; return Result;
} }
[[nodiscard]] std::string UserName() const {
for(const auto &attr:Attrs_) {
if(attr.type==1) {
std::string user_name{(const char *)&P_.attributes[attr.pos],attr.len};
return user_name;
}
}
return "";
}
private: private:
RawRadiusPacket P_; RawRadiusPacket P_;
uint16_t Size_{0}; uint16_t Size_{0};
@@ -204,7 +665,7 @@ namespace OpenWifi::RADIUS {
bool Valid_=false; bool Valid_=false;
}; };
std::ostream &operator<<(std::ostream &os, RadiusPacket const &P) { inline std::ostream &operator<<(std::ostream &os, RadiusPacket const &P) {
os << P.Attrs_ ; os << P.Attrs_ ;
return os; return os;
} }

View File

@@ -15,13 +15,14 @@ namespace OpenWifi {
int RADIUS_proxy_server::Start() { int RADIUS_proxy_server::Start() {
ConfigFilename_ = MicroService::instance().DataDir()+"/radius_pool_config.json";
Poco::File Config(ConfigFilename_);
enabled_ = MicroService::instance().ConfigGetBool("radius.proxy.enable",false); enabled_ = MicroService::instance().ConfigGetBool("radius.proxy.enable",false);
if(!enabled_) if(!enabled_ && !Config.exists())
return 0; return 0;
ConfigFilename_ = MicroService::instance().DataDir()+"/radius_pool_config.json"; enabled_ = true;
Poco::Net::SocketAddress AuthSockAddrV4(Poco::Net::AddressFamily::IPv4, Poco::Net::SocketAddress AuthSockAddrV4(Poco::Net::AddressFamily::IPv4,
MicroService::instance().ConfigGetInt("radius.proxy.authentication.port",DEFAULT_RADIUS_AUTHENTICATION_PORT)); MicroService::instance().ConfigGetInt("radius.proxy.authentication.port",DEFAULT_RADIUS_AUTHENTICATION_PORT));
@@ -44,74 +45,88 @@ namespace OpenWifi {
MicroService::instance().ConfigGetInt("radius.proxy.coa.port",DEFAULT_RADIUS_CoA_PORT)); MicroService::instance().ConfigGetInt("radius.proxy.coa.port",DEFAULT_RADIUS_CoA_PORT));
CoASocketV6_ = std::make_unique<Poco::Net::DatagramSocket>(CoASockAddrV6,true); CoASocketV6_ = std::make_unique<Poco::Net::DatagramSocket>(CoASockAddrV6,true);
AuthenticationReactor_.addEventHandler(*AuthenticationSocketV4_,Poco::NObserver<RADIUS_proxy_server, Poco::Net::ReadableNotification>( RadiusReactor_.addEventHandler(*AuthenticationSocketV4_,Poco::NObserver<RADIUS_proxy_server, Poco::Net::ReadableNotification>(
*this, &RADIUS_proxy_server::OnAuthenticationSocketReadable)); *this, &RADIUS_proxy_server::OnAuthenticationSocketReadable));
AuthenticationReactor_.addEventHandler(*AuthenticationSocketV6_,Poco::NObserver<RADIUS_proxy_server, Poco::Net::ReadableNotification>( RadiusReactor_.addEventHandler(*AuthenticationSocketV6_,Poco::NObserver<RADIUS_proxy_server, Poco::Net::ReadableNotification>(
*this, &RADIUS_proxy_server::OnAuthenticationSocketReadable)); *this, &RADIUS_proxy_server::OnAuthenticationSocketReadable));
AccountingReactor_.addEventHandler(*AccountingSocketV4_,Poco::NObserver<RADIUS_proxy_server, Poco::Net::ReadableNotification>( RadiusReactor_.addEventHandler(*AccountingSocketV4_,Poco::NObserver<RADIUS_proxy_server, Poco::Net::ReadableNotification>(
*this, &RADIUS_proxy_server::OnAccountingSocketReadable)); *this, &RADIUS_proxy_server::OnAccountingSocketReadable));
AccountingReactor_.addEventHandler(*AccountingSocketV6_,Poco::NObserver<RADIUS_proxy_server, Poco::Net::ReadableNotification>( RadiusReactor_.addEventHandler(*AccountingSocketV6_,Poco::NObserver<RADIUS_proxy_server, Poco::Net::ReadableNotification>(
*this, &RADIUS_proxy_server::OnAccountingSocketReadable)); *this, &RADIUS_proxy_server::OnAccountingSocketReadable));
CoAReactor_.addEventHandler(*CoASocketV4_,Poco::NObserver<RADIUS_proxy_server, Poco::Net::ReadableNotification>( RadiusReactor_.addEventHandler(*CoASocketV4_,Poco::NObserver<RADIUS_proxy_server, Poco::Net::ReadableNotification>(
*this, &RADIUS_proxy_server::OnCoASocketReadable)); *this, &RADIUS_proxy_server::OnCoASocketReadable));
CoAReactor_.addEventHandler(*CoASocketV6_,Poco::NObserver<RADIUS_proxy_server, Poco::Net::ReadableNotification>( RadiusReactor_.addEventHandler(*CoASocketV6_,Poco::NObserver<RADIUS_proxy_server, Poco::Net::ReadableNotification>(
*this, &RADIUS_proxy_server::OnCoASocketReadable)); *this, &RADIUS_proxy_server::OnCoASocketReadable));
ParseConfig(); ParseConfig();
AuthenticationReactorThread_.start(AuthenticationReactor_); // start RADSEC servers...
AccountingReactorThread_.start(AccountingReactor_); StartRADSECServers();
CoAReactorThread_.start(CoAReactor_); RadiusReactorThread_.start(RadiusReactor_);
Utils::SetThreadName(AuthenticationReactorThread_,"radproxy:auth"); Utils::SetThreadName(RadiusReactorThread_,"rad:reactor");
Utils::SetThreadName(AccountingReactorThread_,"radproxy:acct");
Utils::SetThreadName(CoAReactorThread_,"radproxy:coa"); running_ = true;
return 0; return 0;
} }
void RADIUS_proxy_server::Stop() { void RADIUS_proxy_server::Stop() {
if(enabled_) { poco_information(Logger(),"Stopping...");
AuthenticationReactor_.removeEventHandler( if(enabled_ && running_) {
RadiusReactor_.removeEventHandler(
*AuthenticationSocketV4_, *AuthenticationSocketV4_,
Poco::NObserver<RADIUS_proxy_server, Poco::Net::ReadableNotification>( Poco::NObserver<RADIUS_proxy_server, Poco::Net::ReadableNotification>(
*this, &RADIUS_proxy_server::OnAuthenticationSocketReadable)); *this, &RADIUS_proxy_server::OnAuthenticationSocketReadable));
AuthenticationReactor_.removeEventHandler( RadiusReactor_.removeEventHandler(
*AuthenticationSocketV6_, *AuthenticationSocketV6_,
Poco::NObserver<RADIUS_proxy_server, Poco::Net::ReadableNotification>( Poco::NObserver<RADIUS_proxy_server, Poco::Net::ReadableNotification>(
*this, &RADIUS_proxy_server::OnAuthenticationSocketReadable)); *this, &RADIUS_proxy_server::OnAuthenticationSocketReadable));
AccountingReactor_.removeEventHandler( RadiusReactor_.removeEventHandler(
*AccountingSocketV4_, *AccountingSocketV4_,
Poco::NObserver<RADIUS_proxy_server, Poco::Net::ReadableNotification>( Poco::NObserver<RADIUS_proxy_server, Poco::Net::ReadableNotification>(
*this, &RADIUS_proxy_server::OnAccountingSocketReadable)); *this, &RADIUS_proxy_server::OnAccountingSocketReadable));
AccountingReactor_.removeEventHandler( RadiusReactor_.removeEventHandler(
*AccountingSocketV6_, *AccountingSocketV6_,
Poco::NObserver<RADIUS_proxy_server, Poco::Net::ReadableNotification>( Poco::NObserver<RADIUS_proxy_server, Poco::Net::ReadableNotification>(
*this, &RADIUS_proxy_server::OnAccountingSocketReadable)); *this, &RADIUS_proxy_server::OnAccountingSocketReadable));
CoAReactor_.removeEventHandler( RadiusReactor_.removeEventHandler(
*CoASocketV4_, *CoASocketV4_,
Poco::NObserver<RADIUS_proxy_server, Poco::Net::ReadableNotification>( Poco::NObserver<RADIUS_proxy_server, Poco::Net::ReadableNotification>(
*this, &RADIUS_proxy_server::OnAccountingSocketReadable)); *this, &RADIUS_proxy_server::OnCoASocketReadable));
CoAReactor_.removeEventHandler( RadiusReactor_.removeEventHandler(
*CoASocketV6_, *CoASocketV6_,
Poco::NObserver<RADIUS_proxy_server, Poco::Net::ReadableNotification>( Poco::NObserver<RADIUS_proxy_server, Poco::Net::ReadableNotification>(
*this, &RADIUS_proxy_server::OnAccountingSocketReadable)); *this, &RADIUS_proxy_server::OnCoASocketReadable));
AuthenticationReactor_.stop(); for(auto &[_,radsec_server]:RADSECservers_)
AuthenticationReactorThread_.join(); radsec_server->Stop();
AccountingReactor_.stop(); RadiusReactor_.stop();
AccountingReactorThread_.join(); RadiusReactorThread_.join();
CoAReactor_.stop();
CoAReactorThread_.join();
enabled_=false; enabled_=false;
running_=false;
} }
poco_information(Logger(),"Stopped...");
}
void RADIUS_proxy_server::StartRADSECServers() {
for(const auto &pool:PoolList_.pools) {
for(const auto &entry:pool.authConfig.servers) {
if(entry.radsec) {
StartRADSECServer(entry);
}
}
}
}
void RADIUS_proxy_server::StartRADSECServer(const GWObjects::RadiusProxyServerEntry &E) {
RADSECservers_[ Poco::Net::SocketAddress(E.ip,0) ] = std::make_unique<RADSECserver>(RadiusReactor_,E);
} }
void RADIUS_proxy_server::OnAccountingSocketReadable(const Poco::AutoPtr<Poco::Net::ReadableNotification>& pNf) { void RADIUS_proxy_server::OnAccountingSocketReadable(const Poco::AutoPtr<Poco::Net::ReadableNotification>& pNf) {
@@ -120,19 +135,19 @@ namespace OpenWifi {
auto ReceiveSize = pNf->socket().impl()->receiveBytes(P.Buffer(),P.BufferLen()); auto ReceiveSize = pNf->socket().impl()->receiveBytes(P.Buffer(),P.BufferLen());
if(ReceiveSize<SMALLEST_RADIUS_PACKET) { if(ReceiveSize<SMALLEST_RADIUS_PACKET) {
Logger().warning("Accounting: bad packet received."); poco_warning(Logger(),"Accounting: bad packet received.");
return; return;
} }
P.Evaluate(ReceiveSize); P.Evaluate(ReceiveSize);
auto SerialNumber = P.ExtractSerialNumberFromProxyState(); auto SerialNumber = P.ExtractSerialNumberFromProxyState();
if(SerialNumber.empty()) { if(SerialNumber.empty()) {
Logger().warning("Accounting: missing serial number."); poco_warning(Logger(),"Accounting: missing serial number.");
return; return;
} }
auto CallingStationID = P.ExtractCallingStationID(); auto CallingStationID = P.ExtractCallingStationID();
auto CalledStationID = P.ExtractCalledStationID(); auto CalledStationID = P.ExtractCalledStationID();
Logger().information(fmt::format("Accounting Packet received for {}, CalledStationID: {}, CallingStationID:{}",SerialNumber, CalledStationID, CallingStationID)); poco_information(Logger(), fmt::format("Accounting Packet received for {}, CalledStationID: {}, CallingStationID:{}",SerialNumber, CalledStationID, CallingStationID));
DeviceRegistry()->SendRadiusAccountingData(SerialNumber,P.Buffer(),P.Size()); DeviceRegistry()->SendRadiusAccountingData(SerialNumber,P.Buffer(),P.Size());
} }
@@ -142,19 +157,19 @@ namespace OpenWifi {
auto ReceiveSize = pNf->socket().impl()->receiveBytes(P.Buffer(),P.BufferLen()); auto ReceiveSize = pNf->socket().impl()->receiveBytes(P.Buffer(),P.BufferLen());
if(ReceiveSize<SMALLEST_RADIUS_PACKET) { if(ReceiveSize<SMALLEST_RADIUS_PACKET) {
Logger().warning("Authentication: bad packet received."); poco_warning(Logger(),"Authentication: bad packet received.");
return; return;
} }
P.Evaluate(ReceiveSize); P.Evaluate(ReceiveSize);
auto SerialNumber = P.ExtractSerialNumberFromProxyState(); auto SerialNumber = P.ExtractSerialNumberFromProxyState();
if(SerialNumber.empty()) { if(SerialNumber.empty()) {
Logger().warning("Authentication: missing serial number."); poco_warning(Logger(),"Authentication: missing serial number.");
return; return;
} }
auto CallingStationID = P.ExtractCallingStationID(); auto CallingStationID = P.ExtractCallingStationID();
auto CalledStationID = P.ExtractCalledStationID(); auto CalledStationID = P.ExtractCalledStationID();
Logger().information(fmt::format("Authentication Packet received for {}, CalledStationID: {}, CallingStationID:{}",SerialNumber, CalledStationID, CallingStationID)); poco_information(Logger(), fmt::format("Authentication Packet received for {}, CalledStationID: {}, CallingStationID:{}",SerialNumber, CalledStationID, CallingStationID));
DeviceRegistry()->SendRadiusAuthenticationData(SerialNumber,P.Buffer(),P.Size()); DeviceRegistry()->SendRadiusAuthenticationData(SerialNumber,P.Buffer(),P.Size());
} }
@@ -164,19 +179,19 @@ namespace OpenWifi {
auto ReceiveSize = pNf.get()->socket().impl()->receiveBytes(P.Buffer(),P.BufferLen()); auto ReceiveSize = pNf.get()->socket().impl()->receiveBytes(P.Buffer(),P.BufferLen());
if(ReceiveSize<SMALLEST_RADIUS_PACKET) { if(ReceiveSize<SMALLEST_RADIUS_PACKET) {
Logger().warning("CoA/DM: bad packet received."); poco_warning(Logger(),"CoA/DM: bad packet received.");
return; return;
} }
P.Evaluate(ReceiveSize); P.Evaluate(ReceiveSize);
auto SerialNumber = P.ExtractSerialNumberTIP(); auto SerialNumber = P.ExtractSerialNumberTIP();
if(SerialNumber.empty()) { if(SerialNumber.empty()) {
Logger().warning("CoA/DM: missing serial number."); poco_warning(Logger(),"CoA/DM: missing serial number.");
return; return;
} }
auto CallingStationID = P.ExtractCallingStationID(); auto CallingStationID = P.ExtractCallingStationID();
auto CalledStationID = P.ExtractCalledStationID(); auto CalledStationID = P.ExtractCalledStationID();
Logger().information(fmt::format("CoA Packet received for {}, CalledStationID: {}, CallingStationID:{}",SerialNumber, CalledStationID, CallingStationID)); poco_information(Logger(), fmt::format("CoA Packet received for {}, CalledStationID: {}, CallingStationID:{}",SerialNumber, CalledStationID, CallingStationID));
DeviceRegistry()->SendRadiusCoAData(SerialNumber,P.Buffer(),P.Size()); DeviceRegistry()->SendRadiusCoAData(SerialNumber,P.Buffer(),P.Size());
} }
@@ -188,12 +203,27 @@ namespace OpenWifi {
Poco::Net::SocketAddress Dst(Destination); Poco::Net::SocketAddress Dst(Destination);
std::lock_guard G(Mutex_); std::lock_guard G(Mutex_);
auto FinalDestination = Route(radius_type::auth, Dst); bool UseRADSEC = false;
auto AllSent = SendData(Dst.family()==Poco::Net::SocketAddress::IPv4 ? *AccountingSocketV4_ : *AccountingSocketV6_, (const unsigned char *)buffer, size, FinalDestination); auto FinalDestination = Route(radius_type::acct, Dst, P, UseRADSEC);
if(!AllSent) if(UseRADSEC) {
Logger().error(fmt::format("{}: Could not send Accounting packet packet to {}.", serialNumber, Destination)); Poco::Net::SocketAddress RSP(FinalDestination.host(),0);
else auto DestinationServer = RADSECservers_.find(RSP);
Logger().information(fmt::format("{}: Sending Accounting Packet to {}, CalledStationID: {}, CallingStationID:{}", serialNumber, FinalDestination.toString(), CalledStationID, CallingStationID)); if(DestinationServer!=end(RADSECservers_)) {
DestinationServer->second->SendData(serialNumber, (const unsigned char *)buffer, size);
}
} else {
auto AllSent =
SendData(Dst.family() == Poco::Net::SocketAddress::IPv4 ? *AccountingSocketV4_
: *AccountingSocketV6_,
(const unsigned char *)buffer, size, FinalDestination);
if (!AllSent)
poco_error(Logger(),fmt::format("{}: Could not send Accounting packet packet to {}.",
serialNumber, Destination));
else
poco_information(Logger(), fmt::format(
"{}: Sending Accounting Packet to {}, CalledStationID: {}, CallingStationID:{}",
serialNumber, FinalDestination.toString(), CalledStationID, CallingStationID));
}
} }
bool RADIUS_proxy_server::SendData( Poco::Net::DatagramSocket & Sock, const unsigned char *buf , std::size_t size, const Poco::Net::SocketAddress &S) { bool RADIUS_proxy_server::SendData( Poco::Net::DatagramSocket & Sock, const unsigned char *buf , std::size_t size, const Poco::Net::SocketAddress &S) {
@@ -208,19 +238,32 @@ namespace OpenWifi {
Poco::Net::SocketAddress Dst(Destination); Poco::Net::SocketAddress Dst(Destination);
std::lock_guard G(Mutex_); std::lock_guard G(Mutex_);
auto FinalDestination = Route(radius_type::auth, Dst); bool UseRADSEC = false;
auto AllSent = SendData(Dst.family()==Poco::Net::SocketAddress::IPv4 ? *AuthenticationSocketV4_ : *AuthenticationSocketV6_, (const unsigned char *)buffer, size, FinalDestination); auto FinalDestination = Route(radius_type::auth, Dst, P, UseRADSEC);
if(!AllSent) if(UseRADSEC) {
Logger().error(fmt::format("{}: Could not send Authentication packet packet to {}.", serialNumber, Destination)); Poco::Net::SocketAddress RSP(FinalDestination.host(),0);
else auto DestinationServer = RADSECservers_.find(RSP);
Logger().information(fmt::format("{}: Sending Authentication Packet to {}, CalledStationID: {}, CallingStationID:{}", serialNumber, FinalDestination.toString(), CalledStationID, CallingStationID)); if(DestinationServer!=end(RADSECservers_)) {
DestinationServer->second->SendData(serialNumber, (const unsigned char *)buffer, size);
}
} else {
auto AllSent =
SendData(Dst.family() == Poco::Net::SocketAddress::IPv4 ? *AuthenticationSocketV4_
: *AuthenticationSocketV6_,
(const unsigned char *)buffer, size, FinalDestination);
if (!AllSent)
poco_error(Logger(),fmt::format("{}: Could not send Authentication packet packet to {}.",
serialNumber, Destination));
else
poco_information(Logger(), fmt::format("{}: Sending Authentication Packet to {}, CalledStationID: {}, CallingStationID:{}",
serialNumber, FinalDestination.toString(),
CalledStationID, CallingStationID));
}
} }
void RADIUS_proxy_server::SendCoAData(const std::string &serialNumber, const char *buffer, std::size_t size) { void RADIUS_proxy_server::SendCoAData(const std::string &serialNumber, const char *buffer, std::size_t size) {
RADIUS::RadiusPacket P((unsigned char *)buffer,size); RADIUS::RadiusPacket P((unsigned char *)buffer,size);
auto Destination = P.ExtractProxyStateDestination(); auto Destination = P.ExtractProxyStateDestination();
// auto CallingStationID = P.ExtractCallingStationID();
// auto CalledStationID = P.ExtractCalledStationID();
if(Destination.empty()) { if(Destination.empty()) {
Destination = "0.0.0.0:0"; Destination = "0.0.0.0:0";
@@ -228,12 +271,25 @@ namespace OpenWifi {
Poco::Net::SocketAddress Dst(Destination); Poco::Net::SocketAddress Dst(Destination);
std::lock_guard G(Mutex_); std::lock_guard G(Mutex_);
auto FinalDestination = Route(radius_type::auth, Dst); bool UseRADSEC = false;
auto AllSent = SendData(Dst.family()==Poco::Net::SocketAddress::IPv4 ? *CoASocketV4_ : *CoASocketV6_, (const unsigned char *)buffer, size, FinalDestination); auto FinalDestination = Route(radius_type::coa, Dst, P, UseRADSEC);
if(!AllSent) if(UseRADSEC) {
Logger().error(fmt::format("{}: Could not send CoA packet packet to {}.", serialNumber, Destination)); Poco::Net::SocketAddress RSP(FinalDestination.host(),0);
else auto DestinationServer = RADSECservers_.find(RSP);
Logger().information(fmt::format("{}: Sending CoA Packet to {}", serialNumber, FinalDestination.toString())); if(DestinationServer!=end(RADSECservers_)) {
DestinationServer->second->SendData(serialNumber, (const unsigned char *)buffer, size);
}
} else {
auto AllSent = SendData(Dst.family() == Poco::Net::SocketAddress::IPv4 ? *CoASocketV4_
: *CoASocketV6_,
(const unsigned char *)buffer, size, FinalDestination);
if (!AllSent)
poco_error(Logger(),fmt::format("{}: Could not send CoA packet packet to {}.",
serialNumber, Destination));
else
poco_information(Logger(), fmt::format("{}: Sending CoA Packet to {}", serialNumber,
FinalDestination.toString()));
}
} }
void RADIUS_proxy_server::ParseServerList(const GWObjects::RadiusProxyServerConfig & Config, std::vector<Destination> &V4, std::vector<Destination> &V6, bool setAsDefault) { void RADIUS_proxy_server::ParseServerList(const GWObjects::RadiusProxyServerConfig & Config, std::vector<Destination> &V4, std::vector<Destination> &V6, bool setAsDefault) {
@@ -242,7 +298,7 @@ namespace OpenWifi {
for(const auto &server:Config.servers) { for(const auto &server:Config.servers) {
Poco::Net::IPAddress a; Poco::Net::IPAddress a;
if(!Poco::Net::IPAddress::tryParse(server.ip,a)) { if(!Poco::Net::IPAddress::tryParse(server.ip,a)) {
Logger().error(fmt::format("RADIUS-PARSE Config: server address {} is nto a valid address in v4 or v6. Entry skipped.",server.ip)); poco_error(Logger(),fmt::format("RADIUS-PARSE Config: server address {} is nto a valid address in v4 or v6. Entry skipped.",server.ip));
continue; continue;
} }
auto S = Poco::Net::SocketAddress(fmt::format("{}:{}",server.ip,server.port)); auto S = Poco::Net::SocketAddress(fmt::format("{}:{}",server.ip,server.port));
@@ -256,9 +312,14 @@ namespace OpenWifi {
.monitor = Config. monitor, .monitor = Config. monitor,
.monitorMethod = Config.monitorMethod, .monitorMethod = Config.monitorMethod,
.methodParameters = Config.methodParameters, .methodParameters = Config.methodParameters,
.useAsDefault = setAsDefault .useAsDefault = setAsDefault,
.useRADSEC = server.radsec,
.realms = server.radsecRealms
}; };
if(setAsDefault && D.useRADSEC)
defaultIsRADSEC_ = true;
if(S.family()==Poco::Net::IPAddress::IPv4) { if(S.family()==Poco::Net::IPAddress::IPv4) {
TotalV4 += server.weight; TotalV4 += server.weight;
V4.push_back(D); V4.push_back(D);
@@ -308,82 +369,119 @@ namespace OpenWifi {
Pools_.push_back(NewPool); Pools_.push_back(NewPool);
} }
} else { } else {
Logger().warning(fmt::format("Configuration file '{}' is bad.",ConfigFilename_)); poco_warning(Logger(),fmt::format("Configuration file '{}' is bad.",ConfigFilename_));
} }
} else { } else {
Logger().warning(fmt::format("No configuration file '{}' exists.",ConfigFilename_)); poco_warning(Logger(),fmt::format("No configuration file '{}' exists.",ConfigFilename_));
} }
} catch (const Poco::Exception &E) { } catch (const Poco::Exception &E) {
Logger().log(E); Logger().log(E);
} catch (...) { } catch (...) {
Logger().error(fmt::format("Error while parsing configuration file '{}'",ConfigFilename_)); poco_error(Logger(),fmt::format("Error while parsing configuration file '{}'",ConfigFilename_));
} }
} }
Poco::Net::SocketAddress RADIUS_proxy_server::DefaultRoute([[maybe_unused]] radius_type rtype, const Poco::Net::SocketAddress &RequestedAddress) { static bool RealmMatch(const std::string &user_realm, const std::string & realm) {
if(realm.find_first_of('*') == std::string::npos)
return user_realm == realm;
return realm.find(user_realm) != std::string::npos;
}
Poco::Net::SocketAddress RADIUS_proxy_server::DefaultRoute(radius_type rtype, const Poco::Net::SocketAddress &RequestedAddress, const RADIUS::RadiusPacket &P, bool &UseRADSEC) {
bool IsV4 = RequestedAddress.family()==Poco::Net::SocketAddress::IPv4; bool IsV4 = RequestedAddress.family()==Poco::Net::SocketAddress::IPv4;
// find the realm...
auto UserName = P.UserName();
if(!UserName.empty()) {
auto UserTokens = Poco::StringTokenizer(UserName, "@");
auto UserRealm = ((UserTokens.count() > 1) ? UserTokens[1] : UserName);
Poco::toLowerInPlace(UserRealm);
for(const auto &pool:Pools_) {
for(const auto &server:pool.AuthV4) {
if(!server.realms.empty()) {
for(const auto &realm:server.realms) {
if (RealmMatch(UserRealm,realm)) {
std::cout << "Realm match..." << std::endl;
UseRADSEC = true;
return server.Addr;
}
}
}
}
}
}
if(defaultIsRADSEC_) {
UseRADSEC = true;
return (IsV4 ? Pools_[defaultPoolIndex_].AuthV4[0].Addr : Pools_[defaultPoolIndex_].AuthV6[0].Addr );
}
switch(rtype) { switch(rtype) {
case radius_type::coa: { case radius_type::auth: {
return ChooseAddress(IsV4 ? Pools_[defaultPoolIndex_].CoaV4 return ChooseAddress(IsV4 ? Pools_[defaultPoolIndex_].AuthV4
: Pools_[defaultPoolIndex_].CoaV6, : Pools_[defaultPoolIndex_].AuthV6,
RequestedAddress); RequestedAddress);
} }
case radius_type::auth: { case radius_type::acct:
return ChooseAddress(IsV4 ? Pools_[defaultPoolIndex_].AuthV4 default: {
: Pools_[defaultPoolIndex_].AuthV6, return ChooseAddress(IsV4 ? Pools_[defaultPoolIndex_].AcctV4
RequestedAddress); : Pools_[defaultPoolIndex_].AcctV6,
} RequestedAddress);
case radius_type::acct: }
default: { case radius_type::coa: {
return ChooseAddress(IsV4 ? Pools_[defaultPoolIndex_].AcctV4 return ChooseAddress(IsV4 ? Pools_[defaultPoolIndex_].CoaV4
: Pools_[defaultPoolIndex_].AcctV6, : Pools_[defaultPoolIndex_].CoaV6,
RequestedAddress); RequestedAddress);
} }
} }
} }
Poco::Net::SocketAddress RADIUS_proxy_server::Route([[maybe_unused]] radius_type rtype, const Poco::Net::SocketAddress &RequestedAddress) { Poco::Net::SocketAddress RADIUS_proxy_server::Route([[maybe_unused]] radius_type rtype, const Poco::Net::SocketAddress &RequestedAddress, const RADIUS::RadiusPacket &P, bool &UseRADSEC) {
std::lock_guard G(Mutex_); std::lock_guard G(Mutex_);
if(Pools_.empty()) { if(Pools_.empty()) {
UseRADSEC = false;
return RequestedAddress; return RequestedAddress;
} }
bool IsV4 = RequestedAddress.family()==Poco::Net::SocketAddress::IPv4; bool IsV4 = RequestedAddress.family()==Poco::Net::SocketAddress::IPv4;
bool useDefault = false; bool useDefault;
useDefault = IsV4 ? RequestedAddress.host() == Poco::Net::IPAddress::wildcard(Poco::Net::IPAddress::IPv4) : RequestedAddress.host() == Poco::Net::IPAddress::wildcard(Poco::Net::IPAddress::IPv6) ; useDefault = IsV4 ? RequestedAddress.host() == Poco::Net::IPAddress::wildcard(Poco::Net::IPAddress::IPv4) : RequestedAddress.host() == Poco::Net::IPAddress::wildcard(Poco::Net::IPAddress::IPv6) ;
if(useDefault) { if(useDefault) {
return DefaultRoute(rtype, RequestedAddress); return DefaultRoute(rtype, RequestedAddress, P, UseRADSEC);
} }
auto isAddressInPool = [&](const std::vector<Destination> & D) -> bool { auto isAddressInPool = [&](const std::vector<Destination> & D, bool &UseRADSEC) -> bool {
for(const auto &entry:D) for(const auto &entry:D)
if(entry.Addr.host()==RequestedAddress.host()) if(entry.Addr.host()==RequestedAddress.host()) {
UseRADSEC = entry.useRADSEC;
return true; return true;
}
return false; return false;
}; };
for(auto &i:Pools_) { for(auto &i:Pools_) {
switch(rtype) { switch(rtype) {
case radius_type::coa: { case radius_type::coa: {
if (isAddressInPool((IsV4 ? i.CoaV4 : i.CoaV6))) { if (isAddressInPool((IsV4 ? i.CoaV4 : i.CoaV6), UseRADSEC)) {
return ChooseAddress(IsV4 ? i.CoaV4 : i.CoaV6, RequestedAddress); return ChooseAddress(IsV4 ? i.CoaV4 : i.CoaV6, RequestedAddress);
} }
} break; } break;
case radius_type::auth: { case radius_type::auth: {
if (isAddressInPool((IsV4 ? i.AuthV4 : i.AuthV6))) { if (isAddressInPool((IsV4 ? i.AuthV4 : i.AuthV6), UseRADSEC)) {
return ChooseAddress(IsV4 ? i.AuthV4 : i.AuthV6, RequestedAddress); return ChooseAddress(IsV4 ? i.AuthV4 : i.AuthV6, RequestedAddress);
} }
} break; } break;
case radius_type::acct: { case radius_type::acct: {
if (isAddressInPool((IsV4 ? i.AcctV4 : i.AcctV6))) { if (isAddressInPool((IsV4 ? i.AcctV4 : i.AcctV6), UseRADSEC)) {
return ChooseAddress(IsV4 ? i.AcctV4 : i.AcctV6, RequestedAddress); return ChooseAddress(IsV4 ? i.AcctV4 : i.AcctV6, RequestedAddress);
} }
} break; } break;
} }
} }
return DefaultRoute(rtype, RequestedAddress); return DefaultRoute(rtype, RequestedAddress, P, UseRADSEC);
} }
Poco::Net::SocketAddress RADIUS_proxy_server::ChooseAddress(std::vector<Destination> &Pool, const Poco::Net::SocketAddress & OriginalAddress) { Poco::Net::SocketAddress RADIUS_proxy_server::ChooseAddress(std::vector<Destination> &Pool, const Poco::Net::SocketAddress & OriginalAddress) {
@@ -459,6 +557,10 @@ namespace OpenWifi {
Disk.stringify(ofs); Disk.stringify(ofs);
ofs.close(); ofs.close();
if(!running_) {
Start();
}
ParseConfig(); ParseConfig();
} }
@@ -479,6 +581,7 @@ namespace OpenWifi {
} }
ResetConfig(); ResetConfig();
Stop();
} }
void RADIUS_proxy_server::GetConfig(GWObjects::RadiusProxyPoolList &C) { void RADIUS_proxy_server::GetConfig(GWObjects::RadiusProxyPoolList &C) {

View File

@@ -10,12 +10,15 @@
#include "Poco/Net/DatagramSocket.h" #include "Poco/Net/DatagramSocket.h"
#include "Poco/Net/SocketReactor.h" #include "Poco/Net/SocketReactor.h"
#include "RADSECserver.h"
namespace OpenWifi { namespace OpenWifi {
enum class radius_type { enum class radius_type {
auth, acct, coa auth, acct, coa
}; };
class RADIUS_proxy_server : public SubSystemServer { class RADIUS_proxy_server : public SubSystemServer {
public: public:
inline static auto instance() { inline static auto instance() {
@@ -39,6 +42,9 @@ namespace OpenWifi {
void DeleteConfig(); void DeleteConfig();
void GetConfig(GWObjects::RadiusProxyPoolList &C); void GetConfig(GWObjects::RadiusProxyPoolList &C);
void StartRADSECServers();
void StartRADSECServer(const GWObjects::RadiusProxyServerEntry &E);
struct Destination { struct Destination {
Poco::Net::SocketAddress Addr; Poco::Net::SocketAddress Addr;
uint64_t state = 0; uint64_t state = 0;
@@ -50,6 +56,8 @@ namespace OpenWifi {
std::string monitorMethod; std::string monitorMethod;
std::vector<std::string> methodParameters; std::vector<std::string> methodParameters;
bool useAsDefault=false; bool useAsDefault=false;
bool useRADSEC=false;
std::vector<std::string> realms;
}; };
private: private:
@@ -59,16 +67,14 @@ namespace OpenWifi {
std::unique_ptr<Poco::Net::DatagramSocket> AuthenticationSocketV6_; std::unique_ptr<Poco::Net::DatagramSocket> AuthenticationSocketV6_;
std::unique_ptr<Poco::Net::DatagramSocket> CoASocketV4_; std::unique_ptr<Poco::Net::DatagramSocket> CoASocketV4_;
std::unique_ptr<Poco::Net::DatagramSocket> CoASocketV6_; std::unique_ptr<Poco::Net::DatagramSocket> CoASocketV6_;
Poco::Net::SocketReactor AccountingReactor_; Poco::Net::SocketReactor RadiusReactor_;
Poco::Net::SocketReactor AuthenticationReactor_; Poco::Thread RadiusReactorThread_;
Poco::Net::SocketReactor CoAReactor_;
Poco::Thread AuthenticationReactorThread_;
Poco::Thread AccountingReactorThread_;
Poco::Thread CoAReactorThread_;
GWObjects::RadiusProxyPoolList PoolList_; GWObjects::RadiusProxyPoolList PoolList_;
std::string ConfigFilename_; std::string ConfigFilename_;
std::map<Poco::Net::SocketAddress, std::unique_ptr<RADSECserver>> RADSECservers_;
struct RadiusPool { struct RadiusPool {
std::vector<Destination> AuthV4; std::vector<Destination> AuthV4;
std::vector<Destination> AuthV6; std::vector<Destination> AuthV6;
@@ -81,6 +87,8 @@ namespace OpenWifi {
std::vector<RadiusPool> Pools_; std::vector<RadiusPool> Pools_;
uint defaultPoolIndex_=0; uint defaultPoolIndex_=0;
bool enabled_=false; bool enabled_=false;
bool defaultIsRADSEC_=false;
std::atomic_bool running_=false;
RADIUS_proxy_server() noexcept: RADIUS_proxy_server() noexcept:
SubSystemServer("RADIUS-PROXY", "RADIUS-PROXY", "radius.proxy") SubSystemServer("RADIUS-PROXY", "RADIUS-PROXY", "radius.proxy")
@@ -91,10 +99,10 @@ namespace OpenWifi {
void ParseConfig(); void ParseConfig();
void ResetConfig(); void ResetConfig();
Poco::Net::SocketAddress Route(radius_type rtype, const Poco::Net::SocketAddress &A); Poco::Net::SocketAddress Route(radius_type rtype, const Poco::Net::SocketAddress &A, const RADIUS::RadiusPacket &P, bool &UseRADSEC);
void ParseServerList(const GWObjects::RadiusProxyServerConfig & Config, std::vector<Destination> &V4, std::vector<Destination> &V6, bool setAsDefault); void ParseServerList(const GWObjects::RadiusProxyServerConfig & Config, std::vector<Destination> &V4, std::vector<Destination> &V6, bool setAsDefault);
static Poco::Net::SocketAddress ChooseAddress(std::vector<Destination> &Pool, const Poco::Net::SocketAddress & OriginalAddress); static Poco::Net::SocketAddress ChooseAddress(std::vector<Destination> &Pool, const Poco::Net::SocketAddress & OriginalAddress);
Poco::Net::SocketAddress DefaultRoute([[maybe_unused]] radius_type rtype, const Poco::Net::SocketAddress &RequestedAddress); Poco::Net::SocketAddress DefaultRoute([[maybe_unused]] radius_type rtype, const Poco::Net::SocketAddress &RequestedAddress, const RADIUS::RadiusPacket &P, bool &UseRADSEC);
}; };
inline auto RADIUS_proxy_server() { return RADIUS_proxy_server::instance(); } inline auto RADIUS_proxy_server() { return RADIUS_proxy_server::instance(); }

251
src/RADSECserver.h Normal file
View File

@@ -0,0 +1,251 @@
//
// Created by stephane bourque on 2022-08-15.
//
#pragma once
#include <iostream>
#include <fstream>
#include "framework/MicroService.h"
#include "RESTObjects/RESTAPI_GWobjects.h"
#include "Poco/Net/SocketReactor.h"
#include "Poco/Net/SecureStreamSocket.h"
#include "Poco/Net/Context.h"
#include "Poco/Crypto/X509Certificate.h"
#include "Poco/Net/NetException.h"
#include "Poco/TemporaryFile.h"
#include "RADIUS_helpers.h"
#include "DeviceRegistry.h"
namespace OpenWifi {
class RADSECserver : public Poco::Runnable {
public:
RADSECserver(Poco::Net::SocketReactor & R, GWObjects::RadiusProxyServerEntry E) :
Reactor_(R),
Server_(std::move(E)),
Logger_(Poco::Logger::get(fmt::format("RADSEC: {}@{}:{}",
Server_.name ,
Server_.ip,
Server_.port)))
{
ReconnectorThr_.start(*this);
}
inline void run() final {
while(TryAgain_) {
if(!Connected_) {
std::unique_lock G(Mutex_);
Connect();
}
Poco::Thread::trySleep(1000);
}
}
inline bool SendData(const std::string &serial_number, const unsigned char *buffer, int length) {
try {
if (Connected_) {
RADIUS::RadiusPacket P(buffer, length);
// std::cout << serial_number << " Sending " << P.PacketType() << " " << length << " bytes" << std::endl;
int sent_bytes;
if (P.VerifyMessageAuthenticator(Server_.radsecSecret)) {
Logger_.debug(fmt::format("{}: {} Sending {} bytes", serial_number,
P.PacketType(), length));
sent_bytes = Socket_->sendBytes(buffer, length);
} else {
Logger_.debug(fmt::format("{}: {} Sending {} bytes", serial_number,
P.PacketType(), length));
P.ComputeMessageAuthenticator(Server_.radsecSecret);
sent_bytes = Socket_->sendBytes(P.Buffer(), length);
}
return (sent_bytes == length);
}
} catch (...) {
}
return false;
}
inline void onData([[maybe_unused]] const Poco::AutoPtr<Poco::Net::ReadableNotification>& pNf) {
unsigned char Buffer[4096];
try {
auto NumberOfReceivedBytes = Socket_->receiveBytes(Buffer,sizeof(Buffer));
if(NumberOfReceivedBytes>40) {
RADIUS::RadiusPacket P(Buffer,NumberOfReceivedBytes);
// P.Log(std::cout);
// std::cout << "RADSEC: " << P.PacketType() << " " << (int) P.PacketTypeInt() << " Received " << NumberOfReceivedBytes << " bytes" << std::endl;
if (P.IsAuthentication()) {
auto SerialNumber = P.ExtractSerialNumberFromProxyState();
Logger_.debug(fmt::format("{}: {} Received {} bytes.", SerialNumber, P.PacketType(), NumberOfReceivedBytes));
DeviceRegistry()->SendRadiusAuthenticationData(
SerialNumber, Buffer,
NumberOfReceivedBytes);
} else if (P.IsAccounting()) {
auto SerialNumber = P.ExtractSerialNumberFromProxyState();
Logger_.debug(fmt::format("{}: {} Received {} bytes.", SerialNumber, P.PacketType(), NumberOfReceivedBytes));
DeviceRegistry()->SendRadiusAccountingData(
SerialNumber, Buffer,
NumberOfReceivedBytes);
} else if (P.IsAuthority()) {
}
} else {
Disconnect();
}
} catch (const Poco::Exception &E) {
Logger_.log(E);
Disconnect();
}
}
inline void onError([[maybe_unused]] const Poco::AutoPtr<Poco::Net::ErrorNotification>& pNf) {
std::cout << "onError" << std::endl;
Disconnect();
}
inline void onShutdown([[maybe_unused]] const Poco::AutoPtr<Poco::Net::ShutdownNotification>& pNf) {
std::cout << "onShutdown" << std::endl;
Disconnect();
}
inline bool Connect() {
if(TryAgain_) {
Poco::TemporaryFile CertFile_(MicroService::instance().DataDir());
Poco::TemporaryFile KeyFile_(MicroService::instance().DataDir());
std::vector<Poco::TemporaryFile> CaCertFiles_;
DecodeFile(CertFile_.path(), Server_.radsecCert);
DecodeFile(KeyFile_.path(), Server_.radsecKey);
for(auto &cert:Server_.radsecCacerts) {
CaCertFiles_.emplace_back(Poco::TemporaryFile(MicroService::instance().DataDir()));
DecodeFile(CaCertFiles_[CaCertFiles_.size()-1].path(), cert);
}
Poco::Net::Context::Ptr SecureContext = Poco::AutoPtr<Poco::Net::Context>(
new Poco::Net::Context(Poco::Net::Context::TLS_CLIENT_USE,
KeyFile_.path(),
CertFile_.path(),""));
for(const auto &ca:CaCertFiles_) {
Poco::Crypto::X509Certificate cert(ca.path());
SecureContext->addCertificateAuthority(cert);
}
Socket_ = std::make_unique<Poco::Net::SecureStreamSocket>(SecureContext);
Poco::Net::SocketAddress Destination(Server_.ip, Server_.port);
try {
poco_information(Logger_, "Attempting to connect");
Socket_->connect(Destination, Poco::Timespan(100, 0));
Socket_->completeHandshake();
Socket_->verifyPeerCertificate();
if(Socket_->havePeerCertificate()) {
Peer_Cert_ = std::make_unique<Poco::Crypto::X509Certificate>(Socket_->peerCertificate());
}
Socket_->setBlocking(false);
Socket_->setNoDelay(true);
Socket_->setKeepAlive(true);
Reactor_.addEventHandler(
*Socket_,
Poco::NObserver<RADSECserver, Poco::Net::ReadableNotification>(
*this, &RADSECserver::onData));
Reactor_.addEventHandler(
*Socket_, Poco::NObserver<RADSECserver, Poco::Net::ErrorNotification>(
*this, &RADSECserver::onError));
Reactor_.addEventHandler(
*Socket_,
Poco::NObserver<RADSECserver, Poco::Net::ShutdownNotification>(
*this, &RADSECserver::onShutdown));
Socket_->setBlocking(false);
Socket_->setNoDelay(true);
Socket_->setKeepAlive(true);
Connected_ = true;
poco_information(Logger_,fmt::format("Connected. CN={}",CommonName()));
return true;
} catch (const Poco::Net::NetException &E) {
poco_information(Logger_,"Could not connect.");
Logger_.log(E);
} catch (const Poco::Exception &E) {
poco_information(Logger_,"Could not connect.");
Logger_.log(E);
} catch (...) {
poco_information(Logger_,"Could not connect.");
}
}
return false;
}
inline void Disconnect() {
if(Connected_) {
std::unique_lock G(Mutex_);
Reactor_.removeEventHandler(
*Socket_, Poco::NObserver<RADSECserver, Poco::Net::ReadableNotification>(
*this, &RADSECserver::onData));
Reactor_.removeEventHandler(
*Socket_, Poco::NObserver<RADSECserver, Poco::Net::ErrorNotification>(
*this, &RADSECserver::onError));
Reactor_.removeEventHandler(
*Socket_, Poco::NObserver<RADSECserver, Poco::Net::ShutdownNotification>(
*this, &RADSECserver::onShutdown));
Connected_ = false;
}
poco_information(Logger_,"Disconnecting.");
}
inline void Stop() {
TryAgain_ = false;
Disconnect();
ReconnectorThr_.wakeUp();
ReconnectorThr_.join();
}
static void DecodeFile(const std::string &filename, const std::string &s) {
std::ofstream sec_file(filename,std::ios_base::out|std::ios_base::trunc|std::ios_base::binary);
std::stringstream is(s);
Poco::Base64Decoder ds(is);
Poco::StreamCopier::copyStream(ds,sec_file);
sec_file.close();
}
[[nodiscard]] inline std::string CommonName() {
if(Peer_Cert_)
return Peer_Cert_->commonName();
return "";
}
[[nodiscard]] inline std::string IssuerName() {
if(Peer_Cert_)
return Peer_Cert_->issuerName();
return "";
}
[[nodiscard]] inline std::string SubjectName() {
if(Peer_Cert_)
return Peer_Cert_->subjectName();
return "";
}
private:
std::shared_mutex Mutex_;
Poco::Net::SocketReactor &Reactor_;
GWObjects::RadiusProxyServerEntry Server_;
Poco::Logger &Logger_;
std::atomic_bool Connected_=false;
std::atomic_bool TryAgain_=true;
std::unique_ptr<Poco::Net::SecureStreamSocket> Socket_;
Poco::Thread ReconnectorThr_;
std::unique_ptr<Poco::Crypto::X509Certificate> Peer_Cert_;
};
}

View File

@@ -42,15 +42,19 @@ namespace OpenWifi::RESTAPI_RPC {
RESTAPIHandler * Handler, RESTAPIHandler * Handler,
Poco::Logger &Logger) { Poco::Logger &Logger) {
Logger.information(fmt::format("{}: New {} command. User={} Serial={}. ", Cmd.UUID, Cmd.Command, Cmd.SubmittedBy, Cmd.SerialNumber)); Logger.information(fmt::format("{},{}: New {} command. User={} Serial={}. ", Cmd.UUID, RPCID, Cmd.Command, Cmd.SubmittedBy, Cmd.SerialNumber));
// if the command should be executed in the future, or if the device is not connected, // if the command should be executed in the future, or if the device is not connected,
// then we should just add the command to // then we should just add the command to
// the DB and let it figure out when to deliver the command. // the DB and let it figure out when to deliver the command.
if (Cmd.RunAt || !DeviceRegistry()->Connected(Cmd.SerialNumber)) { auto SerialNumberInt = Utils::SerialNumberToInt(Cmd.SerialNumber);
Logger.information(fmt::format("{}: Command will be run in the future or when device is connected again.", Cmd.UUID)); if (Cmd.RunAt || (!DeviceRegistry()->Connected(SerialNumberInt) && RetryLater)) {
SetCommandStatus(Cmd, Request, Response, Handler, Storage::COMMAND_PENDING, Logger); Logger.information(fmt::format("{},{}: Command will be run in the future or when device is connected again.", Cmd.UUID, RPCID));
SetCommandStatus(Cmd, Request, Response, Handler, Storage::CommandExecutionType::COMMAND_PENDING, Logger);
return; return;
} else if ((!DeviceRegistry()->Connected(SerialNumberInt) && !RetryLater)){
Logger.information(fmt::format("{},{}: Command canceled. Device is not connected. Command will not be retried.", Cmd.UUID, RPCID));
return SetCommandStatus(Cmd, Request, Response, Handler, Storage::CommandExecutionType::COMMAND_FAILED, Logger);
} }
Cmd.Executed = OpenWifi::Now(); Cmd.Executed = OpenWifi::Now();
@@ -61,25 +65,24 @@ namespace OpenWifi::RESTAPI_RPC {
CommandManager()->PostCommand(RPCID, Cmd.SerialNumber, Cmd.Command, Params, Cmd.UUID, Sent); CommandManager()->PostCommand(RPCID, Cmd.SerialNumber, Cmd.Command, Params, Cmd.UUID, Sent);
if(RetryLater && (!Sent || rpc_endpoint== nullptr)) { if(RetryLater && (!Sent || rpc_endpoint== nullptr)) {
Logger.information(fmt::format("{}: Pending completion. Device is not connected.", Cmd.UUID)); Logger.information(fmt::format("{},{}: Pending completion. Device is not connected.", Cmd.UUID, RPCID));
return SetCommandStatus(Cmd, Request, Response, Handler, Storage::COMMAND_PENDING, Logger); return SetCommandStatus(Cmd, Request, Response, Handler, Storage::CommandExecutionType::COMMAND_PENDING, Logger);
} }
if(!RetryLater && !Sent) { if(!RetryLater && !Sent) {
Logger.information(fmt::format("{}: Command canceled. Device is not connected. Command will not be retried.", Cmd.UUID)); Logger.information(fmt::format("{},{}: Command canceled. Device is not connected. Command will not be retried.", Cmd.UUID, RPCID));
return SetCommandStatus(Cmd, Request, Response, Handler, Storage::COMMAND_FAILED, Logger); return SetCommandStatus(Cmd, Request, Response, Handler, Storage::CommandExecutionType::COMMAND_FAILED, Logger);
} }
Logger.information(fmt::format("{}: Command sent.", Cmd.UUID)); Logger.information(fmt::format("{},{}: Command sent.", Cmd.UUID, RPCID));
std::future<CommandManager::objtype_t> rpc_future(rpc_endpoint->get_future()); std::future<CommandManager::objtype_t> rpc_future(rpc_endpoint->get_future());
auto rpc_result = rpc_future.wait_for(WaitTimeInMs); auto rpc_result = rpc_future.wait_for(WaitTimeInMs);
if (rpc_result == std::future_status::ready) { if (rpc_result == std::future_status::ready) {
std::chrono::duration<double, std::milli> rpc_execution_time = std::chrono::high_resolution_clock::now() - rpc_submitted; std::chrono::duration<double, std::milli> rpc_execution_time = std::chrono::high_resolution_clock::now() - rpc_submitted;
auto rpc_answer = rpc_future.get(); auto rpc_answer = rpc_future.get();
if (!rpc_answer.has(uCentralProtocol::RESULT) || !rpc_answer.isObject(uCentralProtocol::RESULT)) { if (!rpc_answer.has(uCentralProtocol::RESULT) || !rpc_answer.isObject(uCentralProtocol::RESULT)) {
SetCommandStatus(Cmd, Request, Response, Handler, Storage::COMMAND_FAILED, Logger); SetCommandStatus(Cmd, Request, Response, Handler, Storage::CommandExecutionType::COMMAND_FAILED, Logger);
Logger.information(fmt::format("{}: Invalid response. Missing result.", Cmd.UUID)); Logger.information(fmt::format("{},{}: Invalid response. Missing result.", Cmd.UUID, RPCID));
return; return;
} }
@@ -87,11 +90,11 @@ namespace OpenWifi::RESTAPI_RPC {
if (!ResultFields->has(uCentralProtocol::STATUS) || !ResultFields->isObject(uCentralProtocol::STATUS)) { if (!ResultFields->has(uCentralProtocol::STATUS) || !ResultFields->isObject(uCentralProtocol::STATUS)) {
Cmd.executionTime = rpc_execution_time.count(); Cmd.executionTime = rpc_execution_time.count();
if(Cmd.Command=="ping") { if(Cmd.Command=="ping") {
SetCommandStatus(Cmd, Request, Response, Handler, Storage::COMMAND_COMPLETED, Logger); SetCommandStatus(Cmd, Request, Response, Handler, Storage::CommandExecutionType::COMMAND_COMPLETED, Logger);
Logger.information(fmt::format("{}: Invalid response from device (ping: fix override). Missing status.", Cmd.UUID)); Logger.information(fmt::format("{},{}: Invalid response from device (ping: fix override). Missing status.", Cmd.UUID, RPCID));
} else { } else {
SetCommandStatus(Cmd, Request, Response, Handler, Storage::COMMAND_FAILED, Logger); SetCommandStatus(Cmd, Request, Response, Handler, Storage::CommandExecutionType::COMMAND_FAILED, Logger);
Logger.information(fmt::format("{}: Invalid response from device. Missing status.", Cmd.UUID)); Logger.information(fmt::format("{},{}: Invalid response from device. Missing status.", Cmd.UUID,RPCID));
} }
return; return;
} }
@@ -131,7 +134,7 @@ namespace OpenWifi::RESTAPI_RPC {
} }
// Add the completed command to the database... // Add the completed command to the database...
StorageService()->AddCommand(Cmd.SerialNumber, Cmd, Storage::COMMAND_COMPLETED); StorageService()->AddCommand(Cmd.SerialNumber, Cmd, Storage::CommandExecutionType::COMMAND_COMPLETED);
if (ObjectToReturn && Handler) { if (ObjectToReturn && Handler) {
Handler->ReturnObject(*ObjectToReturn); Handler->ReturnObject(*ObjectToReturn);
@@ -141,10 +144,16 @@ namespace OpenWifi::RESTAPI_RPC {
if(Handler) if(Handler)
Handler->ReturnObject(O); Handler->ReturnObject(O);
} }
Logger.information( fmt::format("{}: Completed in {:.3f}ms.", Cmd.UUID, Cmd.executionTime)); Logger.information( fmt::format("{},{}: Completed in {:.3f}ms.", Cmd.UUID, RPCID, Cmd.executionTime));
return; return;
} }
Logger.information(fmt::format( "{}: Pending completion.", Cmd.UUID)); CommandManager()->RemovePendingCommand(RPCID);
SetCommandStatus(Cmd, Request, Response, Handler, Storage::COMMAND_PENDING, Logger); if(RetryLater) {
Logger.information(fmt::format("{},{}: Pending completion.", Cmd.UUID, RPCID));
SetCommandStatus(Cmd, Request, Response, Handler, Storage::CommandExecutionType::COMMAND_PENDING, Logger);
} else {
Logger.information(fmt::format("{},{}: Command canceled. Device is not connected. Command will not be retried.", Cmd.UUID, RPCID));
return SetCommandStatus(Cmd, Request, Response, Handler, Storage::CommandExecutionType::COMMAND_FAILED, Logger);
}
} }
} }

View File

@@ -18,7 +18,7 @@ namespace OpenWifi {
void RESTAPI_blacklist::DoDelete() { void RESTAPI_blacklist::DoDelete() {
auto SerialNumber = GetBinding(RESTAPI::Protocol::SERIALNUMBER, ""); auto SerialNumber = GetBinding(RESTAPI::Protocol::SERIALNUMBER, "");
if(!Utils::ValidSerialNumber(SerialNumber)) { if(!Utils::NormalizeMac(SerialNumber)) {
return BadRequest(RESTAPI::Errors::MissingSerialNumber); return BadRequest(RESTAPI::Errors::MissingSerialNumber);
} }
@@ -36,7 +36,7 @@ namespace OpenWifi {
void RESTAPI_blacklist::DoGet() { void RESTAPI_blacklist::DoGet() {
auto SerialNumber = GetBinding(RESTAPI::Protocol::SERIALNUMBER, ""); auto SerialNumber = GetBinding(RESTAPI::Protocol::SERIALNUMBER, "");
if(!Utils::ValidSerialNumber(SerialNumber)) { if(!Utils::NormalizeMac(SerialNumber)) {
return BadRequest(RESTAPI::Errors::MissingSerialNumber); return BadRequest(RESTAPI::Errors::MissingSerialNumber);
} }
@@ -51,13 +51,14 @@ namespace OpenWifi {
} }
void RESTAPI_blacklist::DoPost() { void RESTAPI_blacklist::DoPost() {
const auto &Obj = ParsedBody_; const auto &Obj = ParsedBody_;
GWObjects::BlackListedDevice D; GWObjects::BlackListedDevice D;
if(!D.from_json(Obj)) { if(!D.from_json(Obj)) {
return BadRequest(RESTAPI::Errors::InvalidJSONDocument); return BadRequest(RESTAPI::Errors::InvalidJSONDocument);
} }
if(D.serialNumber.empty()) { if(D.serialNumber.empty() || !Utils::NormalizeMac(D.serialNumber)) {
return BadRequest(RESTAPI::Errors::MissingSerialNumber); return BadRequest(RESTAPI::Errors::MissingSerialNumber);
} }
@@ -83,7 +84,7 @@ namespace OpenWifi {
void RESTAPI_blacklist::DoPut() { void RESTAPI_blacklist::DoPut() {
auto SerialNumber = Poco::toLower(GetBinding(RESTAPI::Protocol::SERIALNUMBER, "")); auto SerialNumber = Poco::toLower(GetBinding(RESTAPI::Protocol::SERIALNUMBER, ""));
if(!Utils::ValidSerialNumber(SerialNumber)) { if(!Utils::NormalizeMac(SerialNumber)) {
return BadRequest(RESTAPI::Errors::MissingSerialNumber); return BadRequest(RESTAPI::Errors::MissingSerialNumber);
} }

View File

@@ -13,7 +13,7 @@
namespace OpenWifi { namespace OpenWifi {
void RESTAPI_commands::DoGet() { void RESTAPI_commands::DoGet() {
auto SerialNumber = GetParameter(RESTAPI::Protocol::SERIALNUMBER, ""); auto SerialNumber = GetParameter(RESTAPI::Protocol::SERIALNUMBER, "");
if(!Utils::ValidSerialNumber(SerialNumber)) { if(!Utils::NormalizeMac(SerialNumber)) {
return BadRequest(RESTAPI::Errors::MissingSerialNumber); return BadRequest(RESTAPI::Errors::MissingSerialNumber);
} }
@@ -37,7 +37,7 @@ namespace OpenWifi {
void RESTAPI_commands::DoDelete() { void RESTAPI_commands::DoDelete() {
auto SerialNumber = GetParameter(RESTAPI::Protocol::SERIALNUMBER, ""); auto SerialNumber = GetParameter(RESTAPI::Protocol::SERIALNUMBER, "");
if(!Utils::ValidSerialNumber(SerialNumber)) { if(!Utils::NormalizeMac(SerialNumber)) {
return BadRequest(RESTAPI::Errors::MissingSerialNumber); return BadRequest(RESTAPI::Errors::MissingSerialNumber);
} }

View File

@@ -28,12 +28,16 @@
namespace OpenWifi { namespace OpenWifi {
void RESTAPI_device_commandHandler::CallCanceled(const char * Cmd, const OpenWifi::RESTAPI::Errors::msg &Err, const std::string & Details) {
Logger_.warning(fmt::format("{},{}: TID={} Canceled. Error:{} Reason:{} Details={}", Cmd, SerialNumber_, TransactionId_, Err.err_num, Err.err_txt, Details));
}
void RESTAPI_device_commandHandler::DoGet() { void RESTAPI_device_commandHandler::DoGet() {
if(!ValidateParameters()) { if(!ValidateParameters()) {
return BadRequest(RESTAPI::Errors::MissingOrInvalidParameters); return BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
} }
if(!Utils::ValidSerialNumber(SerialNumber_)) { if(!Utils::NormalizeMac(SerialNumber_)) {
return BadRequest(RESTAPI::Errors::MissingSerialNumber); return BadRequest(RESTAPI::Errors::MissingSerialNumber);
} }
@@ -42,7 +46,9 @@ namespace OpenWifi {
return NotFound(); return NotFound();
} }
Poco::Thread::current()->setName(fmt::format("{}: {}",SerialNumber_,Command_)); SerialNumberInt_ = Utils::SerialNumberToInt(SerialNumber_);
Poco::Thread::current()->setName(fmt::format("{}:{}:{}", Command_, TransactionId_, SerialNumber_));
if (Command_ == RESTAPI::Protocol::CAPABILITIES){ if (Command_ == RESTAPI::Protocol::CAPABILITIES){
return GetCapabilities(); return GetCapabilities();
} else if (Command_ == RESTAPI::Protocol::LOGS) { } else if (Command_ == RESTAPI::Protocol::LOGS) {
@@ -54,31 +60,38 @@ namespace OpenWifi {
} else if (Command_ == RESTAPI::Protocol::STATUS) { } else if (Command_ == RESTAPI::Protocol::STATUS) {
return GetStatus(); return GetStatus();
} else if (Command_ == RESTAPI::Protocol::RTTY) { } else if (Command_ == RESTAPI::Protocol::RTTY) {
if(!DeviceRegistry()->Connected(SerialNumberInt_)) {
CallCanceled(Command_.c_str(), RESTAPI::Errors::DeviceNotConnected);
return BadRequest(RESTAPI::Errors::DeviceNotConnected);
}
auto UUID = MicroService::CreateUUID(); auto UUID = MicroService::CreateUUID();
auto RPC = CommandManager()->NextRPCId(); auto RPC = CommandManager()->NextRPCId();
return Rtty(UUID,RPC); poco_debug(Logger_,fmt::format("Command rtty TID={} can proceed. Identified as {} and RPCID as {}. thr_id={}",
TransactionId_, UUID, RPC,
Poco::Thread::current()->id()));
return Rtty(UUID,RPC,60000ms);
} else { } else {
return BadRequest(RESTAPI::Errors::InvalidCommand); return BadRequest(RESTAPI::Errors::InvalidCommand);
} }
} }
void RESTAPI_device_commandHandler::DoDelete() { void RESTAPI_device_commandHandler::DoDelete() {
if(!ValidateParameters()) { if(!ValidateParameters()) {
return BadRequest(RESTAPI::Errors::MissingOrInvalidParameters); return BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
} }
if(!Utils::ValidSerialNumber(SerialNumber_)) { if(!Utils::NormalizeMac(SerialNumber_)) {
return BadRequest(RESTAPI::Errors::MissingSerialNumber); return BadRequest(RESTAPI::Errors::MissingSerialNumber);
} }
Poco::Thread::current()->setName(fmt::format("{}: {}",SerialNumber_,Command_));
GWObjects::Device TheDevice; GWObjects::Device TheDevice;
if(!StorageService()->GetDevice(SerialNumber_,TheDevice)) { if(!StorageService()->GetDevice(SerialNumber_,TheDevice)) {
return NotFound(); return NotFound();
} }
SerialNumberInt_ = Utils::SerialNumberToInt(SerialNumber_);
Poco::Thread::current()->setName(fmt::format("{}:{}:{}",Command_, TransactionId_,SerialNumber_));
if (Command_ == RESTAPI::Protocol::CAPABILITIES) { if (Command_ == RESTAPI::Protocol::CAPABILITIES) {
return DeleteCapabilities(); return DeleteCapabilities();
} else if (Command_ == RESTAPI::Protocol::LOGS){ } else if (Command_ == RESTAPI::Protocol::LOGS){
@@ -92,57 +105,91 @@ namespace OpenWifi {
} }
} }
struct PostDeviceCommand {
const char * Command;
bool AllowParallel=false;
bool RequireConnection = true;
void (RESTAPI_device_commandHandler::*funPtr)(const std::string &, std::uint64_t, std::chrono::milliseconds );
std::chrono::milliseconds Timeout=120ms;
};
/*
const static std::vector<PostDeviceCommand> PostCommands
{
{ RESTAPI::Protocol::PERFORM, false, true, &RESTAPI_device_commandHandler::ExecuteCommand },
{ RESTAPI::Protocol::CONFIGURE, false, false, &RESTAPI_device_commandHandler::Configure },
{ RESTAPI::Protocol::UPGRADE, false, false, &RESTAPI_device_commandHandler::Upgrade },
{ RESTAPI::Protocol::REBOOT, false, true, &RESTAPI_device_commandHandler::Reboot },
{ RESTAPI::Protocol::FACTORY, false, false, &RESTAPI_device_commandHandler::Factory },
{ RESTAPI::Protocol::LEDS, false, true, &RESTAPI_device_commandHandler::LEDs },
{ RESTAPI::Protocol::TRACE, false, true, &RESTAPI_device_commandHandler::Trace },
{ RESTAPI::Protocol::REQUEST, false, true, &RESTAPI_device_commandHandler::MakeRequest },
{ RESTAPI::Protocol::WIFISCAN, false, true, &RESTAPI_device_commandHandler::WifiScan },
{ RESTAPI::Protocol::EVENTQUEUE, false, true, &RESTAPI_device_commandHandler::EventQueue },
{ RESTAPI::Protocol::TELEMETRY, false, true, &RESTAPI_device_commandHandler::Telemetry },
{ RESTAPI::Protocol::PING, false, true, &RESTAPI_device_commandHandler::Ping },
{ RESTAPI::Protocol::SCRIPT, false, true, &RESTAPI_device_commandHandler::Script }
};
*/
void RESTAPI_device_commandHandler::DoPost() { void RESTAPI_device_commandHandler::DoPost() {
if(!ValidateParameters()) { if(!ValidateParameters()) {
return BadRequest(RESTAPI::Errors::MissingOrInvalidParameters); return BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
} }
if(!Utils::NormalizeMac(SerialNumber_)) {
if(!Utils::ValidSerialNumber(SerialNumber_)) {
return BadRequest(RESTAPI::Errors::MissingSerialNumber); return BadRequest(RESTAPI::Errors::MissingSerialNumber);
} }
SerialNumberInt_ = Utils::SerialNumberToInt(SerialNumber_);
Poco::Thread::current()->setName(fmt::format("{}: {}",SerialNumber_,Command_));
GWObjects::Device TheDevice; GWObjects::Device TheDevice;
if(!StorageService()->GetDevice(SerialNumber_,TheDevice)) { if(!StorageService()->GetDevice(SerialNumber_,TheDevice)) {
return NotFound(); return NotFound();
} }
auto UUID = MicroService::CreateUUID(); const std::vector<PostDeviceCommand> PostCommands =
auto RPC = CommandManager()->NextRPCId(); {
{ RESTAPI::Protocol::PERFORM, false, true, &RESTAPI_device_commandHandler::ExecuteCommand, 120000ms },
{ RESTAPI::Protocol::CONFIGURE, false, false, &RESTAPI_device_commandHandler::Configure, 120000ms },
{ RESTAPI::Protocol::UPGRADE, false, false, &RESTAPI_device_commandHandler::Upgrade, 30000ms },
{ RESTAPI::Protocol::REBOOT, false, true, &RESTAPI_device_commandHandler::Reboot, 30000ms },
{ RESTAPI::Protocol::FACTORY, false, false, &RESTAPI_device_commandHandler::Factory, 30000ms },
{ RESTAPI::Protocol::LEDS, false, true, &RESTAPI_device_commandHandler::LEDs, 120000ms },
{ RESTAPI::Protocol::TRACE, false, true, &RESTAPI_device_commandHandler::Trace, 300000ms },
{ RESTAPI::Protocol::REQUEST, false, true, &RESTAPI_device_commandHandler::MakeRequest, 120000ms },
{ RESTAPI::Protocol::WIFISCAN, false, true, &RESTAPI_device_commandHandler::WifiScan, 120000ms },
{ RESTAPI::Protocol::EVENTQUEUE, false, true, &RESTAPI_device_commandHandler::EventQueue, 30000ms },
{ RESTAPI::Protocol::TELEMETRY, false, true, &RESTAPI_device_commandHandler::Telemetry, 30000ms },
{ RESTAPI::Protocol::PING, false, true, &RESTAPI_device_commandHandler::Ping, 60000ms },
{ RESTAPI::Protocol::SCRIPT, false, true, &RESTAPI_device_commandHandler::Script, 300000ms }
};
if (Command_ == RESTAPI::Protocol::PERFORM) { for(const auto &Command:PostCommands) {
return ExecuteCommand(UUID,RPC); if(Command_==Command.Command) {
} else if (Command_ == RESTAPI::Protocol::CONFIGURE) { Poco::Thread::current()->setName(fmt::format("{}:{}:{}",Command.Command, TransactionId_,SerialNumber_));
return Configure(UUID,RPC); if(Command.RequireConnection && !DeviceRegistry()->Connected(SerialNumberInt_)) {
} else if (Command_ == RESTAPI::Protocol::UPGRADE) { CallCanceled(Command.Command, RESTAPI::Errors::DeviceNotConnected);
return Upgrade(UUID,RPC); return BadRequest(RESTAPI::Errors::DeviceNotConnected);
} else if (Command_ == RESTAPI::Protocol::REBOOT) { }
return Reboot(UUID,RPC); std::string Command_UUID, CommandName;
} else if (Command_ == RESTAPI::Protocol::FACTORY) { if(!Command.AllowParallel && CommandManager()->CommandRunningForDevice(SerialNumberInt_,Command_UUID,CommandName)) {
return Factory(UUID,RPC); auto Extra = fmt::format("UUID={} Command={}", Command_UUID, CommandName);
} else if (Command_ == RESTAPI::Protocol::LEDS) { CallCanceled(Command.Command, RESTAPI::Errors::DeviceIsAlreadyBusy, Extra);
return LEDs(UUID,RPC); return BadRequest(RESTAPI::Errors::DeviceIsAlreadyBusy, Extra);
} else if (Command_ == RESTAPI::Protocol::TRACE) { }
return Trace(UUID,RPC); auto UUID = MicroService::CreateUUID();
} else if (Command_ == RESTAPI::Protocol::REQUEST) { auto RPC = CommandManager()->NextRPCId();
return MakeRequest(UUID,RPC); poco_debug(Logger_,fmt::format("Command {} TID={} can proceed. Identified as {} and RPCID as {}. thr_id={}",
} else if (Command_ == RESTAPI::Protocol::WIFISCAN) { Command.Command, TransactionId_, UUID, RPC,
return WifiScan(UUID,RPC); Poco::Thread::current()->id()));
} else if (Command_ == RESTAPI::Protocol::EVENTQUEUE) { return (*this.*Command.funPtr)(UUID,RPC,Command.Timeout);
return EventQueue(UUID,RPC); }
} else if (Command_ == RESTAPI::Protocol::TELEMETRY) {
return Telemetry(UUID,RPC);
} else if (Command_ == RESTAPI::Protocol::PING) {
return Ping(UUID,RPC);
} else if (Command_ == RESTAPI::Protocol::SCRIPT) {
return Script(UUID,RPC);
} else {
return BadRequest(RESTAPI::Errors::InvalidCommand);
} }
return BadRequest(RESTAPI::Errors::InvalidCommand);
} }
void RESTAPI_device_commandHandler::GetCapabilities() { void RESTAPI_device_commandHandler::GetCapabilities() {
Logger_.information(fmt::format("GET-CAPABILITIES: TID={} user={} serial={}. thr_id={}",
TransactionId_, Requester(), SerialNumber_,
Poco::Thread::current()->id()));
GWObjects::Capabilities Caps; GWObjects::Capabilities Caps;
if (StorageService()->GetDeviceCapabilities(SerialNumber_, Caps)) { if (StorageService()->GetDeviceCapabilities(SerialNumber_, Caps)) {
Poco::JSON::Object RetObj; Poco::JSON::Object RetObj;
@@ -154,7 +201,9 @@ namespace OpenWifi {
} }
void RESTAPI_device_commandHandler::DeleteCapabilities() { void RESTAPI_device_commandHandler::DeleteCapabilities() {
Logger_.information(fmt::format("DELETE-CAPABILITIES: user={} serial={}", Requester(), SerialNumber_)); Logger_.information(fmt::format("DELETE-CAPABILITIES: TID={} user={} serial={}. thr_id={}",
TransactionId_, Requester(), SerialNumber_,
Poco::Thread::current()->id()));
if (StorageService()->DeleteDeviceCapabilities(SerialNumber_)) { if (StorageService()->DeleteDeviceCapabilities(SerialNumber_)) {
return OK(); return OK();
} }
@@ -162,6 +211,9 @@ namespace OpenWifi {
} }
void RESTAPI_device_commandHandler::GetStatistics() { void RESTAPI_device_commandHandler::GetStatistics() {
Logger_.information(fmt::format("GET-STATISTICS: TID={} user={} serial={}. thr_id={}",
TransactionId_, Requester(), SerialNumber_,
Poco::Thread::current()->id()));
if (QB_.LastOnly) { if (QB_.LastOnly) {
std::string Stats; std::string Stats;
if (DeviceRegistry()->GetStatistics(SerialNumber_, Stats)) { if (DeviceRegistry()->GetStatistics(SerialNumber_, Stats)) {
@@ -170,40 +222,144 @@ namespace OpenWifi {
Stats = uCentralProtocol::EMPTY_JSON_DOC; Stats = uCentralProtocol::EMPTY_JSON_DOC;
auto Obj = P.parse(Stats).extract<Poco::JSON::Object::Ptr>(); auto Obj = P.parse(Stats).extract<Poco::JSON::Object::Ptr>();
return ReturnObject(*Obj); return ReturnObject(*Obj);
} else {
return NotFound();
} }
} else { return NotFound();
std::vector<GWObjects::Statistics> Stats;
if (QB_.Newest) {
StorageService()->GetNewestStatisticsData(SerialNumber_, QB_.Limit, Stats);
} else {
StorageService()->GetStatisticsData(SerialNumber_, QB_.StartDate, QB_.EndDate,
QB_.Offset, QB_.Limit, Stats);
}
Poco::JSON::Array ArrayObj;
for (auto i : Stats) {
Poco::JSON::Object Obj;
i.to_json(Obj);
ArrayObj.add(Obj);
}
Poco::JSON::Object RetObj;
RetObj.set(RESTAPI::Protocol::DATA, ArrayObj);
RetObj.set(RESTAPI::Protocol::SERIALNUMBER, SerialNumber_);
return ReturnObject(RetObj);
} }
std::vector<GWObjects::Statistics> Stats;
if (QB_.Newest) {
StorageService()->GetNewestStatisticsData(SerialNumber_, QB_.Limit, Stats);
} else {
StorageService()->GetStatisticsData(SerialNumber_, QB_.StartDate, QB_.EndDate,
QB_.Offset, QB_.Limit, Stats);
}
Poco::JSON::Array ArrayObj;
for (const auto &i : Stats) {
Poco::JSON::Object Obj;
i.to_json(Obj);
ArrayObj.add(Obj);
}
Poco::JSON::Object RetObj;
RetObj.set(RESTAPI::Protocol::DATA, ArrayObj);
RetObj.set(RESTAPI::Protocol::SERIALNUMBER, SerialNumber_);
return ReturnObject(RetObj);
} }
void RESTAPI_device_commandHandler::DeleteStatistics() { void RESTAPI_device_commandHandler::DeleteStatistics() {
Logger_.information(fmt::format("DELETE-STATISTICS: user={} serial={}", Requester(), SerialNumber_)); Logger_.information(fmt::format("DELETE-STATISTICS: TID={} user={} serial={}. thr_id={}",
TransactionId_, Requester(), SerialNumber_,
Poco::Thread::current()->id()));
if (StorageService()->DeleteStatisticsData(SerialNumber_, QB_.StartDate, QB_.EndDate)) { if (StorageService()->DeleteStatisticsData(SerialNumber_, QB_.StartDate, QB_.EndDate)) {
return OK(); return OK();
} }
NotFound(); NotFound();
} }
void RESTAPI_device_commandHandler::Ping(const std::string &CMD_UUID, uint64_t CMD_RPC) { void RESTAPI_device_commandHandler::GetStatus() {
Logger_.information(fmt::format("PING({},{}): user={} serial={}", CMD_UUID, CMD_RPC, Requester(), SerialNumber_)); Logger_.information(fmt::format("GET-STATUS: TID={} user={} serial={}. thr_id={}",
TransactionId_, Requester(), SerialNumber_,
Poco::Thread::current()->id()));
GWObjects::ConnectionState State;
if (DeviceRegistry()->GetState(SerialNumber_, State)) {
Poco::JSON::Object RetObject;
State.to_json(RetObject);
return ReturnObject(RetObject);
} else {
Poco::JSON::Object RetObject;
RetObject.set("serialNumber", SerialNumber_);
RetObject.set("connected", false);
return ReturnObject(RetObject);
}
}
void RESTAPI_device_commandHandler::GetLogs() {
Logger_.information(fmt::format("GET-LOGS: TID={} user={} serial={}. thr_id={}",
TransactionId_, Requester(), SerialNumber_,
Poco::Thread::current()->id()));
std::vector<GWObjects::DeviceLog> Logs;
if (QB_.Newest) {
StorageService()->GetNewestLogData(SerialNumber_, QB_.Limit, Logs, QB_.LogType);
} else {
StorageService()->GetLogData(SerialNumber_, QB_.StartDate, QB_.EndDate, QB_.Offset,
QB_.Limit, Logs, QB_.LogType);
}
Poco::JSON::Array ArrayObj;
for (const auto &i : Logs) {
Poco::JSON::Object Obj;
i.to_json(Obj);
ArrayObj.add(Obj);
}
Poco::JSON::Object RetObj;
RetObj.set(RESTAPI::Protocol::VALUES, ArrayObj);
RetObj.set(RESTAPI::Protocol::SERIALNUMBER, SerialNumber_);
ReturnObject(RetObj);
}
void RESTAPI_device_commandHandler::DeleteLogs() {
Logger_.information(fmt::format("DELETE-LOGS: TID={} user={} serial={}. thr_id={}",
TransactionId_, Requester(), SerialNumber_,
Poco::Thread::current()->id()));
if (StorageService()->DeleteLogData(SerialNumber_, QB_.StartDate, QB_.EndDate,
QB_.LogType)) {
return OK();
}
BadRequest(RESTAPI::Errors::NoRecordsDeleted);
}
void RESTAPI_device_commandHandler::GetChecks() {
Logger_.information(fmt::format("GET-HEALTHCHECKS: TID={} user={} serial={}. thr_id={}",
TransactionId_, Requester(), SerialNumber_,
Poco::Thread::current()->id()));
std::vector<GWObjects::HealthCheck> Checks;
if (QB_.LastOnly) {
GWObjects::HealthCheck HC;
if (DeviceRegistry()->GetHealthcheck(SerialNumber_, HC)) {
Poco::JSON::Object Answer;
HC.to_json(Answer);
return ReturnObject(Answer);
} else {
return NotFound();
}
} else {
if (QB_.Newest) {
StorageService()->GetNewestHealthCheckData(SerialNumber_, QB_.Limit, Checks);
} else {
StorageService()->GetHealthCheckData(SerialNumber_, QB_.StartDate, QB_.EndDate,
QB_.Offset, QB_.Limit, Checks);
}
Poco::JSON::Array ArrayObj;
for (auto i : Checks) {
Poco::JSON::Object Obj;
i.to_json(Obj);
ArrayObj.add(Obj);
}
Poco::JSON::Object RetObj;
RetObj.set(RESTAPI::Protocol::VALUES, ArrayObj);
RetObj.set(RESTAPI::Protocol::SERIALNUMBER, SerialNumber_);
ReturnObject(RetObj);
}
}
void RESTAPI_device_commandHandler::DeleteChecks() {
Logger_.information(fmt::format("DELETE-HEALTHCHECKS: TID={} user={} serial={}. thr_id={}",
TransactionId_, Requester(), SerialNumber_,
Poco::Thread::current()->id()));
if (StorageService()->DeleteHealthCheckData(SerialNumber_, QB_.StartDate, QB_.EndDate)) {
return OK();
}
BadRequest(RESTAPI::Errors::NoRecordsDeleted);
}
void RESTAPI_device_commandHandler::Ping(const std::string &CMD_UUID, uint64_t CMD_RPC, std::chrono::milliseconds timeout) {
Logger_.information(fmt::format("PING({},{}): TID={} user={} serial={}", CMD_UUID, CMD_RPC, TransactionId_, Requester(), SerialNumber_));
const auto &Obj = ParsedBody_; const auto &Obj = ParsedBody_;
if (Obj->has(RESTAPI::Protocol::SERIALNUMBER)) { if (Obj->has(RESTAPI::Protocol::SERIALNUMBER)) {
auto SNum = Obj->get(RESTAPI::Protocol::SERIALNUMBER).toString(); auto SNum = Obj->get(RESTAPI::Protocol::SERIALNUMBER).toString();
@@ -215,7 +371,7 @@ namespace OpenWifi {
GWObjects::CommandDetails Cmd; GWObjects::CommandDetails Cmd;
Cmd.SerialNumber = SerialNumber_; Cmd.SerialNumber = SerialNumber_;
Cmd.UUID = CMD_UUID; Cmd.UUID = CMD_UUID;
Cmd.SubmittedBy = UserInfo_.webtoken.username_; Cmd.SubmittedBy = Requester();
Cmd.Command = uCentralProtocol::PING; Cmd.Command = uCentralProtocol::PING;
Cmd.RunAt = 0; Cmd.RunAt = 0;
@@ -226,7 +382,7 @@ namespace OpenWifi {
Params.stringify(ParamStream); Params.stringify(ParamStream);
Cmd.Details = ParamStream.str(); Cmd.Details = ParamStream.str();
RESTAPI_RPC::WaitForCommand(CMD_RPC,false,Cmd, Params, *Request, *Response, 60000ms, nullptr, nullptr, Logger_); RESTAPI_RPC::WaitForCommand(CMD_RPC,false,Cmd, Params, *Request, *Response, timeout, nullptr, nullptr, Logger_);
GWObjects::CommandDetails Cmd2; GWObjects::CommandDetails Cmd2;
if(StorageService()->GetCommand(CMD_UUID,Cmd2)) { if(StorageService()->GetCommand(CMD_UUID,Cmd2)) {
@@ -258,8 +414,8 @@ namespace OpenWifi {
Logger_.warning(fmt::format("{}({},{}): Canceled. Error:{} Reason:{}", Cmd, UUID, RPC, Err.err_num, Err.err_txt)); Logger_.warning(fmt::format("{}({},{}): Canceled. Error:{} Reason:{}", Cmd, UUID, RPC, Err.err_num, Err.err_txt));
} }
void RESTAPI_device_commandHandler::Script(const std::string &CMD_UUID, uint64_t CMD_RPC) { void RESTAPI_device_commandHandler::Script(const std::string &CMD_UUID, uint64_t CMD_RPC, std::chrono::milliseconds timeout) {
Logger_.information(fmt::format("SCRIPT({},{}): user={} serial={}", CMD_UUID, CMD_RPC, Requester(), SerialNumber_)); Logger_.information(fmt::format("SCRIPT({},{}): TID={} user={} serial={}", CMD_UUID, CMD_RPC, TransactionId_, Requester(), SerialNumber_));
if(!Internal_ && UserInfo_.userinfo.userRole!=SecurityObjects::ROOT) { if(!Internal_ && UserInfo_.userinfo.userRole!=SecurityObjects::ROOT) {
CallCanceled("SCRIPT", CMD_UUID, CMD_RPC,RESTAPI::Errors::ACCESS_DENIED); CallCanceled("SCRIPT", CMD_UUID, CMD_RPC,RESTAPI::Errors::ACCESS_DENIED);
return UnAuthorized(RESTAPI::Errors::ACCESS_DENIED); return UnAuthorized(RESTAPI::Errors::ACCESS_DENIED);
@@ -286,18 +442,18 @@ namespace OpenWifi {
return BadRequest(RESTAPI::Errors::SerialNumberMismatch); return BadRequest(RESTAPI::Errors::SerialNumberMismatch);
} }
uint64_t timeout = SCR.timeout==0 ? 30 : SCR.timeout; uint64_t ap_timeout = SCR.timeout==0 ? 30 : SCR.timeout;
GWObjects::CommandDetails Cmd; GWObjects::CommandDetails Cmd;
Cmd.SerialNumber = SerialNumber_; Cmd.SerialNumber = SerialNumber_;
Cmd.UUID = CMD_UUID; Cmd.UUID = CMD_UUID;
Cmd.SubmittedBy = UserInfo_.webtoken.username_; Cmd.SubmittedBy = Requester();
Cmd.Command = uCentralProtocol::SCRIPT; Cmd.Command = uCentralProtocol::SCRIPT;
Cmd.RunAt = 0; Cmd.RunAt = 0;
Poco::JSON::Object Params; Poco::JSON::Object Params;
Params.set(uCentralProtocol::SERIAL, SerialNumber_); Params.set(uCentralProtocol::SERIAL, SerialNumber_);
Params.set(uCentralProtocol::TIMEOUT, timeout); Params.set(uCentralProtocol::TIMEOUT, ap_timeout);
Params.set(uCentralProtocol::TYPE, SCR.type); Params.set(uCentralProtocol::TYPE, SCR.type);
Params.set(uCentralProtocol::SCRIPT, SCR.script); Params.set(uCentralProtocol::SCRIPT, SCR.script);
Params.set(uCentralProtocol::WHEN, SCR.when); Params.set(uCentralProtocol::WHEN, SCR.when);
@@ -306,26 +462,11 @@ namespace OpenWifi {
Params.stringify(ParamStream); Params.stringify(ParamStream);
Cmd.Details = ParamStream.str(); Cmd.Details = ParamStream.str();
return RESTAPI_RPC::WaitForCommand(CMD_RPC,false,Cmd, Params, *Request, *Response, 120000ms, nullptr, this, Logger_); return RESTAPI_RPC::WaitForCommand(CMD_RPC,false,Cmd, Params, *Request, *Response, timeout, nullptr, this, Logger_);
} }
void RESTAPI_device_commandHandler::GetStatus() { void RESTAPI_device_commandHandler::Configure(const std::string &CMD_UUID, uint64_t CMD_RPC, std::chrono::milliseconds timeout) {
GWObjects::ConnectionState State; Logger_.information(fmt::format("CONFIGURE({},{}): TID={} user={} serial={}", CMD_UUID, CMD_RPC, TransactionId_, Requester(), SerialNumber_));
if (DeviceRegistry()->GetState(SerialNumber_, State)) {
Poco::JSON::Object RetObject;
State.to_json(RetObject);
return ReturnObject(RetObject);
} else {
Poco::JSON::Object RetObject;
RetObject.set("serialNumber", SerialNumber_);
RetObject.set("connected", false);
return ReturnObject(RetObject);
}
}
void RESTAPI_device_commandHandler::Configure(const std::string &CMD_UUID, uint64_t CMD_RPC) {
Logger_.information(fmt::format("CONFIGURE({},{}): user={} serial={}", CMD_UUID, CMD_RPC, Requester(), SerialNumber_));
const auto &Obj = ParsedBody_; const auto &Obj = ParsedBody_;
if (Obj->has(RESTAPI::Protocol::SERIALNUMBER) && if (Obj->has(RESTAPI::Protocol::SERIALNUMBER) &&
@@ -353,7 +494,7 @@ namespace OpenWifi {
Cmd.SerialNumber = SerialNumber_; Cmd.SerialNumber = SerialNumber_;
Cmd.UUID = CMD_UUID; Cmd.UUID = CMD_UUID;
Cmd.SubmittedBy = UserInfo_.webtoken.username_; Cmd.SubmittedBy = Requester();
Cmd.Command = uCentralProtocol::CONFIGURE; Cmd.Command = uCentralProtocol::CONFIGURE;
Cmd.RunAt = When; Cmd.RunAt = When;
@@ -368,16 +509,16 @@ namespace OpenWifi {
Params.stringify(ParamStream); Params.stringify(ParamStream);
Cmd.Details = ParamStream.str(); Cmd.Details = ParamStream.str();
DeviceRegistry()->SetPendingUUID(SerialNumber_, NewUUID); // DeviceRegistry()->SetPendingUUID(SerialNumber_, NewUUID);
return RESTAPI_RPC::WaitForCommand(CMD_RPC,true,Cmd, Params, *Request, *Response, 60000ms, nullptr, this, Logger_); return RESTAPI_RPC::WaitForCommand(CMD_RPC,true,Cmd, Params, *Request, *Response, timeout, nullptr, this, Logger_);
} }
return BadRequest(RESTAPI::Errors::RecordNotUpdated); return BadRequest(RESTAPI::Errors::RecordNotUpdated);
} }
BadRequest(RESTAPI::Errors::MissingOrInvalidParameters); BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
} }
void RESTAPI_device_commandHandler::Upgrade(const std::string &CMD_UUID, uint64_t CMD_RPC) { void RESTAPI_device_commandHandler::Upgrade(const std::string &CMD_UUID, uint64_t CMD_RPC, std::chrono::milliseconds timeout) {
Logger_.information(fmt::format("UPGRADE({},{}): user={} serial={}", CMD_UUID, CMD_RPC, Requester(), SerialNumber_)); Logger_.information(fmt::format("UPGRADE({},{}): TID={} user={} serial={}", CMD_UUID, CMD_RPC, TransactionId_, Requester(), SerialNumber_));
const auto &Obj = ParsedBody_; const auto &Obj = ParsedBody_;
@@ -399,7 +540,7 @@ namespace OpenWifi {
Cmd.SerialNumber = SerialNumber_; Cmd.SerialNumber = SerialNumber_;
Cmd.UUID = CMD_UUID; Cmd.UUID = CMD_UUID;
Cmd.SubmittedBy = UserInfo_.webtoken.username_; Cmd.SubmittedBy = Requester();
Cmd.Command = uCentralProtocol::UPGRADE; Cmd.Command = uCentralProtocol::UPGRADE;
Cmd.RunAt = When; Cmd.RunAt = When;
@@ -414,85 +555,14 @@ namespace OpenWifi {
Params.stringify(ParamStream); Params.stringify(ParamStream);
Cmd.Details = ParamStream.str(); Cmd.Details = ParamStream.str();
return RESTAPI_RPC::WaitForCommand(CMD_RPC,true,Cmd,Params, *Request, *Response, 60000ms, nullptr, this, Logger_); return RESTAPI_RPC::WaitForCommand(CMD_RPC,true,Cmd,Params, *Request, *Response, timeout, nullptr, this, Logger_);
} }
BadRequest(RESTAPI::Errors::MissingOrInvalidParameters); BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
} }
void RESTAPI_device_commandHandler::GetLogs() {
std::vector<GWObjects::DeviceLog> Logs;
if (QB_.Newest) {
StorageService()->GetNewestLogData(SerialNumber_, QB_.Limit, Logs, QB_.LogType);
} else {
StorageService()->GetLogData(SerialNumber_, QB_.StartDate, QB_.EndDate, QB_.Offset,
QB_.Limit, Logs, QB_.LogType);
}
Poco::JSON::Array ArrayObj; void RESTAPI_device_commandHandler::ExecuteCommand(const std::string &CMD_UUID, uint64_t CMD_RPC, std::chrono::milliseconds timeout) {
for (auto i : Logs) { Logger_.information(fmt::format("EXECUTE({},{}): TID={} user={} serial={}", CMD_UUID, CMD_RPC, TransactionId_, Requester(), SerialNumber_));
Poco::JSON::Object Obj;
i.to_json(Obj);
ArrayObj.add(Obj);
}
Poco::JSON::Object RetObj;
RetObj.set(RESTAPI::Protocol::VALUES, ArrayObj);
RetObj.set(RESTAPI::Protocol::SERIALNUMBER, SerialNumber_);
ReturnObject(RetObj);
}
void RESTAPI_device_commandHandler::DeleteLogs() {
Logger_.information(fmt::format("DELETE-LOGS: user={} serial={}", Requester(), SerialNumber_));
if (StorageService()->DeleteLogData(SerialNumber_, QB_.StartDate, QB_.EndDate,
QB_.LogType)) {
return OK();
}
BadRequest(RESTAPI::Errors::NoRecordsDeleted);
}
void RESTAPI_device_commandHandler::GetChecks() {
std::vector<GWObjects::HealthCheck> Checks;
if (QB_.LastOnly) {
GWObjects::HealthCheck HC;
if (DeviceRegistry()->GetHealthcheck(SerialNumber_, HC)) {
Poco::JSON::Object Answer;
HC.to_json(Answer);
return ReturnObject(Answer);
} else {
return NotFound();
}
} else {
if (QB_.Newest) {
StorageService()->GetNewestHealthCheckData(SerialNumber_, QB_.Limit, Checks);
} else {
StorageService()->GetHealthCheckData(SerialNumber_, QB_.StartDate, QB_.EndDate,
QB_.Offset, QB_.Limit, Checks);
}
Poco::JSON::Array ArrayObj;
for (auto i : Checks) {
Poco::JSON::Object Obj;
i.to_json(Obj);
ArrayObj.add(Obj);
}
Poco::JSON::Object RetObj;
RetObj.set(RESTAPI::Protocol::VALUES, ArrayObj);
RetObj.set(RESTAPI::Protocol::SERIALNUMBER, SerialNumber_);
ReturnObject(RetObj);
}
}
void RESTAPI_device_commandHandler::DeleteChecks() {
Logger_.information(fmt::format("DELETE-HEALTHCHECKS: user={} serial={}", Requester(), SerialNumber_));
if (StorageService()->DeleteHealthCheckData(SerialNumber_, QB_.StartDate, QB_.EndDate)) {
return OK();
}
BadRequest(RESTAPI::Errors::NoRecordsDeleted);
}
void RESTAPI_device_commandHandler::ExecuteCommand(const std::string &CMD_UUID, uint64_t CMD_RPC) {
Logger_.information(fmt::format("EXECUTE({},{}): user={} serial={}", CMD_UUID, CMD_RPC, Requester(), SerialNumber_));
const auto &Obj = ParsedBody_; const auto &Obj = ParsedBody_;
if (Obj->has(RESTAPI::Protocol::COMMAND) && if (Obj->has(RESTAPI::Protocol::COMMAND) &&
@@ -513,7 +583,7 @@ namespace OpenWifi {
Cmd.SerialNumber = SerialNumber_; Cmd.SerialNumber = SerialNumber_;
Cmd.UUID = CMD_UUID; Cmd.UUID = CMD_UUID;
Cmd.SubmittedBy = UserInfo_.webtoken.username_; Cmd.SubmittedBy = Requester();
Cmd.Command = Command; Cmd.Command = Command;
Cmd.Custom = 1; Cmd.Custom = 1;
Cmd.RunAt = When; Cmd.RunAt = When;
@@ -534,13 +604,13 @@ namespace OpenWifi {
Params.stringify(ParamStream); Params.stringify(ParamStream);
Cmd.Details = ParamStream.str(); Cmd.Details = ParamStream.str();
return RESTAPI_RPC::WaitForCommand(CMD_RPC,false,Cmd, Params, *Request, *Response, 60000ms, nullptr, this, Logger_); return RESTAPI_RPC::WaitForCommand(CMD_RPC,false,Cmd, Params, *Request, *Response, timeout, nullptr, this, Logger_);
} }
BadRequest(RESTAPI::Errors::MissingOrInvalidParameters); BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
} }
void RESTAPI_device_commandHandler::Reboot(const std::string &CMD_UUID, uint64_t CMD_RPC) { void RESTAPI_device_commandHandler::Reboot(const std::string &CMD_UUID, uint64_t CMD_RPC, std::chrono::milliseconds timeout) {
Logger_.information(fmt::format("REBOOT({},{}): user={} serial={}", CMD_UUID, CMD_RPC, Requester(), SerialNumber_)); Logger_.information(fmt::format("REBOOT({},{}): TID={} user={} serial={}", CMD_UUID, CMD_RPC, TransactionId_, Requester(), SerialNumber_));
const auto &Obj = ParsedBody_; const auto &Obj = ParsedBody_;
@@ -551,16 +621,11 @@ namespace OpenWifi {
return BadRequest(RESTAPI::Errors::SerialNumberMismatch); return BadRequest(RESTAPI::Errors::SerialNumberMismatch);
} }
if(!DeviceRegistry()->Connected(SerialNumber_)) {
CallCanceled("REBOOT", CMD_UUID, CMD_RPC,RESTAPI::Errors::DeviceNotConnected);
return BadRequest(RESTAPI::Errors::DeviceNotConnected);
}
uint64_t When = GetWhen(Obj); uint64_t When = GetWhen(Obj);
GWObjects::CommandDetails Cmd; GWObjects::CommandDetails Cmd;
Cmd.SerialNumber = SerialNumber_; Cmd.SerialNumber = SerialNumber_;
Cmd.UUID = CMD_UUID; Cmd.UUID = CMD_UUID;
Cmd.SubmittedBy = UserInfo_.webtoken.username_; Cmd.SubmittedBy = Requester();
Cmd.Command = uCentralProtocol::REBOOT; Cmd.Command = uCentralProtocol::REBOOT;
Cmd.RunAt = When; Cmd.RunAt = When;
@@ -573,13 +638,13 @@ namespace OpenWifi {
Params.stringify(ParamStream); Params.stringify(ParamStream);
Cmd.Details = ParamStream.str(); Cmd.Details = ParamStream.str();
return RESTAPI_RPC::WaitForCommand(CMD_RPC,false,Cmd, Params, *Request, *Response, 60000ms, nullptr, this, Logger_); return RESTAPI_RPC::WaitForCommand(CMD_RPC,false,Cmd, Params, *Request, *Response, timeout, nullptr, this, Logger_);
} }
BadRequest(RESTAPI::Errors::MissingSerialNumber); BadRequest(RESTAPI::Errors::MissingSerialNumber);
} }
void RESTAPI_device_commandHandler::Factory(const std::string &CMD_UUID, uint64_t CMD_RPC) { void RESTAPI_device_commandHandler::Factory(const std::string &CMD_UUID, uint64_t CMD_RPC, std::chrono::milliseconds timeout) {
Logger_.information(fmt::format("FACTORY-RESET({},{}): user={} serial={}", CMD_UUID, CMD_RPC, Requester(), SerialNumber_)); Logger_.information(fmt::format("FACTORY-RESET({},{}): TID={} user={} serial={}", CMD_UUID, CMD_RPC, TransactionId_, Requester(), SerialNumber_));
const auto &Obj = ParsedBody_; const auto &Obj = ParsedBody_;
if (Obj->has(RESTAPI::Protocol::KEEPREDIRECTOR) && if (Obj->has(RESTAPI::Protocol::KEEPREDIRECTOR) &&
@@ -599,7 +664,7 @@ namespace OpenWifi {
Cmd.SerialNumber = SerialNumber_; Cmd.SerialNumber = SerialNumber_;
Cmd.UUID = CMD_UUID; Cmd.UUID = CMD_UUID;
Cmd.SubmittedBy = UserInfo_.webtoken.username_; Cmd.SubmittedBy = Requester();
Cmd.Command = uCentralProtocol::FACTORY; Cmd.Command = uCentralProtocol::FACTORY;
Cmd.RunAt = When; Cmd.RunAt = When;
@@ -613,13 +678,13 @@ namespace OpenWifi {
Params.stringify(ParamStream); Params.stringify(ParamStream);
Cmd.Details = ParamStream.str(); Cmd.Details = ParamStream.str();
return RESTAPI_RPC::WaitForCommand(CMD_RPC,true,Cmd, Params, *Request, *Response, 60000ms, nullptr, this, Logger_); return RESTAPI_RPC::WaitForCommand(CMD_RPC,true,Cmd, Params, *Request, *Response, timeout, nullptr, this, Logger_);
} }
BadRequest(RESTAPI::Errors::MissingOrInvalidParameters); BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
} }
void RESTAPI_device_commandHandler::LEDs(const std::string &CMD_UUID, uint64_t CMD_RPC) { void RESTAPI_device_commandHandler::LEDs(const std::string &CMD_UUID, uint64_t CMD_RPC, std::chrono::milliseconds timeout) {
Logger_.information(fmt::format("LEDS({},{}): user={} serial={}", CMD_UUID, CMD_RPC, Requester(), SerialNumber_)); Logger_.information(fmt::format("LEDS({},{}): TID={} user={} serial={}", CMD_UUID, CMD_RPC, TransactionId_, Requester(), SerialNumber_));
const auto &Obj = ParsedBody_; const auto &Obj = ParsedBody_;
@@ -632,11 +697,6 @@ namespace OpenWifi {
return BadRequest(RESTAPI::Errors::SerialNumberMismatch); return BadRequest(RESTAPI::Errors::SerialNumberMismatch);
} }
if(!DeviceRegistry()->Connected(SerialNumber_)) {
CallCanceled("LEDS", CMD_UUID, CMD_RPC,RESTAPI::Errors::DeviceNotConnected);
return BadRequest(RESTAPI::Errors::DeviceNotConnected);
}
auto Pattern = auto Pattern =
GetS(uCentralProtocol::PATTERN, Obj, uCentralProtocol::BLINK); GetS(uCentralProtocol::PATTERN, Obj, uCentralProtocol::BLINK);
if (Pattern != uCentralProtocol::ON && if (Pattern != uCentralProtocol::ON &&
@@ -652,7 +712,7 @@ namespace OpenWifi {
Cmd.SerialNumber = SerialNumber_; Cmd.SerialNumber = SerialNumber_;
Cmd.UUID = CMD_UUID; Cmd.UUID = CMD_UUID;
Cmd.SubmittedBy = UserInfo_.webtoken.username_; Cmd.SubmittedBy = Requester();
Cmd.Command = uCentralProtocol::LEDS; Cmd.Command = uCentralProtocol::LEDS;
Cmd.RunAt = When; Cmd.RunAt = When;
Poco::JSON::Object Params; Poco::JSON::Object Params;
@@ -666,13 +726,13 @@ namespace OpenWifi {
Params.stringify(ParamStream); Params.stringify(ParamStream);
Cmd.Details = ParamStream.str(); Cmd.Details = ParamStream.str();
return RESTAPI_RPC::WaitForCommand(CMD_RPC,false,Cmd, Params, *Request, *Response, 60000ms, nullptr, this, Logger_); return RESTAPI_RPC::WaitForCommand(CMD_RPC,false,Cmd, Params, *Request, *Response, timeout, nullptr, this, Logger_);
} }
BadRequest(RESTAPI::Errors::MissingOrInvalidParameters); BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
} }
void RESTAPI_device_commandHandler::Trace(const std::string &CMD_UUID, uint64_t CMD_RPC) { void RESTAPI_device_commandHandler::Trace(const std::string &CMD_UUID, uint64_t CMD_RPC, std::chrono::milliseconds timeout) {
Logger_.information(fmt::format("TRACE({},{}): user={} serial={}", CMD_UUID, CMD_RPC, Requester(), SerialNumber_)); Logger_.information(fmt::format("TRACE({},{}): TID={} user={} serial={}", CMD_UUID, CMD_RPC, TransactionId_, Requester(), SerialNumber_));
const auto &Obj = ParsedBody_; const auto &Obj = ParsedBody_;
@@ -686,11 +746,6 @@ namespace OpenWifi {
return BadRequest(RESTAPI::Errors::SerialNumberMismatch); return BadRequest(RESTAPI::Errors::SerialNumberMismatch);
} }
if(!DeviceRegistry()->Connected(SerialNumber_)) {
CallCanceled("TRACE", CMD_UUID, CMD_RPC,RESTAPI::Errors::DeviceNotConnected);
return BadRequest(RESTAPI::Errors::DeviceNotConnected);
}
auto Network = GetS(RESTAPI::Protocol::NETWORK, Obj); auto Network = GetS(RESTAPI::Protocol::NETWORK, Obj);
auto Interface = GetS(RESTAPI::Protocol::INTERFACE, Obj); auto Interface = GetS(RESTAPI::Protocol::INTERFACE, Obj);
auto URI = FileUploader()->FullName() + CMD_UUID; auto URI = FileUploader()->FullName() + CMD_UUID;
@@ -698,7 +753,7 @@ namespace OpenWifi {
GWObjects::CommandDetails Cmd; GWObjects::CommandDetails Cmd;
Cmd.SerialNumber = SerialNumber_; Cmd.SerialNumber = SerialNumber_;
Cmd.UUID = CMD_UUID; Cmd.UUID = CMD_UUID;
Cmd.SubmittedBy = UserInfo_.webtoken.username_; Cmd.SubmittedBy = Requester();
Cmd.Command = uCentralProtocol::TRACE; Cmd.Command = uCentralProtocol::TRACE;
Cmd.RunAt = 0; Cmd.RunAt = 0;
Cmd.WaitingForFile = 1; Cmd.WaitingForFile = 1;
@@ -724,13 +779,13 @@ namespace OpenWifi {
Cmd.Details = ParamStream.str(); Cmd.Details = ParamStream.str();
FileUploader()->AddUUID(CMD_UUID); FileUploader()->AddUUID(CMD_UUID);
return RESTAPI_RPC::WaitForCommand(CMD_RPC,false,Cmd, Params, *Request, *Response, 160000ms, nullptr, this, Logger_); return RESTAPI_RPC::WaitForCommand(CMD_RPC,false,Cmd, Params, *Request, *Response, timeout, nullptr, this, Logger_);
} }
BadRequest(RESTAPI::Errors::MissingOrInvalidParameters); BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
} }
void RESTAPI_device_commandHandler::WifiScan(const std::string &CMD_UUID, uint64_t CMD_RPC) { void RESTAPI_device_commandHandler::WifiScan(const std::string &CMD_UUID, uint64_t CMD_RPC, std::chrono::milliseconds timeout) {
Logger_.information(fmt::format("WIFISCAN({},{}): user={} serial={}", CMD_UUID, CMD_RPC, Requester(), SerialNumber_)); Logger_.information(fmt::format("WIFISCAN({},{}): TID={} user={} serial={}", CMD_UUID, CMD_RPC, TransactionId_, Requester(), SerialNumber_));
const auto &Obj = ParsedBody_; const auto &Obj = ParsedBody_;
auto SNum = Obj->get(RESTAPI::Protocol::SERIALNUMBER).toString(); auto SNum = Obj->get(RESTAPI::Protocol::SERIALNUMBER).toString();
@@ -739,11 +794,6 @@ namespace OpenWifi {
return BadRequest(RESTAPI::Errors::SerialNumberMismatch); return BadRequest(RESTAPI::Errors::SerialNumberMismatch);
} }
if(!DeviceRegistry()->Connected(SerialNumber_)) {
CallCanceled("WIFISCAN", CMD_UUID, CMD_RPC,RESTAPI::Errors::DeviceNotConnected);
return BadRequest(RESTAPI::Errors::DeviceNotConnected);
}
bool OverrideDFS = GetB(RESTAPI::Protocol::OVERRIDEDFS, Obj, true); bool OverrideDFS = GetB(RESTAPI::Protocol::OVERRIDEDFS, Obj, true);
bool ActiveScan = GetB(RESTAPI::Protocol::ACTIVESCAN, Obj, false); bool ActiveScan = GetB(RESTAPI::Protocol::ACTIVESCAN, Obj, false);
uint64_t Bandwidth = Get(RESTAPI::Protocol::BANDWIDTH, Obj, (uint64_t) 0); uint64_t Bandwidth = Get(RESTAPI::Protocol::BANDWIDTH, Obj, (uint64_t) 0);
@@ -757,7 +807,7 @@ namespace OpenWifi {
Cmd.SerialNumber = SerialNumber_; Cmd.SerialNumber = SerialNumber_;
Cmd.UUID = CMD_UUID; Cmd.UUID = CMD_UUID;
Cmd.SubmittedBy = UserInfo_.webtoken.username_; Cmd.SubmittedBy = Requester();
Cmd.Command = uCentralProtocol::WIFISCAN; Cmd.Command = uCentralProtocol::WIFISCAN;
Poco::JSON::Object Params; Poco::JSON::Object Params;
@@ -773,14 +823,14 @@ namespace OpenWifi {
std::stringstream ParamStream; std::stringstream ParamStream;
Params.stringify(ParamStream); Params.stringify(ParamStream);
Cmd.Details = ParamStream.str(); Cmd.Details = ParamStream.str();
RESTAPI_RPC::WaitForCommand(CMD_RPC,false,Cmd, Params, *Request, *Response, 120000ms, nullptr, this, Logger_); RESTAPI_RPC::WaitForCommand(CMD_RPC,false,Cmd, Params, *Request, *Response, timeout, nullptr, this, Logger_);
if (Cmd.ErrorCode == 0) { if (Cmd.ErrorCode == 0) {
KafkaManager()->PostMessage(KafkaTopics::WIFISCAN, SerialNumber_, Cmd.Results); KafkaManager()->PostMessage(KafkaTopics::WIFISCAN, SerialNumber_, Cmd.Results);
} }
} }
void RESTAPI_device_commandHandler::EventQueue(const std::string &CMD_UUID, uint64_t CMD_RPC) { void RESTAPI_device_commandHandler::EventQueue(const std::string &CMD_UUID, uint64_t CMD_RPC, std::chrono::milliseconds timeout) {
Logger_.information(fmt::format("EVENT-QUEUE({},{}): user={} serial={}", CMD_UUID, CMD_RPC, Requester(), SerialNumber_)); Logger_.information(fmt::format("EVENT-QUEUE({},{}): TID={} user={} serial={}", CMD_UUID, CMD_RPC, TransactionId_, Requester(), SerialNumber_));
const auto &Obj = ParsedBody_; const auto &Obj = ParsedBody_;
if (Obj->has(RESTAPI::Protocol::SERIALNUMBER) && if (Obj->has(RESTAPI::Protocol::SERIALNUMBER) &&
@@ -792,17 +842,12 @@ namespace OpenWifi {
return BadRequest(RESTAPI::Errors::SerialNumberMismatch); return BadRequest(RESTAPI::Errors::SerialNumberMismatch);
} }
if(!DeviceRegistry()->Connected(SerialNumber_)) {
CallCanceled("EVENT-QUEUE", CMD_UUID, CMD_RPC,RESTAPI::Errors::DeviceNotConnected);
return BadRequest(RESTAPI::Errors::DeviceNotConnected);
}
auto Types = Obj->getArray(RESTAPI::Protocol::TYPES); auto Types = Obj->getArray(RESTAPI::Protocol::TYPES);
GWObjects::CommandDetails Cmd; GWObjects::CommandDetails Cmd;
Cmd.SerialNumber = SerialNumber_; Cmd.SerialNumber = SerialNumber_;
Cmd.UUID = CMD_UUID; Cmd.UUID = CMD_UUID;
Cmd.SubmittedBy = UserInfo_.webtoken.username_; Cmd.SubmittedBy = Requester();
Cmd.Command = uCentralProtocol::EVENT; Cmd.Command = uCentralProtocol::EVENT;
Poco::JSON::Object Params; Poco::JSON::Object Params;
@@ -813,7 +858,7 @@ namespace OpenWifi {
Params.stringify(ParamStream); Params.stringify(ParamStream);
Cmd.Details = ParamStream.str(); Cmd.Details = ParamStream.str();
RESTAPI_RPC::WaitForCommand(CMD_RPC,false,Cmd, Params, *Request, *Response, 60000ms, nullptr, this, Logger_); RESTAPI_RPC::WaitForCommand(CMD_RPC,false,Cmd, Params, *Request, *Response, timeout, nullptr, this, Logger_);
if(Cmd.ErrorCode==0) { if(Cmd.ErrorCode==0) {
KafkaManager()->PostMessage(KafkaTopics::DEVICE_EVENT_QUEUE, SerialNumber_, KafkaManager()->PostMessage(KafkaTopics::DEVICE_EVENT_QUEUE, SerialNumber_,
Cmd.Results); Cmd.Results);
@@ -823,8 +868,8 @@ namespace OpenWifi {
BadRequest(RESTAPI::Errors::MissingOrInvalidParameters); BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
} }
void RESTAPI_device_commandHandler::MakeRequest(const std::string &CMD_UUID, uint64_t CMD_RPC) { void RESTAPI_device_commandHandler::MakeRequest(const std::string &CMD_UUID, uint64_t CMD_RPC, std::chrono::milliseconds timeout) {
Logger_.information(fmt::format("FORCE-REQUEST({},{}): user={} serial={}", CMD_UUID, CMD_RPC, Requester(), SerialNumber_)); Logger_.information(fmt::format("FORCE-REQUEST({},{}): TID={} user={} serial={}", CMD_UUID, CMD_RPC, TransactionId_, Requester(), SerialNumber_));
const auto &Obj = ParsedBody_; const auto &Obj = ParsedBody_;
if (Obj->has(RESTAPI::Protocol::SERIALNUMBER) && if (Obj->has(RESTAPI::Protocol::SERIALNUMBER) &&
@@ -840,16 +885,11 @@ namespace OpenWifi {
return BadRequest(RESTAPI::Errors::MissingOrInvalidParameters); return BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
} }
if(!DeviceRegistry()->Connected(SerialNumber_)) {
CallCanceled("FORCE-REQUEST", CMD_UUID, CMD_RPC,RESTAPI::Errors::DeviceNotConnected);
return BadRequest(RESTAPI::Errors::DeviceNotConnected);
}
auto When = GetWhen(Obj); auto When = GetWhen(Obj);
GWObjects::CommandDetails Cmd; GWObjects::CommandDetails Cmd;
Cmd.SerialNumber = SerialNumber_; Cmd.SerialNumber = SerialNumber_;
Cmd.SubmittedBy = UserInfo_.webtoken.username_; Cmd.SubmittedBy = Requester();
Cmd.UUID = CMD_UUID; Cmd.UUID = CMD_UUID;
Cmd.Command = uCentralProtocol::REQUEST; Cmd.Command = uCentralProtocol::REQUEST;
Cmd.RunAt = When; Cmd.RunAt = When;
@@ -865,24 +905,22 @@ namespace OpenWifi {
Params.stringify(ParamStream); Params.stringify(ParamStream);
Cmd.Details = ParamStream.str(); Cmd.Details = ParamStream.str();
return RESTAPI_RPC::WaitForCommand(CMD_RPC,false,Cmd, Params, *Request, *Response, 60000ms, nullptr, this, Logger_ ); return RESTAPI_RPC::WaitForCommand(CMD_RPC,false,Cmd, Params, *Request, *Response, timeout, nullptr, this, Logger_ );
} }
BadRequest(RESTAPI::Errors::MissingOrInvalidParameters); BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
} }
void RESTAPI_device_commandHandler::Rtty(const std::string &CMD_UUID, uint64_t CMD_RPC) { void RESTAPI_device_commandHandler::Rtty(const std::string &CMD_UUID, uint64_t CMD_RPC, std::chrono::milliseconds timeout) {
Logger_.information(fmt::format("RTTY({},{}): user={} serial={}", CMD_UUID, CMD_RPC, Requester(), SerialNumber_)); Logger_.information(fmt::format("RTTY({},{}): TID={} user={} serial={}", CMD_UUID, CMD_RPC, TransactionId_, Requester(), SerialNumber_));
if(!DeviceRegistry()->Connected(SerialNumber_)) {
CallCanceled("RTTY", CMD_UUID, CMD_RPC,RESTAPI::Errors::DeviceNotConnected);
return BadRequest(RESTAPI::Errors::DeviceNotConnected);
}
poco_debug(Logger_,fmt::format("RTTY_DEBUG {} ", __LINE__ ));
if (MicroService::instance().ConfigGetBool("rtty.enabled", false)) { if (MicroService::instance().ConfigGetBool("rtty.enabled", false)) {
GWObjects::Device Device; GWObjects::Device Device;
poco_debug(Logger_,fmt::format("RTTY_DEBUG {} ", __LINE__ ));
if (StorageService()->GetDevice(SerialNumber_, Device)) { if (StorageService()->GetDevice(SerialNumber_, Device)) {
poco_debug(Logger_,fmt::format("RTTY_DEBUG {} ", __LINE__ ));
GWObjects::RttySessionDetails Rtty{ GWObjects::RttySessionDetails Rtty{
.SerialNumber = SerialNumber_, .SerialNumber = SerialNumber_,
.Server = MicroService::instance().ConfigGetString("rtty.server", "localhost"), .Server = MicroService::instance().ConfigGetString("rtty.server", "localhost"),
@@ -895,14 +933,19 @@ namespace OpenWifi {
.ViewPort = MicroService::instance().ConfigGetInt("rtty.viewport", 5913), .ViewPort = MicroService::instance().ConfigGetInt("rtty.viewport", 5913),
.DevicePassword = "" .DevicePassword = ""
}; };
poco_debug(Logger_,fmt::format("RTTY_DEBUG {} ", __LINE__ ));
if(RTTYS_server()->UseInternal()) { if(RTTYS_server()->UseInternal()) {
// Rtty.Token = MicroService::instance().CreateHash(UserInfo_.webtoken.refresh_token_ + std::to_string(OpenWifi::Now())).substr(0,32); poco_debug(Logger_,fmt::format("RTTY_DEBUG {} ", __LINE__ ));
Rtty.Token = Utils::ComputeHash(UserInfo_.webtoken.refresh_token_,OpenWifi::Now()).substr(0,32); Rtty.Token = Utils::ComputeHash(UserInfo_.webtoken.refresh_token_,OpenWifi::Now()).substr(0,32);
poco_debug(Logger_,fmt::format("RTTY_DEBUG {} ", __LINE__ ));
if(!RTTYS_server()->CreateEndPoint(Rtty.ConnectionId, Rtty.Token, Requester(), SerialNumber_)) { if(!RTTYS_server()->CreateEndPoint(Rtty.ConnectionId, Rtty.Token, Requester(), SerialNumber_)) {
poco_debug(Logger_,fmt::format("RTTY_DEBUG {} ", __LINE__ ));
return BadRequest(RESTAPI::Errors::MaximumRTTYSessionsReached); return BadRequest(RESTAPI::Errors::MaximumRTTYSessionsReached);
} }
poco_debug(Logger_,fmt::format("RTTY_DEBUG {} ", __LINE__ ));
} }
poco_debug(Logger_,fmt::format("RTTY_DEBUG {} ", __LINE__ ));
Poco::JSON::Object ReturnedObject; Poco::JSON::Object ReturnedObject;
Rtty.to_json(ReturnedObject); Rtty.to_json(ReturnedObject);
@@ -910,10 +953,11 @@ namespace OpenWifi {
// let's create the command for this request // let's create the command for this request
GWObjects::CommandDetails Cmd; GWObjects::CommandDetails Cmd;
Cmd.SerialNumber = SerialNumber_; Cmd.SerialNumber = SerialNumber_;
Cmd.SubmittedBy = UserInfo_.webtoken.username_; Cmd.SubmittedBy = Requester();
Cmd.UUID = CMD_UUID; Cmd.UUID = CMD_UUID;
Cmd.Command = uCentralProtocol::RTTY; Cmd.Command = uCentralProtocol::RTTY;
poco_debug(Logger_,fmt::format("RTTY_DEBUG {} ", __LINE__ ));
Poco::JSON::Object Params; Poco::JSON::Object Params;
Params.set(uCentralProtocol::METHOD, uCentralProtocol::RTTY); Params.set(uCentralProtocol::METHOD, uCentralProtocol::RTTY);
@@ -926,11 +970,16 @@ namespace OpenWifi {
Params.set(uCentralProtocol::TIMEOUT, Rtty.TimeOut); Params.set(uCentralProtocol::TIMEOUT, Rtty.TimeOut);
Params.set(uCentralProtocol::PASSWORD, Device.DevicePassword); Params.set(uCentralProtocol::PASSWORD, Device.DevicePassword);
poco_debug(Logger_,fmt::format("RTTY_DEBUG {} ", __LINE__ ));
std::stringstream ParamStream; std::stringstream ParamStream;
poco_debug(Logger_,fmt::format("RTTY_DEBUG {} ", __LINE__ ));
Params.stringify(ParamStream); Params.stringify(ParamStream);
poco_debug(Logger_,fmt::format("RTTY_DEBUG {} ", __LINE__ ));
Cmd.Details = ParamStream.str(); Cmd.Details = ParamStream.str();
poco_debug(Logger_,fmt::format("RTTY_DEBUG {} ", __LINE__ ));
Logger_.information(fmt::format("RTTY: user={} serial={} rttyid={} token={} cmd={}.", Requester(), SerialNumber_, Rtty.ConnectionId, Rtty.Token, CMD_UUID)); Logger_.information(fmt::format("RTTY: user={} serial={} rttyid={} token={} cmd={}.", Requester(), SerialNumber_, Rtty.ConnectionId, Rtty.Token, CMD_UUID));
return RESTAPI_RPC::WaitForCommand(CMD_RPC,false,Cmd, Params, *Request, *Response, 60000ms, &ReturnedObject, this, Logger_); poco_debug(Logger_,fmt::format("RTTY_DEBUG {} ", __LINE__ ));
return RESTAPI_RPC::WaitForCommand(CMD_RPC,false,Cmd, Params, *Request, *Response, timeout, &ReturnedObject, this, Logger_);
} }
return NotFound(); return NotFound();
} }
@@ -938,8 +987,8 @@ namespace OpenWifi {
return ReturnStatus(Poco::Net::HTTPResponse::HTTP_SERVICE_UNAVAILABLE); return ReturnStatus(Poco::Net::HTTPResponse::HTTP_SERVICE_UNAVAILABLE);
} }
void RESTAPI_device_commandHandler::Telemetry(const std::string &CMD_UUID, uint64_t CMD_RPC){ void RESTAPI_device_commandHandler::Telemetry(const std::string &CMD_UUID, uint64_t CMD_RPC, [[maybe_unused]] std::chrono::milliseconds timeout){
Logger_.information(fmt::format("TELEMETRY({},{}): user={} serial={}", CMD_UUID, CMD_RPC, Requester(), SerialNumber_)); Logger_.information(fmt::format("TELEMETRY({},{}): TID={} user={} serial={}", CMD_UUID, CMD_RPC, TransactionId_, Requester(), SerialNumber_));
const auto &Obj = ParsedBody_; const auto &Obj = ParsedBody_;
if (Obj->has(RESTAPI::Protocol::SERIALNUMBER) && if (Obj->has(RESTAPI::Protocol::SERIALNUMBER) &&
@@ -952,11 +1001,6 @@ namespace OpenWifi {
return BadRequest(RESTAPI::Errors::SerialNumberMismatch); return BadRequest(RESTAPI::Errors::SerialNumberMismatch);
} }
if (!DeviceRegistry()->Connected(SerialNumber_)) {
CallCanceled("TELEMETRY", CMD_UUID, CMD_RPC,RESTAPI::Errors::DeviceNotConnected);
return BadRequest(RESTAPI::Errors::DeviceNotConnected);
}
std::stringstream oooss; std::stringstream oooss;
Obj->stringify(oooss); Obj->stringify(oooss);
// std::cout << "Payload:" << oooss.str() << std::endl; // std::cout << "Payload:" << oooss.str() << std::endl;
@@ -981,16 +1025,16 @@ namespace OpenWifi {
if(!StatusOnly) { if(!StatusOnly) {
if (KafkaOnly) { if (KafkaOnly) {
if (Interval) { if (Interval) {
DeviceRegistry()->SetKafkaTelemetryReporting(IntSerialNumber, Interval, Lifetime); DeviceRegistry()->SetKafkaTelemetryReporting(CMD_RPC,IntSerialNumber, Interval, Lifetime);
Answer.set("action", "Kafka telemetry started."); Answer.set("action", "Kafka telemetry started.");
Answer.set("uuid", CMD_UUID); Answer.set("uuid", CMD_UUID);
} else { } else {
DeviceRegistry()->StopKafkaTelemetry(IntSerialNumber); DeviceRegistry()->StopKafkaTelemetry(CMD_RPC,IntSerialNumber);
Answer.set("action", "Kafka telemetry stopped."); Answer.set("action", "Kafka telemetry stopped.");
} }
} else { } else {
if (Interval) { if (Interval) {
DeviceRegistry()->SetWebSocketTelemetryReporting(IntSerialNumber, Interval, DeviceRegistry()->SetWebSocketTelemetryReporting(CMD_RPC,IntSerialNumber, Interval,
Lifetime); Lifetime);
std::string EndPoint; std::string EndPoint;
if (TelemetryStream()->CreateEndpoint(Utils::SerialNumberToInt(SerialNumber_), EndPoint, CMD_UUID)) { if (TelemetryStream()->CreateEndpoint(Utils::SerialNumberToInt(SerialNumber_), EndPoint, CMD_UUID)) {
@@ -1003,7 +1047,7 @@ namespace OpenWifi {
} }
} else { } else {
Answer.set("action", "WebSocket telemetry stopped."); Answer.set("action", "WebSocket telemetry stopped.");
DeviceRegistry()->StopWebSocketTelemetry(IntSerialNumber); DeviceRegistry()->StopWebSocketTelemetry(CMD_RPC,IntSerialNumber);
} }
} }
} else { } else {
@@ -1032,7 +1076,6 @@ namespace OpenWifi {
TelemetryStatus.set("kafkaPackets", TelemetryKafkaPackets); TelemetryStatus.set("kafkaPackets", TelemetryKafkaPackets);
TelemetryStatus.set("websocketPackets", TelemetryWebSocketPackets); TelemetryStatus.set("websocketPackets", TelemetryWebSocketPackets);
Answer.set("status", TelemetryStatus); Answer.set("status", TelemetryStatus);
return ReturnObject(Answer); return ReturnObject(Answer);
} }
return BadRequest(RESTAPI::Errors::MissingOrInvalidParameters); return BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);

View File

@@ -33,20 +33,20 @@ namespace OpenWifi {
void GetStatus(); void GetStatus();
void GetChecks(); void GetChecks();
void DeleteChecks(); void DeleteChecks();
void ExecuteCommand(const std::string &UUID, uint64_t RPC); void ExecuteCommand(const std::string &UUID, uint64_t RPC, std::chrono::milliseconds timeout);
void Configure(const std::string &UUID, uint64_t RPC); void Configure(const std::string &UUID, uint64_t RPC, std::chrono::milliseconds timeout);
void Upgrade(const std::string &UUID, uint64_t RPC); void Upgrade(const std::string &UUID, uint64_t RPC, std::chrono::milliseconds timeout);
void Reboot(const std::string &UUID, uint64_t RPC); void Reboot(const std::string &UUID, uint64_t RPC, std::chrono::milliseconds timeout);
void Factory(const std::string &UUID, uint64_t RPC); void Factory(const std::string &UUID, uint64_t RPC, std::chrono::milliseconds timeout);
void LEDs(const std::string &UUID, uint64_t RPC); void LEDs(const std::string &UUID, uint64_t RPC, std::chrono::milliseconds timeout);
void Trace(const std::string &UUID, uint64_t RPC); void Trace(const std::string &UUID, uint64_t RPC, std::chrono::milliseconds timeout);
void MakeRequest(const std::string &UUID, uint64_t RPC); void MakeRequest(const std::string &UUID, uint64_t RPC, std::chrono::milliseconds timeout);
void WifiScan(const std::string &UUID, uint64_t RPC); void WifiScan(const std::string &UUID, uint64_t RPC, std::chrono::milliseconds timeout);
void EventQueue(const std::string &UUID, uint64_t RPC); void EventQueue(const std::string &UUID, uint64_t RPC, std::chrono::milliseconds timeout);
void Rtty(const std::string &UUID, uint64_t RPC); void Rtty(const std::string &UUID, uint64_t RPC, std::chrono::milliseconds timeout);
void Telemetry(const std::string &UUID, uint64_t RPC); void Telemetry(const std::string &UUID, uint64_t RPC, std::chrono::milliseconds timeout);
void Ping(const std::string &UUID, uint64_t RPC); void Ping(const std::string &UUID, uint64_t RPC, std::chrono::milliseconds timeout);
void Script(const std::string &UUID, uint64_t RPC); void Script(const std::string &UUID, uint64_t RPC, std::chrono::milliseconds timeout);
static auto PathName() { return std::list<std::string>{"/api/v1/device/{serialNumber}/{command}"}; }; static auto PathName() { return std::list<std::string>{"/api/v1/device/{serialNumber}/{command}"}; };
void DoGet() final; void DoGet() final;
@@ -55,6 +55,7 @@ namespace OpenWifi {
void DoPut() final {}; void DoPut() final {};
void CallCanceled(const char * Cmd,const std::string &UUID, uint64_t RPC, const OpenWifi::RESTAPI::Errors::msg & Err); void CallCanceled(const char * Cmd,const std::string &UUID, uint64_t RPC, const OpenWifi::RESTAPI::Errors::msg & Err);
void CallCanceled(const char * Cmd, const OpenWifi::RESTAPI::Errors::msg &Err, const std::string & Details="");
inline bool ValidateParameters() { inline bool ValidateParameters() {
Command_ = GetBinding(RESTAPI::Protocol::COMMAND, ""); Command_ = GetBinding(RESTAPI::Protocol::COMMAND, "");
@@ -69,6 +70,8 @@ namespace OpenWifi {
} }
private: private:
std::string SerialNumber_, Command_; std::string SerialNumber_,
Command_;
std::uint64_t SerialNumberInt_=0;
}; };
} }

View File

@@ -20,7 +20,7 @@ namespace OpenWifi {
void RESTAPI_device_handler::DoGet() { void RESTAPI_device_handler::DoGet() {
std::string SerialNumber = GetBinding(RESTAPI::Protocol::SERIALNUMBER, ""); std::string SerialNumber = GetBinding(RESTAPI::Protocol::SERIALNUMBER, "");
if(!Utils::ValidSerialNumber(SerialNumber)) { if(!Utils::NormalizeMac(SerialNumber)) {
return BadRequest(RESTAPI::Errors::MissingSerialNumber); return BadRequest(RESTAPI::Errors::MissingSerialNumber);
} }
@@ -42,7 +42,7 @@ namespace OpenWifi {
void RESTAPI_device_handler::DoDelete() { void RESTAPI_device_handler::DoDelete() {
std::string SerialNumber = GetBinding(RESTAPI::Protocol::SERIALNUMBER, ""); std::string SerialNumber = GetBinding(RESTAPI::Protocol::SERIALNUMBER, "");
if(!Utils::ValidSerialNumber(SerialNumber)) { if(!Utils::NormalizeMac(SerialNumber)) {
return BadRequest(RESTAPI::Errors::MissingSerialNumber); return BadRequest(RESTAPI::Errors::MissingSerialNumber);
} }
@@ -86,7 +86,7 @@ namespace OpenWifi {
void RESTAPI_device_handler::DoPost() { void RESTAPI_device_handler::DoPost() {
std::string SerialNumber = GetBinding(RESTAPI::Protocol::SERIALNUMBER, ""); std::string SerialNumber = GetBinding(RESTAPI::Protocol::SERIALNUMBER, "");
if(!Utils::ValidSerialNumber(SerialNumber)) { if(!Utils::NormalizeMac(SerialNumber)) {
return BadRequest(RESTAPI::Errors::MissingSerialNumber); return BadRequest(RESTAPI::Errors::MissingSerialNumber);
} }
@@ -116,6 +116,10 @@ namespace OpenWifi {
return BadRequest(RESTAPI::Errors::InvalidJSONDocument); return BadRequest(RESTAPI::Errors::InvalidJSONDocument);
} }
if(!Utils::NormalizeMac(Device.SerialNumber)) {
return BadRequest( RESTAPI::Errors::InvalidSerialNumber);
}
if(SerialNumber!=Device.SerialNumber) { if(SerialNumber!=Device.SerialNumber) {
return BadRequest(RESTAPI::Errors::SerialNumberMismatch); return BadRequest(RESTAPI::Errors::SerialNumberMismatch);
} }

View File

@@ -57,6 +57,15 @@ namespace OpenWifi {
void RESTAPI_devices_handler::DoGet() { void RESTAPI_devices_handler::DoGet() {
if(GetBoolParameter("connectionStatistics")) {
GWObjects::DeviceConnectionStatistics DCS;
Poco::JSON::Object Answer;
DeviceRegistry()->AverageDeviceStatistics(DCS.connectedDevices,DCS.averageConnectionTime, DCS.connectingDevices);
DCS.to_json(Answer);
return ReturnObject(Answer);
}
if(GetBoolParameter("orderSpec")) { if(GetBoolParameter("orderSpec")) {
Types::StringVec Fields; Types::StringVec Fields;
StorageService()->GetDeviceDbFieldList(Fields); StorageService()->GetDeviceDbFieldList(Fields);

View File

@@ -31,7 +31,7 @@ namespace OpenWifi {
} }
GWObjects::RadiusProxyPoolList C; GWObjects::RadiusProxyPoolList C;
if(!C.from_json(ParsedBody_)) { if(!C.from_json(ParsedBody_) || C.pools.empty()) {
return BadRequest(RESTAPI::Errors::InvalidJSONDocument); return BadRequest(RESTAPI::Errors::InvalidJSONDocument);
} }

View File

@@ -25,6 +25,10 @@ void RESTAPI_telemetryWebSocket::DoGet() {
} }
} }
if(!Utils::NormalizeMac(SNum)) {
return BadRequest(RESTAPI::Errors::InvalidSerialNumber);
}
auto SerialNumber = Utils::SerialNumberToInt(SNum); auto SerialNumber = Utils::SerialNumberToInt(SNum);
if(!TelemetryStream()->IsValidEndPoint(SerialNumber,UUID)) { if(!TelemetryStream()->IsValidEndPoint(SerialNumber,UUID)) {

View File

@@ -203,6 +203,10 @@ namespace OpenWifi::GWObjects {
field_to_json(Obj,"kafkaClients", kafkaClients); field_to_json(Obj,"kafkaClients", kafkaClients);
field_to_json(Obj,"kafkaPackets", kafkaPackets); field_to_json(Obj,"kafkaPackets", kafkaPackets);
field_to_json(Obj,"locale", locale); field_to_json(Obj,"locale", locale);
field_to_json(Obj,"started", started);
field_to_json(Obj,"sessionId", sessionId);
field_to_json(Obj,"connectionCompletionTime", connectionCompletionTime);
field_to_json(Obj,"totalConnectionTime", OpenWifi::Now() - started);
switch(VerifiedCertificate) { switch(VerifiedCertificate) {
case NO_CERTIFICATE: case NO_CERTIFICATE:
@@ -218,6 +222,23 @@ namespace OpenWifi::GWObjects {
} }
} }
void DeviceConnectionStatistics::to_json(Poco::JSON::Object &Obj) const {
field_to_json(Obj,"averageConnectionTime", averageConnectionTime);
field_to_json(Obj,"connectedDevices", connectedDevices );
field_to_json(Obj,"connectingDevices", connectingDevices );
}
bool DeviceConnectionStatistics::from_json(const Poco::JSON::Object::Ptr &Obj) {
try {
field_from_json(Obj,"averageConnectionTime", averageConnectionTime);
field_from_json(Obj,"connectedDevices", connectedDevices );
field_from_json(Obj,"connectingDevices", connectingDevices );
return true;
} catch (const Poco::Exception &E) {
}
return false;
}
void RttySessionDetails::to_json(Poco::JSON::Object &Obj) const { void RttySessionDetails::to_json(Poco::JSON::Object &Obj) const {
field_to_json(Obj,"serialNumber", SerialNumber); field_to_json(Obj,"serialNumber", SerialNumber);
field_to_json(Obj,"server", Server); field_to_json(Obj,"server", Server);
@@ -293,7 +314,6 @@ namespace OpenWifi::GWObjects {
} catch (const Poco::Exception &E) { } catch (const Poco::Exception &E) {
} }
return false; return false;
} }
void RadiusProxyPoolList::to_json(Poco::JSON::Object &Obj) const { void RadiusProxyPoolList::to_json(Poco::JSON::Object &Obj) const {
@@ -361,11 +381,13 @@ namespace OpenWifi::GWObjects {
field_to_json(Obj,"secret",secret); field_to_json(Obj,"secret",secret);
field_to_json(Obj,"certificate",certificate); field_to_json(Obj,"certificate",certificate);
field_to_json(Obj,"radsec",radsec); field_to_json(Obj,"radsec",radsec);
field_to_json(Obj,"radsec_secret",radsec_secret); field_to_json(Obj,"radsecPort",radsecPort);
field_to_json(Obj,"radsec_port",radsec_port); field_to_json(Obj,"radsecSecret",radsecSecret);
field_to_json(Obj,"radsec_cacerts",radsec_cacerts); field_to_json(Obj,"radsecCacerts",radsecCacerts);
field_to_json(Obj,"radsec_cert",radsec_cert); field_to_json(Obj,"radsecCert",radsecCert);
field_to_json(Obj,"radsec_key",radsec_key); field_to_json(Obj,"radsecKey",radsecKey);
field_to_json(Obj,"radsecRealms",radsecRealms);
field_to_json(Obj,"ignore",ignore);
} }
bool RadiusProxyServerEntry::from_json(const Poco::JSON::Object::Ptr &Obj) { bool RadiusProxyServerEntry::from_json(const Poco::JSON::Object::Ptr &Obj) {
@@ -377,11 +399,13 @@ namespace OpenWifi::GWObjects {
field_from_json(Obj,"secret",secret); field_from_json(Obj,"secret",secret);
field_from_json(Obj,"certificate",certificate); field_from_json(Obj,"certificate",certificate);
field_from_json(Obj,"radsec",radsec); field_from_json(Obj,"radsec",radsec);
field_from_json(Obj,"radsec_port",radsec_port); field_from_json(Obj,"radsecSecret",radsecSecret);
field_from_json(Obj,"radsec_secret",radsec_secret); field_from_json(Obj,"radsecPort",radsecPort);
field_from_json(Obj,"radsec_cacerts",radsec_cacerts); field_from_json(Obj,"radsecCacerts",radsecCacerts);
field_from_json(Obj,"radsec_cert",radsec_cert); field_from_json(Obj,"radsecCert",radsecCert);
field_from_json(Obj,"radsec_key",radsec_key); field_from_json(Obj,"radsecKey",radsecKey);
field_from_json(Obj,"radsecRealms",radsecRealms);
field_from_json(Obj,"ignore",ignore);
return true; return true;
} catch (const Poco::Exception &E) { } catch (const Poco::Exception &E) {
} }

View File

@@ -38,6 +38,10 @@ namespace OpenWifi::GWObjects {
uint64_t kafkaPackets=0; uint64_t kafkaPackets=0;
uint64_t websocketPackets=0; uint64_t websocketPackets=0;
std::string locale; std::string locale;
uint64_t started=0;
uint64_t sessionId=0;
double connectionCompletionTime=0.0;
void to_json(Poco::JSON::Object &Obj) const; void to_json(Poco::JSON::Object &Obj) const;
}; };
@@ -71,6 +75,15 @@ namespace OpenWifi::GWObjects {
void Print() const; void Print() const;
}; };
struct DeviceConnectionStatistics {
std::uint64_t connectedDevices = 0;
std::uint64_t averageConnectionTime = 0;
std::uint64_t connectingDevices = 0;
void to_json(Poco::JSON::Object &Obj) const;
bool from_json(const Poco::JSON::Object::Ptr &Obj);
};
struct Statistics { struct Statistics {
std::string SerialNumber; std::string SerialNumber;
uint64_t UUID = 0 ; uint64_t UUID = 0 ;
@@ -219,11 +232,13 @@ namespace OpenWifi::GWObjects {
std::string secret; std::string secret;
std::string certificate; std::string certificate;
bool radsec=false; bool radsec=false;
uint16_t radsec_port=2084; uint16_t radsecPort=2083;
std::string radsec_secret; std::string radsecSecret;
std::string radsec_key; std::string radsecKey;
std::string radsec_cert; std::string radsecCert;
std::string radsec_cacerts; std::vector<std::string> radsecCacerts;
std::vector<std::string> radsecRealms;
bool ignore=false;
void to_json(Poco::JSON::Object &Obj) const; void to_json(Poco::JSON::Object &Obj) const;
bool from_json(const Poco::JSON::Object::Ptr &Obj); bool from_json(const Poco::JSON::Object::Ptr &Obj);

View File

@@ -10,12 +10,16 @@
namespace OpenWifi { namespace OpenWifi {
int SerialNumberCache::Start() { int SerialNumberCache::Start() {
poco_notice(Logger(),"Starting...");
StorageService()->UpdateSerialNumberCache(); StorageService()->UpdateSerialNumberCache();
return 0; return 0;
} }
void SerialNumberCache::Stop() { void SerialNumberCache::Stop() {
poco_notice(Logger(),"Stopping...");
SNs_.clear();
Reverse_SNs_.clear();
poco_notice(Logger(),"Stopped...");
} }
void SerialNumberCache::AddSerialNumber(const std::string &S) { void SerialNumberCache::AddSerialNumber(const std::string &S) {

View File

@@ -4,9 +4,10 @@
#include <fstream> #include <fstream>
#include "framework/MicroService.h"
#include "StorageArchiver.h" #include "StorageArchiver.h"
#include "StorageService.h" #include "StorageService.h"
#include "framework/MicroService.h"
namespace OpenWifi { namespace OpenWifi {
@@ -15,23 +16,23 @@ namespace OpenWifi {
auto now = OpenWifi::Now(); auto now = OpenWifi::Now();
for(const auto &i:DBs_) { for(const auto &i:DBs_) {
if (!Poco::icompare(i.DBName, "healthchecks")) { if (!Poco::icompare(i.DBName, "healthchecks")) {
Logger().information("Archiving HealthChecks..."); poco_information(Logger(),"Archiving HealthChecks...");
StorageService()->RemoveHealthChecksRecordsOlderThan( StorageService()->RemoveHealthChecksRecordsOlderThan(
now - (i.HowManyDays * 24 * 60 * 60)); now - (i.HowManyDays * 24 * 60 * 60));
} else if (!Poco::icompare(i.DBName, "statistics")) { } else if (!Poco::icompare(i.DBName, "statistics")) {
Logger().information("Archiving Statistics..."); poco_information(Logger(),"Archiving Statistics...");
StorageService()->RemoveStatisticsRecordsOlderThan( StorageService()->RemoveStatisticsRecordsOlderThan(
now - (i.HowManyDays * 24 * 60 * 60)); now - (i.HowManyDays * 24 * 60 * 60));
} else if (!Poco::icompare(i.DBName, "devicelogs")) { } else if (!Poco::icompare(i.DBName, "devicelogs")) {
Logger().information("Archiving Device Logs..."); poco_information(Logger(),"Archiving Device Logs...");
StorageService()->RemoveDeviceLogsRecordsOlderThan( StorageService()->RemoveDeviceLogsRecordsOlderThan(
now - (i.HowManyDays * 24 * 60 * 60)); now - (i.HowManyDays * 24 * 60 * 60));
} else if (!Poco::icompare(i.DBName, "commandlist")) { } else if (!Poco::icompare(i.DBName, "commandlist")) {
Logger().information("Archiving Command History..."); poco_information(Logger(),"Archiving Command History...");
StorageService()->RemoveCommandListRecordsOlderThan( StorageService()->RemoveCommandListRecordsOlderThan(
now - (i.HowManyDays * 24 * 60 * 60)); now - (i.HowManyDays * 24 * 60 * 60));
} else { } else {
Logger().information(fmt::format("Cannot archive DB '{}'", i.DBName)); poco_information(Logger(),fmt::format("Cannot archive DB '{}'", i.DBName));
} }
} }
AppServiceRegistry().Set("lastStorageArchiverRun", (uint64_t) Now); AppServiceRegistry().Set("lastStorageArchiverRun", (uint64_t) Now);
@@ -54,11 +55,12 @@ namespace OpenWifi {
Enabled_ = MicroService::instance().ConfigGetBool("archiver.enabled",false); Enabled_ = MicroService::instance().ConfigGetBool("archiver.enabled",false);
if(!Enabled_) { if(!Enabled_) {
Logger().information("Archiver is disabled."); poco_information(Logger(),"Archiver is disabled.");
return 0; return 0;
} }
ArchiverCallback_ = std::make_unique<Poco::TimerCallback<Archiver>>(Archiver_,&Archiver::onTimer); Archiver_ = std::make_unique<Archiver>(Logger());
ArchiverCallback_ = std::make_unique<Poco::TimerCallback<Archiver>>(*Archiver_,&Archiver::onTimer);
auto Schedule = MicroService::instance().ConfigGetString("archiver.schedule","03:00"); auto Schedule = MicroService::instance().ConfigGetString("archiver.schedule","03:00");
auto S = Poco::StringTokenizer(Schedule,":"); auto S = Poco::StringTokenizer(Schedule,":");
@@ -80,7 +82,7 @@ namespace OpenWifi {
if(Poco::icompare(DBName,DB)==0) { if(Poco::icompare(DBName,DB)==0) {
std::string Key = "archiver.db." + std::to_string(i) + ".keep"; std::string Key = "archiver.db." + std::to_string(i) + ".keep";
auto Keep = MicroService::instance().ConfigGetInt(Key,7); auto Keep = MicroService::instance().ConfigGetInt(Key,7);
Archiver_.AddDb(Archiver::ArchiverDBEntry{ Archiver_->AddDb(Archiver::ArchiverDBEntry{
.DBName = DB, .DBName = DB,
.HowManyDays = Keep .HowManyDays = Keep
}); });
@@ -91,7 +93,7 @@ namespace OpenWifi {
int NextRun = CalculateDelta(RunAtHour_,RunAtMin_); int NextRun = CalculateDelta(RunAtHour_,RunAtMin_);
Logger().information(fmt::format("Next run in {} seconds.",NextRun)); poco_information(Logger(),fmt::format("Next run in {} seconds.",NextRun));
Timer_.setStartInterval( NextRun * 1000); Timer_.setStartInterval( NextRun * 1000);
Timer_.setPeriodicInterval(24 * 60 * 60 * 1000); // 1 hours Timer_.setPeriodicInterval(24 * 60 * 60 * 1000); // 1 hours
@@ -101,9 +103,11 @@ namespace OpenWifi {
} }
void StorageArchiver::Stop() { void StorageArchiver::Stop() {
poco_information(Logger(),"Stopping...");
if(Enabled_) { if(Enabled_) {
Timer_.stop(); Timer_.stop();
} }
poco_information(Logger(),"Stopped...");
} }
}; };

View File

@@ -50,7 +50,7 @@ namespace OpenWifi {
private: private:
std::atomic_bool Enabled_ = false; std::atomic_bool Enabled_ = false;
Poco::Timer Timer_; Poco::Timer Timer_;
Archiver Archiver_{Logger()}; std::unique_ptr<Archiver> Archiver_;
std::unique_ptr<Poco::TimerCallback<Archiver>> ArchiverCallback_; std::unique_ptr<Poco::TimerCallback<Archiver>> ArchiverCallback_;
StorageArchiver() noexcept: StorageArchiver() noexcept:

View File

@@ -22,8 +22,9 @@ namespace OpenWifi {
void Storage::Stop() { void Storage::Stop() {
std::lock_guard Guard(Mutex_); std::lock_guard Guard(Mutex_);
Logger().notice("Stopping..."); poco_notice(Logger(),"Stopping...");
StorageClass::Stop(); StorageClass::Stop();
poco_notice(Logger(),"Stopped...");
} }
} }
// namespace // namespace

View File

@@ -19,14 +19,30 @@ namespace OpenWifi {
public: public:
enum CommandExecutionType { enum class CommandExecutionType {
COMMAND_PENDING, COMMAND_PENDING,
COMMAND_EXECUTED, COMMAND_EXECUTED,
COMMAND_COMPLETED, COMMAND_COMPLETED,
COMMAND_TIMEDOUT, COMMAND_TIMEDOUT,
COMMAND_FAILED COMMAND_FAILED,
COMMAND_EXPIRED,
COMMAND_EXECUTING
}; };
inline std::string to_string(const CommandExecutionType &C) {
switch(C) {
case CommandExecutionType::COMMAND_PENDING: return "pending";
case CommandExecutionType::COMMAND_EXECUTED: return "executed";
case CommandExecutionType::COMMAND_COMPLETED: return "completed";
case CommandExecutionType::COMMAND_TIMEDOUT: return "timedout";
case CommandExecutionType::COMMAND_FAILED: return "failed";
case CommandExecutionType::COMMAND_EXPIRED: return "expired";
case CommandExecutionType::COMMAND_EXECUTING:
default:
return "executing";
}
}
[[nodiscard]] inline std::string ComputeRange(uint64_t From, uint64_t HowMany) { [[nodiscard]] inline std::string ComputeRange(uint64_t From, uint64_t HowMany) {
if(dbType_==sqlite) { if(dbType_==sqlite) {
return " LIMIT " + std::to_string(From) + ", " + std::to_string(HowMany) + " "; return " LIMIT " + std::to_string(From) + ", " + std::to_string(HowMany) + " ";
@@ -139,6 +155,10 @@ namespace OpenWifi {
bool SetCommandResult(std::string & UUID, std::string & Result); bool SetCommandResult(std::string & UUID, std::string & Result);
bool GetNewestCommands(std::string &SerialNumber, uint64_t HowMany, std::vector<GWObjects::CommandDetails> & Commands); bool GetNewestCommands(std::string &SerialNumber, uint64_t HowMany, std::vector<GWObjects::CommandDetails> & Commands);
bool SetCommandExecuted(std::string & CommandUUID); bool SetCommandExecuted(std::string & CommandUUID);
bool SetCommandTimedOut(std::string &CommandUUID);
void RemovedExpiredCommands();
void RemoveTimedOutCommands();
bool RemoveOldCommands(std::string & SerilNumber, std::string & Command); bool RemoveOldCommands(std::string & SerilNumber, std::string & Command);

View File

@@ -7,6 +7,7 @@
#include "DeviceRegistry.h" #include "DeviceRegistry.h"
#include "TelemetryClient.h" #include "TelemetryClient.h"
#include "TelemetryStream.h" #include "TelemetryStream.h"
#include "CommandManager.h"
#include "Poco/Net/SSLException.h" #include "Poco/Net/SSLException.h"
@@ -45,6 +46,7 @@ namespace OpenWifi {
WS_->setNoDelay(true); WS_->setNoDelay(true);
WS_->setKeepAlive(true); WS_->setKeepAlive(true);
WS_->setMaxPayloadSize(2048); WS_->setMaxPayloadSize(2048);
WS_->setBlocking(false);
Reactor_.addEventHandler( Reactor_.addEventHandler(
*WS_, Poco::NObserver<TelemetryClient, Poco::Net::ReadableNotification>( *WS_, Poco::NObserver<TelemetryClient, Poco::Net::ReadableNotification>(
*this, &TelemetryClient::OnSocketReadable)); *this, &TelemetryClient::OnSocketReadable));
@@ -55,7 +57,7 @@ namespace OpenWifi {
*WS_, Poco::NObserver<TelemetryClient, Poco::Net::ErrorNotification>( *WS_, Poco::NObserver<TelemetryClient, Poco::Net::ErrorNotification>(
*this, &TelemetryClient::OnSocketError)); *this, &TelemetryClient::OnSocketError));
Registered_ = true; Registered_ = true;
Logger().information(fmt::format("CONNECTION({}): Connection completed.", CId_)); poco_information(Logger(),fmt::format("TELEMETRY-CONNECTION({}): Connection completed.", CId_));
return; return;
} }
} catch (const Poco::Net::SSLException &E) { } catch (const Poco::Net::SSLException &E) {
@@ -68,7 +70,7 @@ namespace OpenWifi {
} }
TelemetryClient::~TelemetryClient() { TelemetryClient::~TelemetryClient() {
Logger().information(fmt::format("CONNECTION({}): Closing connection.", CId_)); poco_information(Logger(),fmt::format("TELEMETRY-CONNECTION({}): Closing connection.", CId_));
if(Registered_ && WS_) if(Registered_ && WS_)
{ {
Reactor_.removeEventHandler(*WS_, Reactor_.removeEventHandler(*WS_,
@@ -91,19 +93,19 @@ namespace OpenWifi {
} }
void TelemetryClient::SendTelemetryShutdown() { void TelemetryClient::SendTelemetryShutdown() {
Logger().information(fmt::format("TELEMETRY-SHUTDOWN({}): Closing.",CId_)); poco_information(Logger(),fmt::format("TELEMETRY-SHUTDOWN({}): Closing.",CId_));
DeviceRegistry()->StopWebSocketTelemetry(SerialNumber_); DeviceRegistry()->StopWebSocketTelemetry(CommandManager()->NextRPCId(), SerialNumber_);
TelemetryStream()->DeRegisterClient(UUID_); TelemetryStream()->DeRegisterClient(UUID_);
delete this; delete this;
} }
void TelemetryClient::OnSocketShutdown([[maybe_unused]] const Poco::AutoPtr<Poco::Net::ShutdownNotification>& pNf) { void TelemetryClient::OnSocketShutdown([[maybe_unused]] const Poco::AutoPtr<Poco::Net::ShutdownNotification>& pNf) {
Logger().information(fmt::format("SOCKET-SHUTDOWN({}): Orderly shutdown.", CId_)); poco_information(Logger(),fmt::format("TELEMETRY-SOCKET-SHUTDOWN({}): Orderly shutdown.", CId_));
SendTelemetryShutdown(); SendTelemetryShutdown();
} }
void TelemetryClient::OnSocketError([[maybe_unused]] const Poco::AutoPtr<Poco::Net::ErrorNotification>& pNf) { void TelemetryClient::OnSocketError([[maybe_unused]] const Poco::AutoPtr<Poco::Net::ErrorNotification>& pNf) {
Logger().information(fmt::format("SOCKET-ERROR({}): Closing.",CId_)); poco_information(Logger(),fmt::format("TELEMETRY-SOCKET-ERROR({}): Closing.",CId_));
SendTelemetryShutdown(); SendTelemetryShutdown();
} }
@@ -120,11 +122,11 @@ namespace OpenWifi {
} }
catch (const std::exception & E) { catch (const std::exception & E) {
std::string W = E.what(); std::string W = E.what();
Logger().information(fmt::format("std::exception caught: {}. Connection terminated with {}",W,CId_)); poco_information(Logger(),fmt::format("TELEMETRY-std::exception caught: {}. Connection terminated with {}",W,CId_));
SendTelemetryShutdown(); SendTelemetryShutdown();
} }
catch ( ... ) { catch ( ... ) {
Logger().information(fmt::format("Unknown exception for {}. Connection terminated.",CId_)); poco_information(Logger(),fmt::format("TELEMETRY-Unknown exception for {}. Connection terminated.",CId_));
SendTelemetryShutdown(); SendTelemetryShutdown();
} }
} }
@@ -141,16 +143,16 @@ namespace OpenWifi {
Op = flags & Poco::Net::WebSocket::FRAME_OP_BITMASK; Op = flags & Poco::Net::WebSocket::FRAME_OP_BITMASK;
if (IncomingSize == 0 && flags == 0 && Op == 0) { if (IncomingSize == 0 && flags == 0 && Op == 0) {
Logger().information(fmt::format("DISCONNECT({}): device has disconnected.", CId_)); poco_information(Logger(),fmt::format("TELEMETRY-DISCONNECT({}): device has disconnected.", CId_));
MustDisconnect = true; MustDisconnect = true;
} else { } else {
if (Op == Poco::Net::WebSocket::FRAME_OP_PING) { if (Op == Poco::Net::WebSocket::FRAME_OP_PING) {
Logger().debug(fmt::format("WS-PING({}): received. PONG sent back.", CId_)); Logger().debug(fmt::format("TELEMETRY-WS-PING({}): received. PONG sent back.", CId_));
WS_->sendFrame("", 0, WS_->sendFrame("", 0,
(int)Poco::Net::WebSocket::FRAME_OP_PONG | (int)Poco::Net::WebSocket::FRAME_OP_PONG |
(int)Poco::Net::WebSocket::FRAME_FLAG_FIN); (int)Poco::Net::WebSocket::FRAME_FLAG_FIN);
} else if (Op == Poco::Net::WebSocket::FRAME_OP_CLOSE) { } else if (Op == Poco::Net::WebSocket::FRAME_OP_CLOSE) {
Logger().information(fmt::format("DISCONNECT({}): device wants to disconnect.", CId_)); poco_information(Logger(),fmt::format("TELEMETRY-DISCONNECT({}): device wants to disconnect.", CId_));
MustDisconnect = true ; MustDisconnect = true ;
} }
} }

View File

@@ -3,34 +3,34 @@
// //
#include <thread> #include <thread>
#include "framework/MicroService.h"
#include "Poco/JSON/Array.h" #include "Poco/JSON/Array.h"
#include "Poco/Net/HTTPHeaderStream.h" #include "Poco/Net/HTTPHeaderStream.h"
#include "Poco/URI.h" #include "Poco/URI.h"
#include "RESTAPI/RESTAPI_telemetryWebSocket.h" #include "RESTAPI/RESTAPI_telemetryWebSocket.h"
#include "TelemetryStream.h" #include "TelemetryStream.h"
#include "framework/MicroService.h"
namespace OpenWifi { namespace OpenWifi {
int TelemetryStream::Start() { int TelemetryStream::Start() {
Running_ = true; Running_ = true;
Messages_->Readable_ += Poco::delegate(this,&TelemetryStream::onMessage); Messages_->Readable_ += Poco::delegate(this,&TelemetryStream::onMessage);
// ReactorPool_.Start("TelemetryWebSocketPool_");
Thr_.start(Reactor_); Thr_.start(Reactor_);
Utils::SetThreadName(Thr_,"telemetry-svr"); Utils::SetThreadName(Thr_,"telemetry-svr");
return 0; return 0;
} }
void TelemetryStream::Stop() { void TelemetryStream::Stop() {
Logger().notice("Stopping reactors..."); poco_information(Logger(),"Stopping...");
// ReactorPool_.Stop();
Reactor_.stop(); Reactor_.stop();
Thr_.join(); Thr_.join();
if(Running_) { if(Running_) {
Running_ = false; Running_ = false;
Messages_->Readable_ -= Poco::delegate( this, &TelemetryStream::onMessage); Messages_->Readable_ -= Poco::delegate( this, &TelemetryStream::onMessage);
} }
poco_information(Logger(),"Stopped...");
} }
bool TelemetryStream::IsValidEndPoint(uint64_t SerialNumber, const std::string & UUID) { bool TelemetryStream::IsValidEndPoint(uint64_t SerialNumber, const std::string & UUID) {

View File

@@ -39,15 +39,17 @@ namespace OpenWifi {
} }
inline void Stop() override { inline void Stop() override {
poco_information(Logger(),"Stopping...");
if(Enabled_ && Running_) { if(Enabled_ && Running_) {
BroadcastQueue_.wakeUpAll(); BroadcastQueue_.wakeUpAll();
BroadcastManager_.wakeUp(); BroadcastManager_.wakeUp();
BroadcastManager_.join(); BroadcastManager_.join();
} }
poco_information(Logger(),"Stopped...");
} }
inline void reinitialize([[maybe_unused]] Poco::Util::Application &self) override { inline void reinitialize([[maybe_unused]] Poco::Util::Application &self) override {
Logger().information("Reinitializing."); poco_information(Logger(),"Reinitializing.");
} }

206
src/attributes.json Normal file
View File

@@ -0,0 +1,206 @@
{
"interfaces": [
{
"ethernet": [
{
"select-ports": [
"WAN*"
]
}
],
"ipv4": {
"addressing": "dynamic"
},
"ipv6": {
"addressing": "dynamic"
},
"name": "wan",
"role": "upstream",
"services": [
"ssh"
],
"ssids": []
},
{
"ethernet": [
{
"select-ports": [
"LAN*"
]
}
],
"ipv4": {
"addressing": "static",
"dhcp": {
"lease-count": 100,
"lease-first": 10,
"lease-time": "6h"
},
"gateway": "192.168.1.1",
"send-hostname": true,
"subnet": "192.168.1.1/24",
"use-dns": []
},
"ipv6": {
"addressing": "dynamic"
},
"name": "lan",
"role": "downstream",
"services": [
"wifi-steering",
"ssh"
],
"ssids": [
{
"bss-mode": "ap",
"encryption": {
"ieee80211w": "optional",
"proto": "wpa-mixed"
},
"hidden-ssid": false,
"isolate-clients": false,
"maximum-clients": 64,
"name": "arilia-rad",
"pass-point": {
"access-network-type": 0,
"anqp-3gpp-cell-net": [],
"anqp-domain": 8888,
"asra": false,
"auth-type": {
"type": "terms-and-conditions"
},
"connection-capability": [
"1:0:2",
"6:22:1",
"17:5060:0"
],
"disable-dgaf": true,
"domain-name": [
"main.arilia.com"
],
"esr": false,
"friendly-name": [
"eng:AriliaWifi",
"fra:AriliaWifi"
],
"hessid": "11:22:33:44:55:66",
"internet": true,
"ipaddr-type-available": 14,
"nai-realm": [],
"osen": false,
"roaming-consortium": [
"F4F5E8F5F4"
],
"uesa": false,
"venue-group": 2,
"venue-name": [
"eng:Bowen Development 1",
"fra:Bowen Development 1"
],
"venue-type": 8,
"venue-url": [
"http://www.example.com/info-fra",
"http://www.example.com/info-eng"
]
},
"radius": {
"accounting": {
"interval" : 600,
"host": "0.0.0.0",
"port": 1813,
"secret": "radsec"
},
"authentication": {
"host": "0.0.0.0",
"port": 1812,
"secret": "radsec",
},
"chargeable-user-id" : true,
"nas-identifier": "AriliaWifi",
"realm" : [
"c2k2q8e2pcs2udar1pa0.orion.area120.com"
]
},
"services": [
"radius-gw-proxy"
],
"wifi-bands": [
"2G",
"5G"
]
}
]
}
],
"metrics": {
"dhcp-snooping": {
"filters": [
"ack",
"discover",
"offer",
"request",
"solicit",
"reply",
"renew"
]
},
"health": {
"interval": 60
},
"statistics": {
"interval": 60,
"types": [
"ssids",
"lldp",
"clients"
]
},
"wifi-frames": {
"filters": [
"probe",
"auth",
"assoc",
"disassoc",
"deauth",
"local-deauth",
"inactive-deauth",
"key-mismatch",
"beacon-report",
"radar-detected"
]
}
},
"radios": [
{
"band": "2G",
"bandwidth": 10,
"beacon-interval": 100,
"channel": "auto",
"channel-mode": "HT",
"channel-width": 20,
"country": "CA",
"dtim-period": 2,
"maximum-clients": 64,
"tx-power": 23
},
{
"band": "5G",
"bandwidth": 20,
"beacon-interval": 100,
"channel": "auto",
"channel-mode": "VHT",
"channel-width": 80,
"country": "CA",
"dtim-period": 2,
"maximum-clients": 64,
"tx-power": 23
}
],
"services": {
"ssh": {
"password-authentication": true,
"port": 22
}
},
"uuid": 1661409802
}

View File

@@ -44,7 +44,7 @@ static json DefaultUCentralSchema = R"(
"switch": { "switch": {
"$ref": "#/$defs/switch" "$ref": "#/$defs/switch"
}, },
"radios": { "radiosgrep": {
"type": "array", "type": "array",
"items": { "items": {
"$ref": "#/$defs/radio" "$ref": "#/$defs/radio"

View File

@@ -23,6 +23,13 @@
#include <queue> #include <queue>
#include <variant> #include <variant>
// This must be defined for poco_debug and poco_trace macros to function.
#ifndef POCO_LOG_DEBUG
#define POCO_LOG_DEBUG true
#endif
namespace OpenWifi { namespace OpenWifi {
inline uint64_t Now() { return std::time(nullptr); }; inline uint64_t Now() { return std::time(nullptr); };
} }
@@ -89,6 +96,7 @@ using namespace std::chrono_literals;
#include "Poco/NObserver.h" #include "Poco/NObserver.h"
#include "Poco/Net/SocketNotification.h" #include "Poco/Net/SocketNotification.h"
#include "Poco/Base64Decoder.h" #include "Poco/Base64Decoder.h"
#include "Poco/ThreadLocal.h"
#include "cppkafka/cppkafka.h" #include "cppkafka/cppkafka.h"
#include "framework/OpenWifiTypes.h" #include "framework/OpenWifiTypes.h"
@@ -660,6 +668,19 @@ namespace OpenWifi::RESTAPI_utils {
namespace OpenWifi::Utils { namespace OpenWifi::Utils {
inline bool NormalizeMac(std::string & Mac) {
Poco::replaceInPlace(Mac,":","");
Poco::replaceInPlace(Mac,"-","");
if(Mac.size()!=12)
return false;
for(const auto &i:Mac) {
if(!std::isxdigit(i))
return false;
}
Poco::toLowerInPlace(Mac);
return true;
}
inline void SetThreadName(const char *name) { inline void SetThreadName(const char *name) {
#ifdef __linux__ #ifdef __linux__
Poco::Thread::current()->setName(name); Poco::Thread::current()->setName(name);
@@ -1339,23 +1360,27 @@ namespace OpenWifi {
Poco::ExpireLRUCache<KeyType,Record> Cache_{Size,Expiry}; Poco::ExpireLRUCache<KeyType,Record> Cache_{Size,Expiry};
}; };
class MyErrorHandler : public Poco::ErrorHandler { class MicroServiceErrorHandler : public Poco::ErrorHandler {
public: public:
explicit MyErrorHandler(Poco::Util::Application &App) : App_(App) {} explicit MicroServiceErrorHandler(Poco::Util::Application &App) : App_(App) {}
inline void exception(const Poco::Exception & E) { inline void exception(const Poco::Exception & E) {
Poco::Thread * CurrentThread = Poco::Thread::current(); Poco::Thread * CurrentThread = Poco::Thread::current();
App_.logger().log(E); App_.logger().log(E);
App_.logger().error(fmt::format("Exception occurred in {}",CurrentThread->getName())); poco_error(App_.logger(), fmt::format("Poco::Exception occurred in name={} thr_id={}",
CurrentThread->getName(), CurrentThread->id()));
} }
inline void exception(const std::exception & E) { inline void exception(const std::exception & E) {
Poco::Thread * CurrentThread = Poco::Thread::current(); Poco::Thread * CurrentThread = Poco::Thread::current();
App_.logger().warning(fmt::format("std::exception in {}: {}",CurrentThread->getName(),E.what())); poco_warning(App_.logger(), fmt::format("std::exception in {}: {} thr_id={}",
CurrentThread->getName(),E.what(),
CurrentThread->id()));
} }
inline void exception() { inline void exception() {
Poco::Thread * CurrentThread = Poco::Thread::current(); Poco::Thread * CurrentThread = Poco::Thread::current();
App_.logger().warning(fmt::format("exception in {}",CurrentThread->getName())); poco_warning(App_.logger(), fmt::format("generic exception in {} thr_id={}",
CurrentThread->getName(), CurrentThread->id()));
} }
private: private:
Poco::Util::Application &App_; Poco::Util::Application &App_;
@@ -1363,12 +1388,17 @@ namespace OpenWifi {
class BusEventManager : public Poco::Runnable { class BusEventManager : public Poco::Runnable {
public: public:
explicit BusEventManager(Poco::Logger &L) : Logger_(L) {
}
inline void run() final; inline void run() final;
inline void Start(); inline void Start();
inline void Stop(); inline void Stop();
inline Poco::Logger & Logger() { return Logger_; }
private: private:
mutable std::atomic_bool Running_ = false; mutable std::atomic_bool Running_ = false;
Poco::Thread Thread_; Poco::Thread Thread_;
Poco::Logger &Logger_;
}; };
class MyPrivateKeyPassphraseHandler : public Poco::Net::PrivateKeyPassphraseHandler { class MyPrivateKeyPassphraseHandler : public Poco::Net::PrivateKeyPassphraseHandler {
@@ -1382,6 +1412,7 @@ namespace OpenWifi {
Logger_.information("Returning key passphrase."); Logger_.information("Returning key passphrase.");
privateKey = Password_; privateKey = Password_;
}; };
inline Poco::Logger & Logger() { return Logger_; }
private: private:
std::string Password_; std::string Password_;
Poco::Logger & Logger_; Poco::Logger & Logger_;
@@ -1650,14 +1681,14 @@ namespace OpenWifi {
class SubSystemServer : public Poco::Util::Application::Subsystem { class SubSystemServer : public Poco::Util::Application::Subsystem {
public: public:
SubSystemServer(std::string Name, const std::string &LoggingPrefix, SubSystemServer(const std::string & Name, const std::string &LoggingPrefix,
std::string SubSystemConfigPrefix); const std::string & SubSystemConfigPrefix);
inline void initialize(Poco::Util::Application &self) override; inline void initialize(Poco::Util::Application &self) override;
inline void uninitialize() override { inline void uninitialize() override {
} }
inline void reinitialize([[maybe_unused]] Poco::Util::Application &self) override { inline void reinitialize([[maybe_unused]] Poco::Util::Application &self) override {
Logger().information("Reloading of this subsystem is not supported."); Logger_->L_.information("Reloading of this subsystem is not supported.");
} }
inline void defineOptions([[maybe_unused]] Poco::Util::OptionSet &options) override { inline void defineOptions([[maybe_unused]] Poco::Util::OptionSet &options) override {
} }
@@ -1666,30 +1697,30 @@ namespace OpenWifi {
inline const PropertiesFileServerEntry & Host(uint64_t index) { return ConfigServersList_[index]; }; inline const PropertiesFileServerEntry & Host(uint64_t index) { return ConfigServersList_[index]; };
inline uint64_t HostSize() const { return ConfigServersList_.size(); } inline uint64_t HostSize() const { return ConfigServersList_.size(); }
inline Poco::Logger &Logger() { if(Log_) inline Poco::Logger & Logger() const { return Logger_->L_; }
return Log_->L; inline void SetLoggingLevel(const std::string & levelName) {
return Poco::Logger::get("tmp"); Logger_->L_.setLevel(Poco::Logger::parseLevel(levelName));
}; }
inline void SetLoggingLevel(Poco::Message::Priority NewPriority) { Logger().setLevel(NewPriority); } inline int GetLoggingLevel() { return Logger_->L_.getLevel(); }
inline int GetLoggingLevel() { return Logger().getLevel(); }
virtual int Start() = 0; virtual int Start() = 0;
virtual void Stop() = 0; virtual void Stop() = 0;
struct LoggerWrapper { struct LoggerWrapper {
Poco::Logger &L; Poco::Logger & L_;
explicit inline LoggerWrapper(Poco::Logger &Logger) : L(Logger) {} LoggerWrapper(Poco::Logger &L) :
}; L_(L) {}
};
protected: protected:
std::recursive_mutex Mutex_; std::recursive_mutex Mutex_;
std::vector<PropertiesFileServerEntry> ConfigServersList_; std::vector<PropertiesFileServerEntry> ConfigServersList_;
private: private:
std::unique_ptr<LoggerWrapper> Log_; std::unique_ptr<LoggerWrapper> Logger_;
// Poco::Logger &Logger_; std::string Name_;
std::string Name_; std::string LoggerPrefix_;
std::string LoggerPrefix_; std::string SubSystemConfigPrefix_;
std::string SubSystemConfigPrefix_;
}; };
class RESTAPI_GenericServer { class RESTAPI_GenericServer {
@@ -1823,7 +1854,7 @@ namespace OpenWifi {
E->Count++; E->Count++;
Cache_.update(H,E); Cache_.update(H,E);
if(E->Count > MaxCalls) { if(E->Count > MaxCalls) {
Logger().warning(fmt::format("RATE-LIMIT-EXCEEDED: from '{}'", R.clientAddress().toString())); poco_warning(Logger(),fmt::format("RATE-LIMIT-EXCEEDED: from '{}'", R.clientAddress().toString()));
return true; return true;
} }
return false; return false;
@@ -2165,12 +2196,16 @@ namespace OpenWifi {
SetCommonHeaders(CloseConnection); SetCommonHeaders(CloseConnection);
} }
inline void BadRequest(const OpenWifi::RESTAPI::Errors::msg &E) { inline void BadRequest(const OpenWifi::RESTAPI::Errors::msg &E, const std::string & Extra="") {
PrepareResponse(Poco::Net::HTTPResponse::HTTP_BAD_REQUEST); PrepareResponse(Poco::Net::HTTPResponse::HTTP_BAD_REQUEST);
Poco::JSON::Object ErrorObject; Poco::JSON::Object ErrorObject;
ErrorObject.set("ErrorCode",400); ErrorObject.set("ErrorCode",400);
ErrorObject.set("ErrorDetails",Request->getMethod()); ErrorObject.set("ErrorDetails",Request->getMethod());
ErrorObject.set("ErrorDescription",fmt::format("{}: {}",E.err_num,E.err_txt)) ; if(Extra.empty())
ErrorObject.set("ErrorDescription",fmt::format("{}: {}",E.err_num,E.err_txt)) ;
else
ErrorObject.set("ErrorDescription",fmt::format("{}: {} ({})",E.err_num,E.err_txt, Extra)) ;
std::ostream &Answer = Response->send(); std::ostream &Answer = Response->send();
Poco::JSON::Stringifier::stringify(ErrorObject, Answer); Poco::JSON::Stringifier::stringify(ErrorObject, Answer);
} }
@@ -2214,7 +2249,7 @@ namespace OpenWifi {
ErrorObject.set("ErrorDescription",fmt::format("{}: {}",E.err_num,E.err_txt)) ; ErrorObject.set("ErrorDescription",fmt::format("{}: {}",E.err_num,E.err_txt)) ;
std::ostream &Answer = Response->send(); std::ostream &Answer = Response->send();
Poco::JSON::Stringifier::stringify(ErrorObject, Answer); Poco::JSON::Stringifier::stringify(ErrorObject, Answer);
Logger_.debug(fmt::format("RES-NOTFOUND: User='{}@{}' Method='{}' Path='{}", poco_debug(Logger_,fmt::format("RES-NOTFOUND: User='{}@{}' Method='{}' Path='{}",
UserInfo_.userinfo.email, UserInfo_.userinfo.email,
Utils::FormatIPv6(Request->clientAddress().toString()), Utils::FormatIPv6(Request->clientAddress().toString()),
Request->getMethod(), Request->getMethod(),
@@ -2783,9 +2818,11 @@ namespace OpenWifi {
inline void Stop() override { inline void Stop() override {
if(KafkaEnabled_) { if(KafkaEnabled_) {
poco_information(Logger(),"Stopping...");
Dispatcher_.Stop(); Dispatcher_.Stop();
ProducerThr_.Stop(); ProducerThr_.Stop();
ConsumerThr_.Stop(); ConsumerThr_.Stop();
poco_information(Logger(),"Stopped...");
return; return;
} }
} }
@@ -2863,12 +2900,13 @@ namespace OpenWifi {
} }
inline void Stop() override { inline void Stop() override {
poco_information(Logger(),"Stopping...");
std::lock_guard G(Mutex_); std::lock_guard G(Mutex_);
Cache_.clear(); Cache_.clear();
poco_information(Logger(),"Stopped...");
} }
inline void RemovedCachedToken(const std::string &Token) { inline void RemovedCachedToken(const std::string &Token) {
std::lock_guard G(Mutex_);
Cache_.remove(Token); Cache_.remove(Token);
} }
@@ -2878,6 +2916,7 @@ namespace OpenWifi {
inline bool RetrieveTokenInformation(const std::string & SessionToken, inline bool RetrieveTokenInformation(const std::string & SessionToken,
SecurityObjects::UserInfoAndPolicy & UInfo, SecurityObjects::UserInfoAndPolicy & UInfo,
std::uint64_t TID,
bool & Expired, bool & Contacted, bool Sub=false) { bool & Expired, bool & Contacted, bool Sub=false) {
try { try {
Types::StringPairVec QueryData; Types::StringPairVec QueryData;
@@ -2903,7 +2942,6 @@ namespace OpenWifi {
return false; return false;
} }
Expired = false; Expired = false;
std::lock_guard G(Mutex_);
Cache_.update(SessionToken, UInfo); Cache_.update(SessionToken, UInfo);
return true; return true;
} else { } else {
@@ -2911,14 +2949,15 @@ namespace OpenWifi {
} }
} }
} catch (...) { } catch (...) {
poco_error(Logger(),fmt::format("Failed to retrieve token={} for TID={}", SessionToken, TID));
} }
Expired = false; Expired = false;
return false; return false;
} }
inline bool IsAuthorized(const std::string &SessionToken, SecurityObjects::UserInfoAndPolicy & UInfo, inline bool IsAuthorized(const std::string &SessionToken, SecurityObjects::UserInfoAndPolicy & UInfo,
std::uint64_t TID,
bool & Expired, bool & Contacted, bool Sub = false) { bool & Expired, bool & Contacted, bool Sub = false) {
std::lock_guard G(Mutex_);
auto User = Cache_.get(SessionToken); auto User = Cache_.get(SessionToken);
if(!User.isNull()) { if(!User.isNull()) {
if(IsTokenExpired(User->webtoken)) { if(IsTokenExpired(User->webtoken)) {
@@ -2929,7 +2968,7 @@ namespace OpenWifi {
UInfo = *User; UInfo = *User;
return true; return true;
} }
return RetrieveTokenInformation(SessionToken, UInfo, Expired, Contacted, Sub); return RetrieveTokenInformation(SessionToken, UInfo, TID, Expired, Contacted, Sub);
} }
private: private:
@@ -2947,12 +2986,12 @@ namespace OpenWifi {
{ {
} }
void handleRequest(Poco::Net::HTTPServerRequest& Request, Poco::Net::HTTPServerResponse& Response) override void handleRequest([[maybe_unused]] Poco::Net::HTTPServerRequest& Request, Poco::Net::HTTPServerResponse& Response) override
{ {
Utils::SetThreadName("alb-request"); Utils::SetThreadName("alb-request");
try { try {
if((id_ % 100) == 0) { if((id_ % 100) == 0) {
Logger_.debug(fmt::format("ALB-REQUEST({}): ALB Request {}.", poco_debug(Logger_,fmt::format("ALB-REQUEST({}): ALB Request {}.",
Request.clientAddress().toString(), id_)); Request.clientAddress().toString(), id_));
} }
Response.setChunkedTransferEncoding(true); Response.setChunkedTransferEncoding(true);
@@ -3010,8 +3049,10 @@ namespace OpenWifi {
inline int Start() override; inline int Start() override;
inline void Stop() override { inline void Stop() override {
poco_information(Logger(),"Stopping...");
if(Running_) if(Running_)
Server_->stop(); Server_->stopAll(true);
poco_information(Logger(),"Stopped...");
} }
private: private:
@@ -3040,12 +3081,14 @@ namespace OpenWifi {
inline void Stop() override { inline void Stop() override {
Logger().information("Stopping..."); Logger().information("Stopping...");
for( const auto & svr : RESTServers_ ) for( const auto & svr : RESTServers_ )
svr->stop(); svr->stopAll(true);
Pool_.stopAll(); Pool_.stopAll();
Pool_.joinAll(); Pool_.joinAll();
RESTServers_.clear(); RESTServers_.clear();
Logger().information("Stopped...");
} }
inline void reinitialize(Poco::Util::Application &self) override; inline void reinitialize(Poco::Util::Application &self) override;
inline Poco::Net::HTTPRequestHandler *CallServer(const std::string &Path, uint64_t Id) { inline Poco::Net::HTTPRequestHandler *CallServer(const std::string &Path, uint64_t Id) {
@@ -3053,10 +3096,11 @@ namespace OpenWifi {
Utils::SetThreadName(fmt::format("x-rest:{}",Id).c_str()); Utils::SetThreadName(fmt::format("x-rest:{}",Id).c_str());
return RESTAPI_ExtRouter(Path, Bindings, Logger(), Server_, Id); return RESTAPI_ExtRouter(Path, Bindings, Logger(), Server_, Id);
} }
const Poco::ThreadPool & Pool() { return Pool_; }
private: private:
std::vector<std::unique_ptr<Poco::Net::HTTPServer>> RESTServers_; std::vector<std::unique_ptr<Poco::Net::HTTPServer>> RESTServers_;
Poco::ThreadPool Pool_{"x-rest",2,32}; Poco::ThreadPool Pool_{"x-rest",32,128};
RESTAPI_GenericServer Server_; RESTAPI_GenericServer Server_;
RESTAPI_ExtServer() noexcept: RESTAPI_ExtServer() noexcept:
@@ -3073,15 +3117,16 @@ namespace OpenWifi {
inline Poco::Net::HTTPRequestHandler *createRequestHandler(const Poco::Net::HTTPServerRequest &Request) override { inline Poco::Net::HTTPRequestHandler *createRequestHandler(const Poco::Net::HTTPServerRequest &Request) override {
try { try {
Poco::URI uri(Request.getURI()); Poco::URI uri(Request.getURI());
Utils::SetThreadName(fmt::format("x-rest:{}",TransactionId_).c_str()); auto TID = NextTransactionId_++;
return RESTAPI_ExtServer()->CallServer(uri.getPath(), TransactionId_++); Utils::SetThreadName(fmt::format("x-rest:{}",TID).c_str());
return RESTAPI_ExtServer()->CallServer(uri.getPath(), TID);
} catch (...) { } catch (...) {
} }
return nullptr; return nullptr;
} }
private: private:
static inline std::atomic_uint64_t TransactionId_ = 1; static inline std::atomic_uint64_t NextTransactionId_ = 1;
}; };
class LogMuxer : public Poco::Channel { class LogMuxer : public Poco::Channel {
@@ -3173,9 +3218,10 @@ namespace OpenWifi {
inline void Stop() override { inline void Stop() override {
Logger().information("Stopping..."); Logger().information("Stopping...");
for( const auto & svr : RESTServers_ ) for( const auto & svr : RESTServers_ )
svr->stop(); svr->stopAll(true);
Pool_.stopAll(); Pool_.stopAll();
Pool_.joinAll(); Pool_.joinAll();
Logger().information("Stopped...");
} }
inline void reinitialize(Poco::Util::Application &self) override; inline void reinitialize(Poco::Util::Application &self) override;
@@ -3185,9 +3231,10 @@ namespace OpenWifi {
Utils::SetThreadName(fmt::format("i-rest:{}",Id).c_str()); Utils::SetThreadName(fmt::format("i-rest:{}",Id).c_str());
return RESTAPI_IntRouter(Path, Bindings, Logger(), Server_, Id); return RESTAPI_IntRouter(Path, Bindings, Logger(), Server_, Id);
} }
const Poco::ThreadPool & Pool() { return Pool_; }
private: private:
std::vector<std::unique_ptr<Poco::Net::HTTPServer>> RESTServers_; std::vector<std::unique_ptr<Poco::Net::HTTPServer>> RESTServers_;
Poco::ThreadPool Pool_{"i-rest",2,16}; Poco::ThreadPool Pool_{"i-rest",32,96};
RESTAPI_GenericServer Server_; RESTAPI_GenericServer Server_;
RESTAPI_IntServer() noexcept: RESTAPI_IntServer() noexcept:
@@ -3202,12 +3249,13 @@ namespace OpenWifi {
public: public:
inline IntRequestHandlerFactory() = default; inline IntRequestHandlerFactory() = default;
inline Poco::Net::HTTPRequestHandler *createRequestHandler(const Poco::Net::HTTPServerRequest &Request) override { inline Poco::Net::HTTPRequestHandler *createRequestHandler(const Poco::Net::HTTPServerRequest &Request) override {
Utils::SetThreadName(fmt::format("i-rest:{}",TransactionId_).c_str()); auto TID=NextTransactionId_++;
Utils::SetThreadName(fmt::format("i-rest:{}",TID).c_str());
Poco::URI uri(Request.getURI()); Poco::URI uri(Request.getURI());
return RESTAPI_IntServer()->CallServer(uri.getPath(), TransactionId_); return RESTAPI_IntServer()->CallServer(uri.getPath(), TID);
} }
private: private:
static inline std::atomic_uint64_t TransactionId_ = 1; static inline std::atomic_uint64_t NextTransactionId_ = 1;
}; };
struct MicroServiceMeta { struct MicroServiceMeta {
@@ -3268,7 +3316,7 @@ namespace OpenWifi {
return ((RandomEngine_() % (max-min)) + min); return ((RandomEngine_() % (max-min)) + min);
} }
inline Poco::Logger & GetLogger(const std::string &Name) { /* inline Poco::Logger & GetLogger(const std::string &Name) {
static auto initialized = false; static auto initialized = false;
if(!initialized) { if(!initialized) {
@@ -3277,7 +3325,7 @@ namespace OpenWifi {
} }
return Poco::Logger::get(Name); return Poco::Logger::get(Name);
} }
*/
virtual void GetExtraConfiguration(Poco::JSON::Object & Cfg) { virtual void GetExtraConfiguration(Poco::JSON::Object & Cfg) {
Cfg.set("additionalConfiguration",false); Cfg.set("additionalConfiguration",false);
} }
@@ -3370,7 +3418,6 @@ namespace OpenWifi {
std::string MyPublicEndPoint_; std::string MyPublicEndPoint_;
std::string UIURI_; std::string UIURI_;
std::string Version_{ OW_VERSION::VERSION + "("+ OW_VERSION::BUILD + ")" + " - " + OW_VERSION::HASH }; std::string Version_{ OW_VERSION::VERSION + "("+ OW_VERSION::BUILD + ")" + " - " + OW_VERSION::HASH };
BusEventManager BusEventManager_;
std::recursive_mutex InfraMutex_; std::recursive_mutex InfraMutex_;
std::default_random_engine RandomEngine_; std::default_random_engine RandomEngine_;
Poco::Util::PropertyFileConfiguration * PropConfigurationFile_ = nullptr; Poco::Util::PropertyFileConfiguration * PropConfigurationFile_ = nullptr;
@@ -3384,7 +3431,8 @@ namespace OpenWifi {
bool NoBuiltInCrypto_=false; bool NoBuiltInCrypto_=false;
Poco::JWT::Signer Signer_; Poco::JWT::Signer Signer_;
Poco::Logger &Logger_; Poco::Logger &Logger_;
Poco::ThreadPool TimerPool_{"timer:pool",2,16}; Poco::ThreadPool TimerPool_{"timer:pool",2,16};
std::unique_ptr<BusEventManager> BusEventManager_;
}; };
inline void MicroService::Exit(int Reason) { inline void MicroService::Exit(int Reason) {
@@ -3465,7 +3513,7 @@ namespace OpenWifi {
} }
} catch (const Poco::Exception &E) { } catch (const Poco::Exception &E) {
Logger_.log(E); logger().log(E);
} }
} }
@@ -3605,7 +3653,9 @@ namespace OpenWifi {
SubSystems_.push_back(ALBHealthCheckServer()); SubSystems_.push_back(ALBHealthCheckServer());
SubSystems_.push_back(RESTAPI_ExtServer()); SubSystems_.push_back(RESTAPI_ExtServer());
SubSystems_.push_back(RESTAPI_IntServer()); SubSystems_.push_back(RESTAPI_IntServer());
#ifndef TIP_SECURITY_SERVICE
SubSystems_.push_back(AuthClient());
#endif
Poco::Net::initializeSSL(); Poco::Net::initializeSSL();
Poco::Net::HTTPStreamFactory::registerFactory(); Poco::Net::HTTPStreamFactory::registerFactory();
Poco::Net::HTTPSStreamFactory::registerFactory(); Poco::Net::HTTPSStreamFactory::registerFactory();
@@ -3716,8 +3766,9 @@ namespace OpenWifi {
} }
inline void MicroService::InitializeSubSystemServers() { inline void MicroService::InitializeSubSystemServers() {
for(auto i:SubSystems_) for(auto i:SubSystems_) {
addSubsystem(i); addSubsystem(i);
}
} }
inline void MicroService::StartSubSystemServers() { inline void MicroService::StartSubSystemServers() {
@@ -3725,12 +3776,13 @@ namespace OpenWifi {
for(auto i:SubSystems_) { for(auto i:SubSystems_) {
i->Start(); i->Start();
} }
BusEventManager_.Start(); BusEventManager_ = std::make_unique<BusEventManager>(Poco::Logger::create("BusEventManager",Poco::Logger::root().getChannel(),Poco::Logger::root().getLevel()));
BusEventManager_->Start();
} }
inline void MicroService::StopSubSystemServers() { inline void MicroService::StopSubSystemServers() {
AddActivity("Stopping"); AddActivity("Stopping");
BusEventManager_.Stop(); BusEventManager_->Stop();
for(auto i=SubSystems_.rbegin(); i!=SubSystems_.rend(); ++i) { for(auto i=SubSystems_.rbegin(); i!=SubSystems_.rend(); ++i) {
(*i)->Stop(); (*i)->Stop();
} }
@@ -3907,14 +3959,15 @@ namespace OpenWifi {
} }
} }
inline SubSystemServer::SubSystemServer(std::string Name, const std::string &LoggingPrefix, inline SubSystemServer::SubSystemServer(const std::string &Name, const std::string &LoggingPrefix,
std::string SubSystemConfigPrefix): const std::string &SubSystemConfigPrefix):
Name_(std::move(Name)), Name_(Name),
LoggerPrefix_(LoggingPrefix), LoggerPrefix_(LoggingPrefix),
SubSystemConfigPrefix_(std::move(SubSystemConfigPrefix)) { SubSystemConfigPrefix_(SubSystemConfigPrefix) {
} }
inline int RESTAPI_ExtServer::Start() { inline int RESTAPI_ExtServer::Start() {
Logger().information("Starting.");
Server_.InitLogging(); Server_.InitLogging();
for(const auto & Svr: ConfigServersList_) { for(const auto & Svr: ConfigServersList_) {
@@ -3930,8 +3983,6 @@ namespace OpenWifi {
} }
Poco::Net::HTTPServerParams::Ptr Params = new Poco::Net::HTTPServerParams; Poco::Net::HTTPServerParams::Ptr Params = new Poco::Net::HTTPServerParams;
Params->setMaxThreads(50);
Params->setMaxQueued(200);
Params->setKeepAlive(true); Params->setKeepAlive(true);
Params->setName("ws:xrest"); Params->setName("ws:xrest");
@@ -3946,7 +3997,6 @@ namespace OpenWifi {
NewServer->start(); NewServer->start();
RESTServers_.push_back(std::move(NewServer)); RESTServers_.push_back(std::move(NewServer));
} }
return 0; return 0;
} }
@@ -3967,8 +4017,6 @@ namespace OpenWifi {
} }
auto Params = new Poco::Net::HTTPServerParams; auto Params = new Poco::Net::HTTPServerParams;
Params->setMaxThreads(50);
Params->setMaxQueued(200);
Params->setKeepAlive(true); Params->setKeepAlive(true);
Params->setName("ws:irest"); Params->setName("ws:irest");
@@ -3988,7 +4036,7 @@ namespace OpenWifi {
} }
inline int MicroService::main([[maybe_unused]] const ArgVec &args) { inline int MicroService::main([[maybe_unused]] const ArgVec &args) {
MyErrorHandler ErrorHandler(*this); MicroServiceErrorHandler ErrorHandler(*this);
Poco::ErrorHandler::set(&ErrorHandler); Poco::ErrorHandler::set(&ErrorHandler);
if (!HelpRequested_) { if (!HelpRequested_) {
@@ -4036,7 +4084,11 @@ namespace OpenWifi {
auto i = 0; auto i = 0;
bool good = true; bool good = true;
Log_ = std::make_unique<LoggerWrapper>(Poco::Logger::get(LoggerPrefix_)); auto NewLevel = MicroService::instance().ConfigGetString("logging.level." + Name_, "");
if(NewLevel.empty())
Logger_ = std::make_unique<LoggerWrapper>(Poco::Logger::create(LoggerPrefix_, Poco::Logger::root().getChannel(), Poco::Logger::root().getLevel()));
else
Logger_ = std::make_unique<LoggerWrapper>(Poco::Logger::create(LoggerPrefix_, Poco::Logger::root().getChannel(), Poco::Logger::parseLevel(NewLevel)));
ConfigServersList_.clear(); ConfigServersList_.clear();
while (good) { while (good) {
@@ -4126,9 +4178,11 @@ namespace OpenWifi {
inline void BusEventManager::Stop() { inline void BusEventManager::Stop() {
if(KafkaManager()->Enabled()) { if(KafkaManager()->Enabled()) {
poco_information(Logger(),"Stopping...");
Running_ = false; Running_ = false;
Thread_.wakeUp(); Thread_.wakeUp();
Thread_.join(); Thread_.join();
poco_information(Logger(),"Stopped...");
} }
} }
@@ -4140,37 +4194,37 @@ namespace OpenWifi {
inline void KafkaLoggerFun([[maybe_unused]] cppkafka::KafkaHandleBase & handle, int level, const std::string & facility, const std::string &message) { inline void KafkaLoggerFun([[maybe_unused]] cppkafka::KafkaHandleBase & handle, int level, const std::string & facility, const std::string &message) {
switch ((cppkafka::LogLevel) level) { switch ((cppkafka::LogLevel) level) {
case cppkafka::LogLevel::LogNotice: { case cppkafka::LogLevel::LogNotice: {
KafkaManager()->Logger().notice(fmt::format("kafka-log: facility: {} message: {}",facility, message)); poco_notice(KafkaManager()->Logger(),fmt::format("kafka-log: facility: {} message: {}",facility, message));
} }
break; break;
case cppkafka::LogLevel::LogDebug: { case cppkafka::LogLevel::LogDebug: {
KafkaManager()->Logger().debug(fmt::format("kafka-log: facility: {} message: {}",facility, message)); poco_debug(KafkaManager()->Logger(),fmt::format("kafka-log: facility: {} message: {}",facility, message));
} }
break; break;
case cppkafka::LogLevel::LogInfo: { case cppkafka::LogLevel::LogInfo: {
KafkaManager()->Logger().information(fmt::format("kafka-log: facility: {} message: {}",facility, message)); poco_information(KafkaManager()->Logger(),fmt::format("kafka-log: facility: {} message: {}",facility, message));
} }
break; break;
case cppkafka::LogLevel::LogWarning: { case cppkafka::LogLevel::LogWarning: {
KafkaManager()->Logger().warning(fmt::format("kafka-log: facility: {} message: {}",facility, message)); poco_warning(KafkaManager()->Logger(), fmt::format("kafka-log: facility: {} message: {}",facility, message));
} }
break; break;
case cppkafka::LogLevel::LogAlert: case cppkafka::LogLevel::LogAlert:
case cppkafka::LogLevel::LogCrit: { case cppkafka::LogLevel::LogCrit: {
KafkaManager()->Logger().critical(fmt::format("kafka-log: facility: {} message: {}",facility, message)); poco_critical(KafkaManager()->Logger(),fmt::format("kafka-log: facility: {} message: {}",facility, message));
} }
break; break;
case cppkafka::LogLevel::LogErr: case cppkafka::LogLevel::LogErr:
case cppkafka::LogLevel::LogEmerg: case cppkafka::LogLevel::LogEmerg:
default: { default: {
KafkaManager()->Logger().error(fmt::format("kafka-log: facility: {} message: {}",facility, message)); poco_error(KafkaManager()->Logger(),fmt::format("kafka-log: facility: {} message: {}",facility, message));
} }
break; break;
} }
} }
inline void KafkaErrorFun([[maybe_unused]] cppkafka::KafkaHandleBase & handle, int error, const std::string &reason) { inline void KafkaErrorFun([[maybe_unused]] cppkafka::KafkaHandleBase & handle, int error, const std::string &reason) {
KafkaManager()->Logger().error(fmt::format("kafka-error: {}, reason: {}", error, reason)); poco_error(KafkaManager()->Logger(),fmt::format("kafka-error: {}, reason: {}", error, reason));
} }
inline void AddKafkaSecurity(cppkafka::Configuration & Config) { inline void AddKafkaSecurity(cppkafka::Configuration & Config) {
@@ -4219,11 +4273,11 @@ namespace OpenWifi {
cppkafka::MessageBuilder(Msg->Topic()).key(Msg->Key()).payload(Msg->Payload())); cppkafka::MessageBuilder(Msg->Topic()).key(Msg->Key()).payload(Msg->Payload()));
} }
} catch (const cppkafka::HandleException &E) { } catch (const cppkafka::HandleException &E) {
KafkaManager()->Logger().warning(fmt::format("Caught a Kafka exception (producer): {}", E.what())); poco_warning(KafkaManager()->Logger(),fmt::format("Caught a Kafka exception (producer): {}", E.what()));
} catch( const Poco::Exception &E) { } catch( const Poco::Exception &E) {
KafkaManager()->Logger().log(E); KafkaManager()->Logger().log(E);
} catch (...) { } catch (...) {
KafkaManager()->Logger().error("std::exception"); poco_error(KafkaManager()->Logger(),"std::exception");
} }
Note = Queue_.waitDequeueNotification(); Note = Queue_.waitDequeueNotification();
} }
@@ -4283,7 +4337,7 @@ namespace OpenWifi {
continue; continue;
if (Msg.get_error()) { if (Msg.get_error()) {
if (!Msg.is_eof()) { if (!Msg.is_eof()) {
KafkaManager()->Logger().error(fmt::format("Error: {}", Msg.get_error().to_string())); poco_error(KafkaManager()->Logger(),fmt::format("Error: {}", Msg.get_error().to_string()));
} }
if(!AutoCommit) if(!AutoCommit)
Consumer.async_commit(Msg); Consumer.async_commit(Msg);
@@ -4294,11 +4348,11 @@ namespace OpenWifi {
Consumer.async_commit(Msg); Consumer.async_commit(Msg);
} }
} catch (const cppkafka::HandleException &E) { } catch (const cppkafka::HandleException &E) {
KafkaManager()->Logger().warning(fmt::format("Caught a Kafka exception (consumer): {}", E.what())); poco_warning(KafkaManager()->Logger(),fmt::format("Caught a Kafka exception (consumer): {}", E.what()));
} catch (const Poco::Exception &E) { } catch (const Poco::Exception &E) {
KafkaManager()->Logger().log(E); KafkaManager()->Logger().log(E);
} catch (...) { } catch (...) {
KafkaManager()->Logger().error("std::exception"); poco_error(KafkaManager()->Logger(),"std::exception");
} }
} }
Consumer.unsubscribe(); Consumer.unsubscribe();
@@ -4742,7 +4796,7 @@ namespace OpenWifi {
} }
#ifdef TIP_SECURITY_SERVICE #ifdef TIP_SECURITY_SERVICE
[[nodiscard]] bool AuthServiceIsAuthorized(Poco::Net::HTTPServerRequest & Request,std::string &SessionToken, SecurityObjects::UserInfoAndPolicy & UInfo, bool & Expired , bool Sub ); [[nodiscard]] bool AuthServiceIsAuthorized(Poco::Net::HTTPServerRequest & Request,std::string &SessionToken, SecurityObjects::UserInfoAndPolicy & UInfo, std::uint64_t TID, bool & Expired , bool Sub );
#endif #endif
inline bool RESTAPIHandler::IsAuthorized( bool & Expired , [[maybe_unused]] bool & Contacted , bool Sub ) { inline bool RESTAPIHandler::IsAuthorized( bool & Expired , [[maybe_unused]] bool & Contacted , bool Sub ) {
if(Internal_ && Request->has("X-INTERNAL-NAME")) { if(Internal_ && Request->has("X-INTERNAL-NAME")) {
@@ -4750,17 +4804,20 @@ namespace OpenWifi {
Contacted = true; Contacted = true;
if(!Allowed) { if(!Allowed) {
if(Server_.LogBadTokens(false)) { if(Server_.LogBadTokens(false)) {
Logger_.debug(fmt::format("I-REQ-DENIED({}): Method={} Path={}", poco_debug(Logger_,fmt::format("I-REQ-DENIED({}): TID={} Method={} Path={}",
Utils::FormatIPv6(Request->clientAddress().toString()), Utils::FormatIPv6(Request->clientAddress().toString()),
Request->getMethod(), Request->getURI())); TransactionId_,
Request->getMethod(), Request->getURI()));
} }
} else { } else {
auto Id = Request->get("X-INTERNAL-NAME", "unknown"); auto Id = Request->get("X-INTERNAL-NAME", "unknown");
REST_Requester_ = Id; REST_Requester_ = Id;
if(Server_.LogIt(Request->getMethod(),true)) { if(Server_.LogIt(Request->getMethod(),true)) {
Logger_.debug(fmt::format("I-REQ-ALLOWED({}): User='{}' Method={} Path={}", poco_debug(Logger_,fmt::format("I-REQ-ALLOWED({}): TID={} User='{}' Method={} Path={}",
Utils::FormatIPv6(Request->clientAddress().toString()), Id, Utils::FormatIPv6(Request->clientAddress().toString()),
Request->getMethod(), Request->getURI())); TransactionId_,
Id,
Request->getMethod(), Request->getURI()));
} }
} }
return Allowed; return Allowed;
@@ -4776,25 +4833,28 @@ namespace OpenWifi {
} }
} }
#ifdef TIP_SECURITY_SERVICE #ifdef TIP_SECURITY_SERVICE
if (AuthServiceIsAuthorized(*Request, SessionToken_, UserInfo_, Expired, Sub)) { if (AuthServiceIsAuthorized(*Request, SessionToken_, UserInfo_, TransactionId_, Expired, Sub)) {
#else #else
if (AuthClient()->IsAuthorized( SessionToken_, UserInfo_, Expired, Contacted, Sub)) { if (AuthClient()->IsAuthorized( SessionToken_, UserInfo_, TransactionId_, Expired, Contacted, Sub)) {
#endif #endif
REST_Requester_ = UserInfo_.userinfo.email; REST_Requester_ = UserInfo_.userinfo.email;
if(Server_.LogIt(Request->getMethod(),true)) { if(Server_.LogIt(Request->getMethod(),true)) {
Logger_.debug(fmt::format("X-REQ-ALLOWED({}): User='{}@{}' Method={} Path={}", poco_debug(Logger_,fmt::format("X-REQ-ALLOWED({}): TID={} User='{}@{}' Method={} Path={}",
UserInfo_.userinfo.email, UserInfo_.userinfo.email,
Utils::FormatIPv6(Request->clientAddress().toString()), TransactionId_,
Request->clientAddress().toString(), Utils::FormatIPv6(Request->clientAddress().toString()),
Request->getMethod(), Request->clientAddress().toString(),
Request->getURI())); Request->getMethod(),
Request->getURI()));
} }
return true; return true;
} else { } else {
if(Server_.LogBadTokens(true)) { if(Server_.LogBadTokens(true)) {
Logger_.debug(fmt::format("X-REQ-DENIED({}): Method={} Path={}", poco_debug(Logger_,fmt::format("X-REQ-DENIED({}): TID={} Method={} Path={}",
Utils::FormatIPv6(Request->clientAddress().toString()), Utils::FormatIPv6(Request->clientAddress().toString()),
Request->getMethod(), Request->getURI())); TransactionId_,
Request->getMethod(),
Request->getURI()));
} }
} }
return false; return false;
@@ -4863,7 +4923,7 @@ namespace OpenWifi {
void run() override; void run() override;
// MyParallelSocketReactor &ReactorPool(); // MyParallelSocketReactor &ReactorPool();
Poco::Net::SocketReactor & Reactor() { return Reactor_; } Poco::Net::SocketReactor & Reactor() { return Reactor_; }
void NewClient(Poco::Net::WebSocket &WS, const std::string &Id); void NewClient(Poco::Net::WebSocket &WS, const std::string &Id, const std::string &UserName);
bool Register(WebSocketClient *Client, const std::string &Id); bool Register(WebSocketClient *Client, const std::string &Id);
void SetProcessor(WebSocketClientProcessor *F); void SetProcessor(WebSocketClientProcessor *F);
void UnRegister(const std::string &Id); void UnRegister(const std::string &Id);
@@ -4914,18 +4974,22 @@ namespace OpenWifi {
class WebSocketClient { class WebSocketClient {
public: public:
explicit WebSocketClient(Poco::Net::WebSocket &WS, const std::string &Id, Poco::Logger &L, explicit WebSocketClient(Poco::Net::WebSocket &WS,
WebSocketClientProcessor *Processor); const std::string &Id,
const std::string &UserName,
Poco::Logger &L,
WebSocketClientProcessor *Processor);
virtual ~WebSocketClient(); virtual ~WebSocketClient();
[[nodiscard]] inline const std::string &Id(); [[nodiscard]] inline const std::string &Id();
[[nodiscard]] Poco::Logger &Logger(); [[nodiscard]] Poco::Logger &Logger();
inline bool Send(const std::string &Payload); inline bool Send(const std::string &Payload);
private: private:
std::unique_ptr<Poco::Net::WebSocket> WS_; std::unique_ptr<Poco::Net::WebSocket> WS_;
Poco::Net::SocketReactor &Reactor_; Poco::Net::SocketReactor &Reactor_;
std::string Id_; std::string Id_;
Poco::Logger &Logger_; std::string UserName_;
bool Authenticated_ = false; Poco::Logger &Logger_;
std::atomic_bool Authenticated_ = false;
SecurityObjects::UserInfoAndPolicy UserInfo_; SecurityObjects::UserInfoAndPolicy UserInfo_;
WebSocketClientProcessor *Processor_ = nullptr; WebSocketClientProcessor *Processor_ = nullptr;
void OnSocketReadable(const Poco::AutoPtr<Poco::Net::ReadableNotification> &pNf); void OnSocketReadable(const Poco::AutoPtr<Poco::Net::ReadableNotification> &pNf);
@@ -4933,33 +4997,9 @@ namespace OpenWifi {
void OnSocketError(const Poco::AutoPtr<Poco::Net::ErrorNotification> &pNf); void OnSocketError(const Poco::AutoPtr<Poco::Net::ErrorNotification> &pNf);
}; };
/* inline MyParallelSocketReactor::MyParallelSocketReactor(uint32_t NumReactors) : inline void WebSocketClientServer::NewClient(Poco::Net::WebSocket & WS, const std::string &Id, const std::string &UserName ) {
NumReactors_(NumReactors)
{
Reactors_ = new Poco::Net::SocketReactor[NumReactors_];
for(uint32_t i=0;i<NumReactors_;i++) {
ReactorPool_.start(Reactors_[i]);
}
}
inline MyParallelSocketReactor::~MyParallelSocketReactor() {
for(uint32_t i=0;i<NumReactors_;i++) {
Reactors_[i].stop();
}
ReactorPool_.stopAll();
ReactorPool_.joinAll();
delete [] Reactors_;
}
inline Poco::Net::SocketReactor & MyParallelSocketReactor::Reactor() {
return Reactors_[ rand() % NumReactors_ ];
}
// inline MyParallelSocketReactor & WebSocketClientServer::ReactorPool() { return *ReactorPool_; }
*/
inline void WebSocketClientServer::NewClient(Poco::Net::WebSocket & WS, const std::string &Id) {
std::lock_guard G(Mutex_); std::lock_guard G(Mutex_);
auto Client = new WebSocketClient(WS,Id,Logger(), Processor_); auto Client = new WebSocketClient(WS,Id,UserName,Logger(), Processor_);
Clients_[Id] = std::make_pair(Client,""); Clients_[Id] = std::make_pair(Client,"");
} }
@@ -5076,6 +5116,7 @@ namespace OpenWifi {
auto Op = flags & Poco::Net::WebSocket::FRAME_OP_BITMASK; auto Op = flags & Poco::Net::WebSocket::FRAME_OP_BITMASK;
if (n == 0) { if (n == 0) {
poco_debug(Logger(),fmt::format("CLOSE({}): {} UI Client is closing WS connection.", Id_, UserName_));
return delete this; return delete this;
} }
@@ -5088,7 +5129,7 @@ namespace OpenWifi {
case Poco::Net::WebSocket::FRAME_OP_PONG: { case Poco::Net::WebSocket::FRAME_OP_PONG: {
} break; } break;
case Poco::Net::WebSocket::FRAME_OP_CLOSE: { case Poco::Net::WebSocket::FRAME_OP_CLOSE: {
Logger().warning(Poco::format("CLOSE(%s): UI Client is closing its connection.", Id_)); poco_debug(Logger(),fmt::format("CLOSE({}): {} UI Client is closing WS connection.", Id_, UserName_));
Done = true; Done = true;
} break; } break;
case Poco::Net::WebSocket::FRAME_OP_TEXT: { case Poco::Net::WebSocket::FRAME_OP_TEXT: {
@@ -5098,8 +5139,10 @@ namespace OpenWifi {
auto Tokens = Utils::Split(Frame, ':'); auto Tokens = Utils::Split(Frame, ':');
bool Expired = false, Contacted = false; bool Expired = false, Contacted = false;
if (Tokens.size() == 2 && if (Tokens.size() == 2 &&
AuthClient()->IsAuthorized(Tokens[1], UserInfo_, Expired, Contacted)) { AuthClient()->IsAuthorized(Tokens[1], UserInfo_, 0, Expired, Contacted)) {
Authenticated_ = true; Authenticated_ = true;
UserName_ = UserInfo_.userinfo.email;
poco_debug(Logger(),fmt::format("START({}): {} UI Client is starting WS connection.", Id_, UserName_));
std::string S{"Welcome! Bienvenue! Bienvenidos!"}; std::string S{"Welcome! Bienvenue! Bienvenidos!"};
WS_->sendFrame(S.c_str(), S.size()); WS_->sendFrame(S.c_str(), S.size());
WebSocketClientServer()->SetUser(Id_, UserInfo_.userinfo.email); WebSocketClientServer()->SetUser(Id_, UserInfo_.userinfo.email);
@@ -5145,9 +5188,10 @@ namespace OpenWifi {
} }
inline WebSocketClient::WebSocketClient( Poco::Net::WebSocket & WS , const std::string &Id, Poco::Logger & L, WebSocketClientProcessor * Processor) : inline WebSocketClient::WebSocketClient( Poco::Net::WebSocket & WS , const std::string &Id, const std::string &UserName, Poco::Logger & L, WebSocketClientProcessor * Processor) :
Reactor_(WebSocketClientServer()->Reactor()), Reactor_(WebSocketClientServer()->Reactor()),
Id_(Id), Id_(Id),
UserName_(UserName),
Logger_(L), Logger_(L),
Processor_(Processor) { Processor_(Processor) {
try { try {
@@ -5161,7 +5205,10 @@ namespace OpenWifi {
Reactor_.addEventHandler(*WS_, Reactor_.addEventHandler(*WS_,
Poco::NObserver<WebSocketClient, Poco::Net::ErrorNotification>( Poco::NObserver<WebSocketClient, Poco::Net::ErrorNotification>(
*this, &WebSocketClient::OnSocketError)); *this, &WebSocketClient::OnSocketError));
// WebSocketClientServer()->Register(this, Id_); WS_->setNoDelay(true);
WS_->setKeepAlive(true);
WS_->setBlocking(false);
} catch (...) { } catch (...) {
delete this; delete this;
} }
@@ -5181,7 +5228,6 @@ namespace OpenWifi {
Poco::Net::ErrorNotification>(*this,&WebSocketClient::OnSocketError)); Poco::Net::ErrorNotification>(*this,&WebSocketClient::OnSocketError));
(*WS_).shutdown(); (*WS_).shutdown();
(*WS_).close(); (*WS_).close();
WebSocketClientServer()->UnRegister(Id_);
} catch(...) { } catch(...) {
} }
@@ -5227,9 +5273,8 @@ namespace OpenWifi {
try try
{ {
Poco::Net::WebSocket WS(*Request, *Response); Poco::Net::WebSocket WS(*Request, *Response);
Logger().information("UI-WebSocket connection established.");
auto Id = MicroService::CreateUUID(); auto Id = MicroService::CreateUUID();
WebSocketClientServer()->NewClient(WS,Id); WebSocketClientServer()->NewClient(WS,Id,UserInfo_.userinfo.email);
} }
catch (...) { catch (...) {
std::cout << "Cannot create websocket client..." << std::endl; std::cout << "Cannot create websocket client..." << std::endl;

View File

@@ -33,7 +33,6 @@ namespace OpenWifi {
int Start() override { int Start() override {
std::lock_guard Guard(Mutex_); std::lock_guard Guard(Mutex_);
Logger().setLevel(Poco::Message::PRIO_INFORMATION);
Logger().notice("Starting."); Logger().notice("Starting.");
std::string DBType = MicroService::instance().ConfigGetString("storage.type"); std::string DBType = MicroService::instance().ConfigGetString("storage.type");

View File

@@ -69,6 +69,41 @@ namespace OpenWifi {
} }
}; };
struct WebSocketClientNotificationNumberOfConnection {
std::uint64_t numberOfDevices=0;
std::uint64_t averageConnectedTime=0;
std::uint64_t numberOfConnectingDevices=0;
inline void to_json(Poco::JSON::Object &Obj) const {
RESTAPI_utils::field_to_json(Obj,"numberOfDevices", numberOfDevices);
RESTAPI_utils::field_to_json(Obj,"averageConnectedTime", averageConnectedTime);
RESTAPI_utils::field_to_json(Obj,"numberOfConnectingDevices", numberOfConnectingDevices);
}
inline bool from_json(const Poco::JSON::Object::Ptr &Obj) {
try {
RESTAPI_utils::field_from_json(Obj,"numberOfDevices", numberOfDevices);
RESTAPI_utils::field_from_json(Obj,"averageConnectedTime", averageConnectedTime);
RESTAPI_utils::field_from_json(Obj,"numberOfConnectingDevices", numberOfConnectingDevices);
return true;
} catch (...) {
}
return false;
}
};
inline void WebSocketClientNotificationNumberOfConnections(std::uint64_t numberOfDevices,
std::uint64_t averageConnectedTime,
std::uint64_t numberOfConnectingDevices) {
WebSocketNotification<WebSocketClientNotificationNumberOfConnection> N;
N.content.numberOfDevices = numberOfDevices;
N.content.averageConnectedTime = averageConnectedTime;
N.content.numberOfConnectingDevices = numberOfConnectingDevices;
N.type = "device_connections_statistics";
WebSocketClientServer()->SendNotification(N);
}
inline void WebSocketClientNotificationDeviceConfigurationChange(const std::string &SerialNumber, uint64_t oldUUID, uint64_t newUUID) { inline void WebSocketClientNotificationDeviceConfigurationChange(const std::string &SerialNumber, uint64_t oldUUID, uint64_t newUUID) {
WebSocketNotification<WebNotificationSingleDeviceConfigurationChange> N; WebSocketNotification<WebNotificationSingleDeviceConfigurationChange> N;
N.content.serialNumber = SerialNumber; N.content.serialNumber = SerialNumber;
@@ -146,6 +181,10 @@ namespace OpenWifi {
WebSocketClientServer()->SendUserNotification(User,N); WebSocketClientServer()->SendUserNotification(User,N);
} }
/////
/////
/////
struct WebSocketNotificationRebootList { struct WebSocketNotificationRebootList {
std::string title, std::string title,
details, details,
@@ -189,5 +228,58 @@ namespace OpenWifi {
WebSocketClientServer()->SendUserNotification(User,N); WebSocketClientServer()->SendUserNotification(User,N);
} }
/////
/////
/////
struct WebSocketNotificationUpgradeList {
std::string title,
details,
jobId;
std::vector<std::string> success,
skipped,
no_firmware,
not_connected;
uint64_t timeStamp=OpenWifi::Now();
void to_json(Poco::JSON::Object &Obj) const;
bool from_json(const Poco::JSON::Object::Ptr &Obj);
};
typedef WebSocketNotification<WebSocketNotificationUpgradeList> WebSocketClientNotificationVenueUpgradeList_t;
inline void WebSocketNotificationUpgradeList::to_json(Poco::JSON::Object &Obj) const {
RESTAPI_utils::field_to_json(Obj,"title",title);
RESTAPI_utils::field_to_json(Obj,"jobId",jobId);
RESTAPI_utils::field_to_json(Obj,"success",success);
RESTAPI_utils::field_to_json(Obj,"notConnected",not_connected);
RESTAPI_utils::field_to_json(Obj,"noFirmware",no_firmware);
RESTAPI_utils::field_to_json(Obj,"skipped",skipped);
RESTAPI_utils::field_to_json(Obj,"timeStamp",timeStamp);
RESTAPI_utils::field_to_json(Obj,"details",details);
}
inline bool WebSocketNotificationUpgradeList::from_json(const Poco::JSON::Object::Ptr &Obj) {
try {
RESTAPI_utils::field_from_json(Obj,"title",title);
RESTAPI_utils::field_from_json(Obj,"jobId",jobId);
RESTAPI_utils::field_from_json(Obj,"success",success);
RESTAPI_utils::field_from_json(Obj,"notConnected",not_connected);
RESTAPI_utils::field_from_json(Obj,"noFirmware",no_firmware);
RESTAPI_utils::field_from_json(Obj,"skipped",skipped);
RESTAPI_utils::field_from_json(Obj,"timeStamp",timeStamp);
RESTAPI_utils::field_from_json(Obj,"details",details);
return true;
} catch(...) {
}
return false;
}
inline void WebSocketClientNotificationVenueUpgradeCompletionToUser( const std::string & User, WebSocketClientNotificationVenueUpgradeList_t &N) {
N.type = "venue_upgrader";
WebSocketClientServer()->SendUserNotification(User,N);
}
} // namespace OpenWifi } // namespace OpenWifi

View File

@@ -197,6 +197,7 @@ namespace OpenWifi::RESTAPI::Errors {
static const struct msg InvalidRadiusServerWeigth{1143,"RADIUS Server IP weight cannot be 0."}; static const struct msg InvalidRadiusServerWeigth{1143,"RADIUS Server IP weight cannot be 0."};
static const struct msg MaximumRTTYSessionsReached{1144,"Too many RTTY sessions currently active"}; static const struct msg MaximumRTTYSessionsReached{1144,"Too many RTTY sessions currently active"};
static const struct msg DeviceIsAlreadyBusy{1145,"Device is already executing a command. Please try later."};
} }

View File

@@ -18,48 +18,52 @@ namespace OpenWifi {
Id_(Id), Id_(Id),
Logger_(Poco::Logger::get(fmt::format("RTTY-client({})",Id_))) Logger_(Poco::Logger::get(fmt::format("RTTY-client({})",Id_)))
{ {
Logger_.information("Starting connection");
Valid_ = true; Valid_ = true;
WS_ = std::make_unique<Poco::Net::WebSocket>(request,response); WS_ = std::make_unique<Poco::Net::WebSocket>(request,response);
WS_->setBlocking(false);
WS_->setNoDelay(true);
WS_->setKeepAlive(true);
Registered_ = true;
Reactor_.addEventHandler( Reactor_.addEventHandler(
*WS_, Poco::NObserver<RTTYS_ClientConnection, Poco::Net::ReadableNotification>( *WS_, Poco::NObserver<RTTYS_ClientConnection, Poco::Net::ReadableNotification>(
*this, &RTTYS_ClientConnection::onSocketReadable)); *this, &RTTYS_ClientConnection::onSocketReadable));
Reactor_.addEventHandler( Reactor_.addEventHandler(
*WS_, Poco::NObserver<RTTYS_ClientConnection, Poco::Net::ShutdownNotification>( *WS_, Poco::NObserver<RTTYS_ClientConnection, Poco::Net::ShutdownNotification>(
*this, &RTTYS_ClientConnection::onSocketShutdown)); *this, &RTTYS_ClientConnection::onSocketShutdown));
Logger_.information("Starting connection");
} }
RTTYS_ClientConnection::~RTTYS_ClientConnection() { RTTYS_ClientConnection::~RTTYS_ClientConnection() {
if(Valid_) { poco_information(Logger_,
std::unique_lock G(Mutex_); fmt::format("Client {} session ending", Id_)
EndConnection(false); );
DeRegister();
}
void RTTYS_ClientConnection::DeRegister() {
Valid_ = false;
if(Registered_) {
Registered_ = false;
Reactor_.removeEventHandler(
*WS_, Poco::NObserver<RTTYS_ClientConnection, Poco::Net::ReadableNotification>(
*this, &RTTYS_ClientConnection::onSocketReadable));
Reactor_.removeEventHandler(
*WS_, Poco::NObserver<RTTYS_ClientConnection, Poco::Net::ShutdownNotification>(
*this, &RTTYS_ClientConnection::onSocketShutdown));
} }
} }
void RTTYS_ClientConnection::EndConnection(bool SendNotification) { void RTTYS_ClientConnection::EndConnection() {
if(Valid_) { DeRegister();
Valid_=false; RTTYS_server()->NotifyClientDisconnect(Id_, this);
try {
Reactor_.removeEventHandler(
*WS_, Poco::NObserver<RTTYS_ClientConnection, Poco::Net::ReadableNotification>(
*this, &RTTYS_ClientConnection::onSocketReadable));
Reactor_.removeEventHandler(
*WS_, Poco::NObserver<RTTYS_ClientConnection, Poco::Net::ShutdownNotification>(
*this, &RTTYS_ClientConnection::onSocketShutdown));
if (SendNotification)
RTTYS_server()->NotifyClientDisconnect(Id_, this);
} catch(...) {
}
Logger_.information("Disconnected.");
}
} }
void RTTYS_ClientConnection::onSocketReadable([[maybe_unused]] const Poco::AutoPtr<Poco::Net::ReadableNotification> &pNf) { void RTTYS_ClientConnection::onSocketReadable([[maybe_unused]] const Poco::AutoPtr<Poco::Net::ReadableNotification> &pNf) {
bool MustDisconnect = false; bool MustDisconnect = false;
{ {
if(!Valid_ || !Registered_)
return;
std::shared_lock G(Mutex_); std::shared_lock G(Mutex_);
try { try {
int flags; int flags;
@@ -129,13 +133,12 @@ namespace OpenWifi {
} }
if(MustDisconnect) { if(MustDisconnect) {
std::unique_lock G(Mutex_);
EndConnection(); EndConnection();
} }
} }
void RTTYS_ClientConnection::SendData( const u_char *Buf, size_t len ) { void RTTYS_ClientConnection::SendData( const u_char *Buf, size_t len ) {
if(!Valid_) if(!Valid_ || !Registered_)
return; return;
try { try {
WS_->sendFrame(Buf, len, WS_->sendFrame(Buf, len,
@@ -145,12 +148,11 @@ namespace OpenWifi {
} catch (...) { } catch (...) {
Logger_.information("SendData shutdown."); Logger_.information("SendData shutdown.");
} }
std::unique_lock G(Mutex_);
EndConnection(); EndConnection();
} }
void RTTYS_ClientConnection::SendData( const std::string &s) { void RTTYS_ClientConnection::SendData( const std::string &s) {
if(!Valid_) if(!Valid_ || !Registered_)
return; return;
try { try {
WS_->sendFrame(s.c_str(), s.length()); WS_->sendFrame(s.c_str(), s.length());
@@ -158,13 +160,11 @@ namespace OpenWifi {
} catch (...) { } catch (...) {
Logger_.information("SendData shutdown."); Logger_.information("SendData shutdown.");
} }
std::unique_lock G(Mutex_);
EndConnection(); EndConnection();
} }
void RTTYS_ClientConnection::onSocketShutdown([[maybe_unused]] const Poco::AutoPtr<Poco::Net::ShutdownNotification> &pNf) { void RTTYS_ClientConnection::onSocketShutdown([[maybe_unused]] const Poco::AutoPtr<Poco::Net::ShutdownNotification> &pNf) {
Logger_.information("Socket shutdown."); Logger_.information("Socket shutdown.");
std::unique_lock G(Mutex_);
EndConnection(); EndConnection();
} }

View File

@@ -27,6 +27,7 @@ namespace OpenWifi {
void SendData( const u_char *Buf, size_t len ); void SendData( const u_char *Buf, size_t len );
void SendData( const std::string & S ); void SendData( const std::string & S );
void DeRegister();
[[nodiscard]] inline std::string ID() { return Id_; } [[nodiscard]] inline std::string ID() { return Id_; }
[[nodiscard]] inline bool Valid() { return Valid_; } [[nodiscard]] inline bool Valid() { return Valid_; }
@@ -37,10 +38,11 @@ namespace OpenWifi {
std::unique_ptr<Poco::Net::WebSocket> WS_; std::unique_ptr<Poco::Net::WebSocket> WS_;
Poco::Logger &Logger_; Poco::Logger &Logger_;
std::string Sid_; std::string Sid_;
std::atomic_bool Valid_=false;
std::shared_mutex Mutex_; std::shared_mutex Mutex_;
volatile bool Valid_=false;
volatile bool Registered_=false;
void EndConnection(bool SendNotification=true); void EndConnection();
}; };
} }

View File

@@ -32,7 +32,7 @@ namespace OpenWifi {
try { try {
RTTYS_server()->CreateNewClient(request,response,T[2]); RTTYS_server()->CreateNewClient(request,response,T[2]);
} catch (...) { } catch (...) {
Logger_.warning("Exception during WS creation"); poco_warning(Logger_,"Exception during WS creation");
} }
}; };

View File

@@ -58,6 +58,11 @@ namespace OpenWifi {
poco_information(Logger(), "Secure connection."); poco_information(Logger(), "Secure connection.");
} }
socket_.setBlocking(false);
socket_.setKeepAlive(true);
socket_.setNoDelay(true);
registered_=true;
reactor_.addEventHandler( reactor_.addEventHandler(
socket_, socket_,
Poco::NObserver<RTTYS_Device_ConnectionHandler, Poco::Net::ReadableNotification>( Poco::NObserver<RTTYS_Device_ConnectionHandler, Poco::Net::ReadableNotification>(
@@ -74,32 +79,31 @@ namespace OpenWifi {
} }
RTTYS_Device_ConnectionHandler::~RTTYS_Device_ConnectionHandler() { RTTYS_Device_ConnectionHandler::~RTTYS_Device_ConnectionHandler() {
if(valid_) { poco_information(Logger_,
std::unique_lock G(M_); fmt::format("Device {} session ending", id_)
poco_warning(Logger(), "Device connection being deleted."); );
EndConnection(false); DeRegister();
}
void RTTYS_Device_ConnectionHandler::DeRegister() {
if(registered_) {
registered_ = false;
reactor_.removeEventHandler(
socket_,
Poco::NObserver<RTTYS_Device_ConnectionHandler, Poco::Net::ReadableNotification>(
*this, &RTTYS_Device_ConnectionHandler::onSocketReadable));
reactor_.removeEventHandler(
socket_,
Poco::NObserver<RTTYS_Device_ConnectionHandler, Poco::Net::ShutdownNotification>(
*this, &RTTYS_Device_ConnectionHandler::onSocketShutdown));
} }
} }
void RTTYS_Device_ConnectionHandler::EndConnection(bool SendNotification) { void RTTYS_Device_ConnectionHandler::EndConnection() {
try { if(valid_) {
if(valid_) { valid_ = false;
valid_ = false; DeRegister();
reactor_.removeEventHandler( RTTYS_server()->NotifyDeviceDisconnect(id_, this);
socket_,
Poco::NObserver<RTTYS_Device_ConnectionHandler, Poco::Net::ReadableNotification>(
*this, &RTTYS_Device_ConnectionHandler::onSocketReadable));
reactor_.removeEventHandler(
socket_,
Poco::NObserver<RTTYS_Device_ConnectionHandler, Poco::Net::ShutdownNotification>(
*this, &RTTYS_Device_ConnectionHandler::onSocketShutdown));
if(SendNotification)
RTTYS_server()->NotifyDeviceDisconnect(id_,this);
poco_information(Logger(), "Connection done.");
socket_.close();
}
} catch (...) {
} }
} }
@@ -115,6 +119,9 @@ namespace OpenWifi {
void RTTYS_Device_ConnectionHandler::onSocketReadable([[maybe_unused]] const Poco::AutoPtr<Poco::Net::ReadableNotification> &pNf) { void RTTYS_Device_ConnectionHandler::onSocketReadable([[maybe_unused]] const Poco::AutoPtr<Poco::Net::ReadableNotification> &pNf) {
bool good = true; bool good = true;
if(!valid_ || !registered_)
return;
std::unique_lock G(M_); std::unique_lock G(M_);
try { try {
auto received_bytes = socket_.receiveBytes(inBuf_); auto received_bytes = socket_.receiveBytes(inBuf_);
@@ -196,7 +203,6 @@ namespace OpenWifi {
} }
void RTTYS_Device_ConnectionHandler::onSocketShutdown([[maybe_unused]] const Poco::AutoPtr<Poco::Net::ShutdownNotification>& pNf) { void RTTYS_Device_ConnectionHandler::onSocketShutdown([[maybe_unused]] const Poco::AutoPtr<Poco::Net::ShutdownNotification>& pNf) {
std::unique_lock G(M_);
poco_information(Logger(),fmt::format("{}: Connection being closed - socket shutdown.",id_)); poco_information(Logger(),fmt::format("{}: Connection being closed - socket shutdown.",id_));
EndConnection(); EndConnection();
} }
@@ -214,11 +220,13 @@ namespace OpenWifi {
} }
bool RTTYS_Device_ConnectionHandler::SendToClient(const std::string &S) { bool RTTYS_Device_ConnectionHandler::SendToClient(const std::string &S) {
if(!valid_ || !registered_)
return false;
return RTTYS_server()->SendToClient(id_,S); return RTTYS_server()->SendToClient(id_,S);
} }
bool RTTYS_Device_ConnectionHandler::KeyStrokes(const u_char *buf, size_t len) { bool RTTYS_Device_ConnectionHandler::KeyStrokes(const u_char *buf, size_t len) {
if(!valid_) if(!valid_ || !registered_)
return false; return false;
if(len<=(sizeof(small_buf_)-RTTY_HDR_SIZE-session_length_)) { if(len<=(sizeof(small_buf_)-RTTY_HDR_SIZE-session_length_)) {
@@ -250,7 +258,7 @@ namespace OpenWifi {
} }
bool RTTYS_Device_ConnectionHandler::WindowSize(int cols, int rows) { bool RTTYS_Device_ConnectionHandler::WindowSize(int cols, int rows) {
if(!valid_) if(!valid_ || !registered_)
return false; return false;
u_char outBuf[8+RTTY_SESSION_ID_LENGTH]{0}; u_char outBuf[8+RTTY_SESSION_ID_LENGTH]{0};
@@ -272,7 +280,7 @@ namespace OpenWifi {
} }
bool RTTYS_Device_ConnectionHandler::Login() { bool RTTYS_Device_ConnectionHandler::Login() {
if(!valid_) if(!valid_ || !registered_)
return false; return false;
u_char outBuf[RTTY_HDR_SIZE+RTTY_SESSION_ID_LENGTH]{0}; u_char outBuf[RTTY_HDR_SIZE+RTTY_SESSION_ID_LENGTH]{0};
@@ -297,7 +305,7 @@ namespace OpenWifi {
} }
bool RTTYS_Device_ConnectionHandler::Logout() { bool RTTYS_Device_ConnectionHandler::Logout() {
if(!valid_) if(!valid_ || !registered_)
return false; return false;
u_char outBuf[4+RTTY_SESSION_ID_LENGTH]{0}; u_char outBuf[4+RTTY_SESSION_ID_LENGTH]{0};

View File

@@ -67,10 +67,12 @@ namespace OpenWifi {
std::uint64_t session_length_=1; std::uint64_t session_length_=1;
std::size_t waiting_for_bytes_{0}; std::size_t waiting_for_bytes_{0};
u_char last_command_=0; u_char last_command_=0;
std::atomic_bool registered_=false;
unsigned char small_buf_[64+RTTY_SESSION_ID_LENGTH]; unsigned char small_buf_[64+RTTY_SESSION_ID_LENGTH];
void EndConnection(bool SendNotification=true) ; void EndConnection() ;
void CompleteConnection(); void CompleteConnection();
void DeRegister();
[[nodiscard]] bool do_msgTypeRegister(std::size_t msg_len); [[nodiscard]] bool do_msgTypeRegister(std::size_t msg_len);
[[nodiscard]] bool do_msgTypeLogin(std::size_t msg_len); [[nodiscard]] bool do_msgTypeLogin(std::size_t msg_len);

View File

@@ -87,34 +87,28 @@ namespace OpenWifi {
} }
void RTTYS_server::Stop() { void RTTYS_server::Stop() {
Timer_.stop();
if(Internal_) { if(Internal_) {
ClientReactor_.stop();
ClientReactorThread_.join();
DeviceReactor_.stop();
DeviceAcceptor_->unregisterAcceptor();
DeviceReactorThread_.join();
NotificationManagerRunning_=false;
ResponseQueue_.wakeUpAll(); ResponseQueue_.wakeUpAll();
NotificationManager_.wakeUp(); NotificationManager_.wakeUp();
NotificationManager_.join(); NotificationManager_.join();
WebServer_->stopAll(true);
Timer_.stop();
WebServer_->stopAll();
WebServer_->stop(); WebServer_->stop();
ClientReactor_.stop();
ClientReactorThread_.join();
DeviceReactor_.stop();
DeviceAcceptor_->unregisterAcceptor();
DeviceReactorThread_.join();
NotificationManagerRunning_ = false;
} }
} }
void RTTYS_server::onTimer([[maybe_unused]] Poco::Timer & timer) { void RTTYS_server::onTimer([[maybe_unused]] Poco::Timer & timer) {
poco_debug(Logger(),"Removing stale connections."); poco_trace(Logger(),"Removing stale connections.");
Utils::SetThreadName("rt:janitor"); Utils::SetThreadName("rt:janitor");
static auto LastStats = OpenWifi::Now(); static auto LastStats = OpenWifi::Now();
std::unique_lock G(M_); std::unique_lock Lock(LocalMutex_);
for(auto element=EndPoints_.begin();element!=EndPoints_.end();) { for(auto element=EndPoints_.begin();element!=EndPoints_.end();) {
if(element->second->TooOld()) { if(element->second->TooOld()) {
auto c = fmt::format("Removing {}. Serial: {} Device connection time: {}s. Client connection time: {}s", auto c = fmt::format("Removing {}. Serial: {} Device connection time: {}s. Client connection time: {}s",
@@ -139,7 +133,7 @@ namespace OpenWifi {
TotalEndPoints_, TotalEndPoints_,
TotalConnectedDeviceTime_, TotalConnectedDeviceTime_,
TotalConnectedClientTime_, TotalConnectedClientTime_,
FaildedNumDevices_, FailedNumDevices_,
FailedNumClients_)); FailedNumClients_));
} }
} }
@@ -159,7 +153,7 @@ namespace OpenWifi {
while (NextNotification && NotificationManagerRunning_) { while (NextNotification && NotificationManagerRunning_) {
auto Notification = dynamic_cast<RTTYS_Notification *>(NextNotification.get()); auto Notification = dynamic_cast<RTTYS_Notification *>(NextNotification.get());
if (Notification != nullptr) { if (Notification != nullptr) {
std::unique_lock G(M_); std::unique_lock Lock(LocalMutex_);
auto It = EndPoints_.find(Notification->id_); auto It = EndPoints_.find(Notification->id_);
if (It != EndPoints_.end()) { if (It != EndPoints_.end()) {
switch (Notification->type_) { switch (Notification->type_) {
@@ -170,16 +164,14 @@ namespace OpenWifi {
It->second->DisconnectClient(); It->second->DisconnectClient();
} break; } break;
case RTTYS_Notification_type::device_registration: { case RTTYS_Notification_type::device_registration: {
auto ptr = std::unique_ptr<RTTYS_Device_ConnectionHandler>{Notification->device_}; It->second->SetDevice(Notification->device_);
It->second->SetDevice(std::move(ptr));
if(!It->second->Joined() && It->second->ValidClient()) { if(!It->second->Joined() && It->second->ValidClient()) {
It->second->Join(); It->second->Join();
It->second->Login(); It->second->Login();
} }
} break; } break;
case RTTYS_Notification_type::client_registration: { case RTTYS_Notification_type::client_registration: {
auto ptr = std::unique_ptr<RTTYS_ClientConnection>{Notification->client_}; It->second->SetClient(Notification->client_);
It->second->SetClient(std::move(ptr));
if(!It->second->Joined() && It->second->ValidDevice()) { if(!It->second->Joined() && It->second->ValidDevice()) {
It->second->Join(); It->second->Join();
It->second->Login(); It->second->Login();
@@ -190,7 +182,7 @@ namespace OpenWifi {
}; };
} else { } else {
if(Notification->type_==RTTYS_Notification_type::device_registration) { if(Notification->type_==RTTYS_Notification_type::device_registration) {
FaildedNumDevices_++; FailedNumDevices_++;
auto ptr = std::unique_ptr<RTTYS_Device_ConnectionHandler>{Notification->device_}; auto ptr = std::unique_ptr<RTTYS_Device_ConnectionHandler>{Notification->device_};
FailedDevices.push_back(std::move(ptr)); FailedDevices.push_back(std::move(ptr));
} else if(Notification->type_==RTTYS_Notification_type::client_registration) { } else if(Notification->type_==RTTYS_Notification_type::client_registration) {
@@ -205,11 +197,11 @@ namespace OpenWifi {
} }
bool RTTYS_server::SendToClient(const std::string &Id, const u_char *Buf, std::size_t Len) { bool RTTYS_server::SendToClient(const std::string &Id, const u_char *Buf, std::size_t Len) {
std::shared_lock Guard(M_); std::shared_lock Lock(LocalMutex_);
try { try {
auto It = EndPoints_.find(Id); auto It = EndPoints_.find(Id);
if (It != EndPoints_.end()) { if (It != EndPoints_.end() && It->second!=nullptr) {
return It->second->SendToClient(Buf,Len); return It->second->SendToClient(Buf,Len);
} }
} catch(const Poco::Exception &E) { } catch(const Poco::Exception &E) {
@@ -221,11 +213,11 @@ namespace OpenWifi {
} }
bool RTTYS_server::SendToClient(const std::string &Id, const std::string &s) { bool RTTYS_server::SendToClient(const std::string &Id, const std::string &s) {
std::shared_lock Guard(M_); std::shared_lock Lock(LocalMutex_);
try { try {
auto It = EndPoints_.find(Id); auto It = EndPoints_.find(Id);
if (It != EndPoints_.end()) { if (It != EndPoints_.end() && It->second!=nullptr) {
return It->second->SendToClient(s); return It->second->SendToClient(s);
} }
} catch(const Poco::Exception &E) { } catch(const Poco::Exception &E) {
@@ -237,21 +229,16 @@ namespace OpenWifi {
} }
bool RTTYS_server::SendKeyStrokes(const std::string &Id, const u_char *buffer, std::size_t len) { bool RTTYS_server::SendKeyStrokes(const std::string &Id, const u_char *buffer, std::size_t len) {
std::shared_lock Guard(M_); std::shared_lock Lock(LocalMutex_);
auto It=EndPoints_.find(Id); auto It=EndPoints_.find(Id);
if(It==EndPoints_.end()) { if(It==EndPoints_.end() || It->second==nullptr) {
return false; return false;
} }
try { try {
if(It->second.get() != nullptr) { auto res = It->second->KeyStrokes(buffer, len);
auto res = It->second->KeyStrokes(buffer, len); return res;
return res;
}
else {
return true;
}
} catch(const Poco::Exception &E) { } catch(const Poco::Exception &E) {
Logger().log(E); Logger().log(E);
} catch (...) { } catch (...) {
@@ -260,10 +247,10 @@ namespace OpenWifi {
} }
bool RTTYS_server::WindowSize(const std::string &Id, int cols, int rows) { bool RTTYS_server::WindowSize(const std::string &Id, int cols, int rows) {
std::shared_lock Guard(M_); std::shared_lock Lock(LocalMutex_);
auto It=EndPoints_.find(Id); auto It=EndPoints_.find(Id);
if(It==EndPoints_.end()) { if(It==EndPoints_.end() || It->second==nullptr) {
return false; return false;
} }
try { try {
@@ -276,20 +263,19 @@ namespace OpenWifi {
} }
bool RTTYS_server::CreateEndPoint(const std::string &Id, const std::string & Token, const std::string & UserName, const std::string & SerialNumber ) { bool RTTYS_server::CreateEndPoint(const std::string &Id, const std::string & Token, const std::string & UserName, const std::string & SerialNumber ) {
std::unique_lock Guard(M_); std::unique_lock Lock(LocalMutex_);
if(MaxConcurrentSessions_!=0 && EndPoints_.size()==MaxConcurrentSessions_) { if(MaxConcurrentSessions_!=0 && EndPoints_.size()==MaxConcurrentSessions_) {
return false; return false;
} }
auto NewEP = std::make_unique<RTTYS_EndPoint>(Token, SerialNumber, UserName ); EndPoints_[Id] = std::make_unique<RTTYS_EndPoint>(Token, SerialNumber, UserName );
EndPoints_[Id] = std::move(NewEP);
++TotalEndPoints_; ++TotalEndPoints_;
return true; return true;
} }
bool RTTYS_server::ValidId(const std::string &Token) { bool RTTYS_server::ValidId(const std::string &Token) {
std::shared_lock Guard(M_); std::shared_lock Lock(LocalMutex_);
return EndPoints_.find(Token) != EndPoints_.end(); return EndPoints_.find(Token) != EndPoints_.end();
} }

View File

@@ -90,14 +90,14 @@ namespace OpenWifi {
Created_ = std::chrono::high_resolution_clock::now(); Created_ = std::chrono::high_resolution_clock::now();
} }
inline void SetClient(std::unique_ptr<RTTYS_ClientConnection> Client) { inline void SetClient(RTTYS_ClientConnection *Client) {
ClientConnected_ = std::chrono::high_resolution_clock::now(); ClientConnected_ = std::chrono::high_resolution_clock::now();
Client_ = std::move(Client); Client_ = std::unique_ptr<RTTYS_ClientConnection>(Client);
} }
inline void SetDevice(std::unique_ptr<RTTYS_Device_ConnectionHandler> Device) { inline void SetDevice(RTTYS_Device_ConnectionHandler* Device) {
DeviceConnected_ = std::chrono::high_resolution_clock::now(); DeviceConnected_ = std::chrono::high_resolution_clock::now();
Device_ = std::move(Device); Device_ = std::unique_ptr<RTTYS_Device_ConnectionHandler>(Device);
} }
inline bool Login() { inline bool Login() {
@@ -107,12 +107,6 @@ namespace OpenWifi {
return false; return false;
} }
RTTYS_EndPoint & operator=(RTTYS_EndPoint Other) {
Other.Client_ = std::move(Client_);
Other.Device_ = std::move(Device_);
return *this;
}
inline void DisconnectClient() { inline void DisconnectClient() {
ClientDisconnected_ = std::chrono::high_resolution_clock::now(); ClientDisconnected_ = std::chrono::high_resolution_clock::now();
} }
@@ -275,24 +269,23 @@ namespace OpenWifi {
std::unique_ptr<Poco::Net::SocketAcceptor<RTTYS_Device_ConnectionHandler>> DeviceAcceptor_; std::unique_ptr<Poco::Net::SocketAcceptor<RTTYS_Device_ConnectionHandler>> DeviceAcceptor_;
Poco::Thread DeviceReactorThread_; Poco::Thread DeviceReactorThread_;
Poco::NotificationQueue ResponseQueue_; Poco::NotificationQueue ResponseQueue_;
mutable bool NotificationManagerRunning_=false; std::atomic_bool NotificationManagerRunning_=false;
Poco::Thread NotificationManager_; Poco::Thread NotificationManager_;
Poco::Timer Timer_; Poco::Timer Timer_;
std::unique_ptr<Poco::TimerCallback<RTTYS_server>> GCCallBack_; std::unique_ptr<Poco::TimerCallback<RTTYS_server>> GCCallBack_;
std::list<std::unique_ptr<RTTYS_Device_ConnectionHandler>> FailedDevices; std::list<std::unique_ptr<RTTYS_Device_ConnectionHandler>> FailedDevices;
std::list<std::unique_ptr<RTTYS_ClientConnection>> FailedClients; std::list<std::unique_ptr<RTTYS_ClientConnection>> FailedClients;
mutable std::shared_mutex M_; std::shared_mutex LocalMutex_;
uint64_t TotalEndPoints_=0; std::atomic_uint64_t TotalEndPoints_=0;
uint64_t FaildedNumDevices_=0; std::atomic_uint64_t FailedNumDevices_=0;
uint64_t FailedNumClients_=0; std::atomic_uint64_t FailedNumClients_=0;
double TotalConnectedDeviceTime_=0.0; double TotalConnectedDeviceTime_=0.0;
double TotalConnectedClientTime_=0.0; double TotalConnectedClientTime_=0.0;
uint64_t Started_=OpenWifi::Now(); std::atomic_uint64_t Started_=OpenWifi::Now();
std::atomic_uint64_t MaxConcurrentSessions_=0;
uint64_t MaxConcurrentSessions_=0;
explicit RTTYS_server() noexcept: explicit RTTYS_server() noexcept:
SubSystemServer("RTTY_Server", "RTTY-SVR", "rtty.server") SubSystemServer("RTTY_Server", "RTTY-SVR", "rtty.server")

View File

@@ -76,7 +76,7 @@ namespace OpenWifi {
} }
return true; return true;
} catch(const Poco::Exception &E) { } catch(const Poco::Exception &E) {
Logger().warning(fmt::format("{}: Failed with: {}", std::string(__func__), E.displayText())); poco_warning(Logger(),fmt::format("{}: Failed with: {}", std::string(__func__), E.displayText()));
} }
return false; return false;
} }
@@ -99,7 +99,7 @@ namespace OpenWifi {
return true; return true;
} catch (const Poco::Exception &E) { } catch (const Poco::Exception &E) {
Logger().warning(fmt::format("{}: Failed with: {}", std::string(__func__), E.displayText())); poco_warning(Logger(),fmt::format("{}: Failed with: {}", std::string(__func__), E.displayText()));
} }
return false; return false;
} }
@@ -111,7 +111,7 @@ namespace OpenWifi {
} }
return true; return true;
} catch (const Poco::Exception &E) { } catch (const Poco::Exception &E) {
Logger().warning(fmt::format("{}: Failed with: {}", std::string(__func__), E.displayText())); poco_warning(Logger(),fmt::format("{}: Failed with: {}", std::string(__func__), E.displayText()));
} }
return false; return false;
} }
@@ -132,7 +132,7 @@ namespace OpenWifi {
BlackListDevices.erase(SerialNumber); BlackListDevices.erase(SerialNumber);
return true; return true;
} catch (const Poco::Exception &E) { } catch (const Poco::Exception &E) {
Logger().warning(fmt::format("{}: Failed with: {}", std::string(__func__), E.displayText())); poco_warning(Logger(),fmt::format("{}: Failed with: {}", std::string(__func__), E.displayText()));
} }
return false; return false;
} }
@@ -155,7 +155,7 @@ namespace OpenWifi {
return Select.rowsExtracted()==1; return Select.rowsExtracted()==1;
} catch (const Poco::Exception &E) { } catch (const Poco::Exception &E) {
Logger().warning(fmt::format("{}: Failed with: {}", std::string(__func__), E.displayText())); poco_warning(Logger(),fmt::format("{}: Failed with: {}", std::string(__func__), E.displayText()));
} }
return false; return false;
} }
@@ -177,7 +177,7 @@ namespace OpenWifi {
return true; return true;
} catch (const Poco::Exception &E) { } catch (const Poco::Exception &E) {
Logger().warning(fmt::format("{}: Failed with: {}", std::string(__func__), E.displayText())); poco_warning(Logger(),fmt::format("{}: Failed with: {}", std::string(__func__), E.displayText()));
} }
return false; return false;
} }
@@ -202,7 +202,7 @@ namespace OpenWifi {
} }
return true; return true;
} catch (const Poco::Exception &E) { } catch (const Poco::Exception &E) {
Logger().warning(fmt::format("{}: Failed with: {}", std::string(__func__), E.displayText())); poco_warning(Logger(),fmt::format("{}: Failed with: {}", std::string(__func__), E.displayText()));
} }
return false; return false;
} }

View File

@@ -34,7 +34,7 @@ bool Storage::CreateDeviceCapabilities(std::string &SerialNumber, std::string &C
return true; return true;
} }
catch (const Poco::Exception &E) { catch (const Poco::Exception &E) {
Logger().warning(fmt::format("{}: Failed with: {}", std::string(__func__), E.displayText())); poco_warning(Logger(),fmt::format("{}: Failed with: {}", std::string(__func__), E.displayText()));
} }
return false; return false;
} }
@@ -63,7 +63,7 @@ bool Storage::CreateDeviceCapabilities(std::string &SerialNumber, std::string &C
return true; return true;
} }
catch (const Poco::Exception &E) { catch (const Poco::Exception &E) {
Logger().warning( fmt::format("{}: Failed with: {}", std::string(__func__), E.displayText())); poco_warning(Logger(), fmt::format("{}: Failed with: {}", std::string(__func__), E.displayText()));
} }
return false; return false;
} }
@@ -110,7 +110,7 @@ bool Storage::CreateDeviceCapabilities(std::string &SerialNumber, std::string &C
return true; return true;
} }
catch (const Poco::Exception &E) { catch (const Poco::Exception &E) {
Logger().warning(fmt::format("{}: Failed with: {}", std::string(__func__), E.displayText())); poco_warning(Logger(),fmt::format("{}: Failed with: {}", std::string(__func__), E.displayText()));
} }
return false; return false;
} }

View File

@@ -130,20 +130,14 @@ typedef Poco::Tuple<
try { try {
auto Now = OpenWifi::Now(); auto Now = OpenWifi::Now();
if(Type == COMMAND_PENDING) { Command.Status = to_string(Type);
Command.Status = "pending"; if( Type==CommandExecutionType::COMMAND_COMPLETED ||
} else if(Type == COMMAND_COMPLETED) { Type==CommandExecutionType::COMMAND_TIMEDOUT ||
Command.Status = "completed"; Type==CommandExecutionType::COMMAND_FAILED ||
Type==CommandExecutionType::COMMAND_EXPIRED ||
Type==CommandExecutionType::COMMAND_EXECUTED
) {
Command.Executed = Now; Command.Executed = Now;
} else if (Type == COMMAND_TIMEDOUT) {
Command.Executed = Now;
Command.Status = "timedout";
} else if (Type == COMMAND_FAILED) {
Command.Executed = Now;
Command.Status = "failed";
} else {
Command.Executed = Now;
Command.Status = "executing";
} }
RemoveOldCommands(SerialNumber, Command.Command); RemoveOldCommands(SerialNumber, Command.Command);
@@ -271,7 +265,7 @@ typedef Poco::Tuple<
Offset++; Offset++;
GWObjects::CommandDetails R; GWObjects::CommandDetails R;
ConvertCommandRecord(i,R); ConvertCommandRecord(i,R);
if (DeviceRegistry()->Connected(R.SerialNumber)) if (DeviceRegistry()->Connected(Utils::SerialNumberToInt(R.SerialNumber)))
Commands.push_back(R); Commands.push_back(R);
} }
@@ -318,10 +312,13 @@ typedef Poco::Tuple<
Poco::Data::Statement Update(Sess); Poco::Data::Statement Update(Sess);
auto Now = OpenWifi::Now(); auto Now = OpenWifi::Now();
std::string St{"UPDATE CommandList SET Executed=? WHERE UUID=?"}; auto Status = to_string(Storage::CommandExecutionType::COMMAND_EXECUTED);
std::string St{"UPDATE CommandList SET Executed=?, Status=? WHERE UUID=?"};
Update << ConvertParams(St), Update << ConvertParams(St),
Poco::Data::Keywords::use(Now), Poco::Data::Keywords::use(Now),
Poco::Data::Keywords::use(Status),
Poco::Data::Keywords::use( CommandUUID); Poco::Data::Keywords::use( CommandUUID);
Update.execute(); Update.execute();
return true; return true;
@@ -331,6 +328,62 @@ typedef Poco::Tuple<
return false; return false;
} }
void Storage::RemovedExpiredCommands() {
try {
Poco::Data::Session Sess = Pool_->get();
Poco::Data::Statement Update(Sess);
auto Now = OpenWifi::Now(), Window = Now-(4*60*60);
auto Status = to_string(Storage::CommandExecutionType::COMMAND_EXPIRED);
std::string St{"UPDATE CommandList SET Executed=?, Status=? WHERE submitted<? and executed=0"};
Update << ConvertParams(St),
Poco::Data::Keywords::use(Now),
Poco::Data::Keywords::use(Status),
Poco::Data::Keywords::use(Window);
Update.execute();
} catch (const Poco::Exception &E) {
Logger().log(E);
}
}
void Storage::RemoveTimedOutCommands() {
try {
Poco::Data::Session Sess = Pool_->get();
Poco::Data::Statement Update(Sess);
auto Now = OpenWifi::Now(), Window = Now-(1*60*60);
std::string St{"UPDATE CommandList SET Executed=?, Status='timedout' WHERE Executed<? and completed=0"};
Update << ConvertParams(St),
Poco::Data::Keywords::use(Now),
Poco::Data::Keywords::use(Window);
Update.execute();
} catch (const Poco::Exception &E) {
Logger().log(E);
}
}
bool Storage::SetCommandTimedOut(std::string &CommandUUID) {
try {
Poco::Data::Session Sess = Pool_->get();
Poco::Data::Statement Update(Sess);
auto Now = OpenWifi::Now();
auto Status = to_string(Storage::CommandExecutionType::COMMAND_TIMEDOUT);
std::string St{"UPDATE CommandList SET Executed=?, Status=? WHERE UUID=?"};
Update << ConvertParams(St),
Poco::Data::Keywords::use(Now),
Poco::Data::Keywords::use(Status),
Poco::Data::Keywords::use(CommandUUID);
Update.execute();
return true;
} catch (const Poco::Exception &E) {
Logger().log(E);
}
return false;
}
bool Storage::GetCommand(const std::string &UUID, GWObjects::CommandDetails &Command) { bool Storage::GetCommand(const std::string &UUID, GWObjects::CommandDetails &Command) {
try { try {
@@ -411,7 +464,7 @@ typedef Poco::Tuple<
"SELECT " + "SELECT " +
DB_Command_SelectFields DB_Command_SelectFields
+ " FROM CommandList " + " FROM CommandList "
" WHERE ((RunAt<=?) And (Executed=0)) ORDER BY UUID ASC "}; " WHERE ((RunAt<=?) And (Executed=0)) ORDER BY Submitted ASC "};
CommandDetailsRecordList Records; CommandDetailsRecordList Records;
std::string SS = ConvertParams(St) + ComputeRange(Offset, HowMany); std::string SS = ConvertParams(St) + ComputeRange(Offset, HowMany);
@@ -423,7 +476,7 @@ typedef Poco::Tuple<
for(const auto &i : Records) { for(const auto &i : Records) {
GWObjects::CommandDetails R; GWObjects::CommandDetails R;
ConvertCommandRecord(i,R); ConvertCommandRecord(i,R);
if (DeviceRegistry()->Connected(R.SerialNumber)) if (DeviceRegistry()->Connected(Utils::SerialNumberToInt(R.SerialNumber)))
Commands.push_back(R); Commands.push_back(R);
} }
return true; return true;
@@ -485,7 +538,7 @@ typedef Poco::Tuple<
Poco::Data::Session Sess = Pool_->get(); Poco::Data::Session Sess = Pool_->get();
Poco::Data::Statement Update(Sess); Poco::Data::Statement Update(Sess);
std::string StatusText{"completed"}; auto Status = to_string(Storage::CommandExecutionType::COMMAND_COMPLETED);
std::string St{"UPDATE CommandList SET Completed=?, ErrorCode=?, ErrorText=?, Results=?, Status=?, executionTime=? WHERE UUID=?"}; std::string St{"UPDATE CommandList SET Completed=?, ErrorCode=?, ErrorText=?, Results=?, Status=?, executionTime=? WHERE UUID=?"};
double tET{execution_time.count()}; double tET{execution_time.count()};
Update << ConvertParams(St), Update << ConvertParams(St),
@@ -493,7 +546,7 @@ typedef Poco::Tuple<
Poco::Data::Keywords::use(ErrorCode), Poco::Data::Keywords::use(ErrorCode),
Poco::Data::Keywords::use(ErrorText), Poco::Data::Keywords::use(ErrorText),
Poco::Data::Keywords::use(ResultStr), Poco::Data::Keywords::use(ResultStr),
Poco::Data::Keywords::use(StatusText), Poco::Data::Keywords::use(Status),
Poco::Data::Keywords::use(tET), Poco::Data::Keywords::use(tET),
Poco::Data::Keywords::use(UUID); Poco::Data::Keywords::use(UUID);
Update.execute(); Update.execute();
@@ -569,7 +622,7 @@ typedef Poco::Tuple<
Insert.execute(); Insert.execute();
return true; return true;
} else { } else {
Logger().warning(fmt::format("File {} is too large.", UUID)); poco_warning(Logger(),fmt::format("File {} is too large.", UUID));
} }
} catch (const Poco::Exception &E) { } catch (const Poco::Exception &E) {
Logger().log(E); Logger().log(E);
@@ -623,10 +676,14 @@ typedef Poco::Tuple<
Poco::Data::Statement Update(Sess); Poco::Data::Statement Update(Sess);
auto Now = OpenWifi::Now(); auto Now = OpenWifi::Now();
std::string St{"UPDATE CommandList SET Completed=?, Results=? WHERE UUID=?"}; auto Status = to_string(Storage::CommandExecutionType::COMMAND_COMPLETED);
std::string St{"UPDATE CommandList SET Completed=?, Results=?, Status=? WHERE UUID=?"};
Update << ConvertParams(St), Poco::Data::Keywords::use(Now), Update << ConvertParams(St),
Poco::Data::Keywords::use(Result), Poco::Data::Keywords::use(UUID); Poco::Data::Keywords::use(Now),
Poco::Data::Keywords::use(Result),
Poco::Data::Keywords::use(Status),
Poco::Data::Keywords::use(UUID);
Update.execute(); Update.execute();
return true; return true;

View File

@@ -69,7 +69,7 @@ namespace OpenWifi {
std::string St{"SELECT name FROM DefaultConfigs WHERE Name=?"}; std::string St{"SELECT name FROM DefaultConfigs WHERE Name=?"};
Select << ConvertParams(St) , Select << ConvertParams(St) ,
Poco::Data::Keywords::into(TmpName) , Poco::Data::Keywords::into(TmpName) ,
Name; Poco::Data::Keywords::use(Name);
Select.execute(); Select.execute();
if (!TmpName.empty()) if (!TmpName.empty())
@@ -90,12 +90,12 @@ namespace OpenWifi {
Insert.execute(); Insert.execute();
return true; return true;
} else { } else {
Logger().warning("Cannot create device: invalid configuration."); poco_warning(Logger(),"Cannot create device: invalid configuration.");
return false; return false;
} }
} }
catch (const Poco::Exception &E) { catch (const Poco::Exception &E) {
Logger().warning(fmt::format("{}: Failed with: {}", std::string(__func__), E.displayText())); poco_warning(Logger(),fmt::format("{}: Failed with: {}", std::string(__func__), E.displayText()));
} }
return false; return false;
} }
@@ -115,7 +115,7 @@ namespace OpenWifi {
return true; return true;
} }
catch (const Poco::Exception &E) { catch (const Poco::Exception &E) {
Logger().warning(fmt::format("{}: Failed with: {}", std::string(__func__), E.displayText())); poco_warning(Logger(),fmt::format("{}: Failed with: {}", std::string(__func__), E.displayText()));
} }
return false; return false;
} }
@@ -140,7 +140,7 @@ namespace OpenWifi {
return true; return true;
} }
catch (const Poco::Exception &E) { catch (const Poco::Exception &E) {
Logger().warning(fmt::format("{}: Failed with: {}", std::string(__func__), E.displayText())); poco_warning(Logger(),fmt::format("{}: Failed with: {}", std::string(__func__), E.displayText()));
} }
return false; return false;
} }
@@ -167,7 +167,7 @@ namespace OpenWifi {
return false; return false;
} }
catch (const Poco::Exception &E) { catch (const Poco::Exception &E) {
Logger().warning(fmt::format("{}: Failed with: {}", std::string(__func__), E.displayText())); poco_warning(Logger(),fmt::format("{}: Failed with: {}", std::string(__func__), E.displayText()));
} }
return false; return false;
} }
@@ -190,7 +190,7 @@ namespace OpenWifi {
return Select.rowsExtracted()==1; return Select.rowsExtracted()==1;
} }
catch (const Poco::Exception &E) { catch (const Poco::Exception &E) {
Logger().warning(fmt::format("{}: Failed with: {}", std::string(__func__), E.displayText())); poco_warning(Logger(),fmt::format("{}: Failed with: {}", std::string(__func__), E.displayText()));
} }
return false; return false;
} }
@@ -215,7 +215,7 @@ namespace OpenWifi {
return true; return true;
} }
catch (const Poco::Exception &E) { catch (const Poco::Exception &E) {
Logger().warning(fmt::format("{}: Failed with: {}", std::string(__func__), E.displayText())); poco_warning(Logger(),fmt::format("{}: Failed with: {}", std::string(__func__), E.displayText()));
} }
return false; return false;
} }
@@ -245,7 +245,7 @@ namespace OpenWifi {
return false; return false;
} }
catch (const Poco::Exception &E) { catch (const Poco::Exception &E) {
Logger().warning(fmt::format("{}: Failed with: {}", std::string(__func__), E.displayText())); poco_warning(Logger(),fmt::format("{}: Failed with: {}", std::string(__func__), E.displayText()));
} }
return false; return false;
} }
@@ -261,7 +261,7 @@ namespace OpenWifi {
return Count; return Count;
} }
catch (const Poco::Exception &E) { catch (const Poco::Exception &E) {
Logger().warning(fmt::format("{}: Failed with: {}", std::string(__func__), E.displayText())); poco_warning(Logger(),fmt::format("{}: Failed with: {}", std::string(__func__), E.displayText()));
} }
return Count; return Count;
} }

View File

@@ -433,7 +433,7 @@ namespace OpenWifi {
bool Storage::DeleteDevice(std::string &SerialNumber) { bool Storage::DeleteDevice(std::string &SerialNumber) {
try { try {
std::vector<std::string> DBList{"Devices", "Statistics", "CommandList", "HealthChecks", "LifetimeStats", "Capabilities", "DeviceLogs"}; std::vector<std::string> DBList{"Devices", "Statistics", "CommandList", "HealthChecks", "Capabilities", "DeviceLogs"};
for(const auto &i:DBList) { for(const auto &i:DBList) {
@@ -453,10 +453,14 @@ namespace OpenWifi {
SerialNumberCache()->DeleteSerialNumber(SerialNumber); SerialNumberCache()->DeleteSerialNumber(SerialNumber);
if(KafkaManager()->Enabled()) { if(KafkaManager()->Enabled()) {
nlohmann::json Message; Poco::JSON::Object Message;
Message["command"] = "delete_device"; Message.set("command","command");
Message["payload"]["serialNumber"] = SerialNumber; Poco::JSON::Object Payload;
KafkaManager()->PostMessage(KafkaTopics::COMMAND, SerialNumber, to_string(Message)); Payload.set("serialNumber", SerialNumber);
Message.set("payload",Payload);
std::ostringstream StrPayload;
Message.stringify(StrPayload);
KafkaManager()->PostMessage(KafkaTopics::COMMAND, SerialNumber, StrPayload.str());
} }
return true; return true;

View File

@@ -57,7 +57,7 @@ namespace OpenWifi {
return true; return true;
} }
catch (const Poco::Exception &E) { catch (const Poco::Exception &E) {
Logger().warning(fmt::format("{}: Failed with: {}", std::string(__func__), E.displayText())); poco_warning(Logger(),fmt::format("{}: Failed with: {}", std::string(__func__), E.displayText()));
} }
return false; return false;
} }
@@ -100,7 +100,7 @@ namespace OpenWifi {
return true; return true;
} }
catch (const Poco::Exception &E) { catch (const Poco::Exception &E) {
Logger().warning(fmt::format("{}: Failed with: {}", std::string(__func__), E.displayText())); poco_warning(Logger(),fmt::format("{}: Failed with: {}", std::string(__func__), E.displayText()));
} }
return false; return false;
} }
@@ -127,7 +127,7 @@ namespace OpenWifi {
return true; return true;
} }
catch (const Poco::Exception &E) { catch (const Poco::Exception &E) {
Logger().warning(fmt::format("{}: Failed with: {}", std::string(__func__), E.displayText())); poco_warning(Logger(),fmt::format("{}: Failed with: {}", std::string(__func__), E.displayText()));
} }
return false; return false;
} }
@@ -162,7 +162,7 @@ namespace OpenWifi {
return true; return true;
} }
catch (const Poco::Exception &E) { catch (const Poco::Exception &E) {
Logger().warning(fmt::format("{}: Failed with: {}", std::string(__func__), E.displayText())); poco_warning(Logger(),fmt::format("{}: Failed with: {}", std::string(__func__), E.displayText()));
} }
return false; return false;
} }
@@ -178,7 +178,7 @@ namespace OpenWifi {
Delete.execute(); Delete.execute();
return true; return true;
} catch (const Poco::Exception &E) { } catch (const Poco::Exception &E) {
Logger().warning(fmt::format("{}: Failed with: {}", std::string(__func__), E.displayText())); poco_warning(Logger(),fmt::format("{}: Failed with: {}", std::string(__func__), E.displayText()));
} }
return false; return false;
} }

View File

@@ -63,7 +63,7 @@ namespace OpenWifi {
return true; return true;
} }
catch (const Poco::Exception &E) { catch (const Poco::Exception &E) {
Logger().warning(fmt::format("{}: Failed with: {}", std::string(__func__), E.displayText())); poco_warning(Logger(),fmt::format("{}: Failed with: {}", std::string(__func__), E.displayText()));
} }
return false; return false;
} }
@@ -109,7 +109,7 @@ namespace OpenWifi {
return true; return true;
} }
catch (const Poco::Exception &E) { catch (const Poco::Exception &E) {
Logger().warning(fmt::format("{}: Failed with: {}", std::string(__func__), E.displayText())); poco_warning(Logger(),fmt::format("{}: Failed with: {}", std::string(__func__), E.displayText()));
} }
return false; return false;
} }
@@ -147,7 +147,7 @@ namespace OpenWifi {
return true; return true;
} }
catch (const Poco::Exception &E) { catch (const Poco::Exception &E) {
Logger().warning(fmt::format("{}: Failed with: {}", std::string(__func__), E.displayText())); poco_warning(Logger(),fmt::format("{}: Failed with: {}", std::string(__func__), E.displayText()));
} }
return false; return false;
} }
@@ -174,7 +174,7 @@ namespace OpenWifi {
return true; return true;
} }
catch (const Poco::Exception &E) { catch (const Poco::Exception &E) {
Logger().warning(fmt::format("{}: Failed with: {}", std::string(__func__), E.displayText())); poco_warning(Logger(),fmt::format("{}: Failed with: {}", std::string(__func__), E.displayText()));
} }
return false; return false;
} }
@@ -189,7 +189,7 @@ namespace OpenWifi {
Delete.execute(); Delete.execute();
return true; return true;
} catch (const Poco::Exception &E) { } catch (const Poco::Exception &E) {
Logger().warning(fmt::format("{}: Failed with: {}", std::string(__func__), E.displayText())); poco_warning(Logger(),fmt::format("{}: Failed with: {}", std::string(__func__), E.displayText()));
} }
return false; return false;
} }

View File

@@ -36,12 +36,11 @@ namespace OpenWifi {
} }
bool Storage::AddStatisticsData(const GWObjects::Statistics & Stats) { bool Storage::AddStatisticsData(const GWObjects::Statistics & Stats) {
DeviceRegistry()->SetStatistics(Stats.SerialNumber, Stats.Data);
try { try {
Poco::Data::Session Sess = Pool_->get(); Poco::Data::Session Sess = Pool_->get();
Poco::Data::Statement Insert(Sess); Poco::Data::Statement Insert(Sess);
poco_debug(Logger(),"Device:" + Stats.SerialNumber + " Stats size:" + std::to_string(Stats.Data.size())); poco_trace(Logger(),fmt::format("{}: Adding stats. Size={}",Stats.SerialNumber,std::to_string(Stats.Data.size())));
std::string St{"INSERT INTO Statistics ( " + std::string St{"INSERT INTO Statistics ( " +
DB_StatsSelectFields + DB_StatsSelectFields +
" ) VALUES ( " + " ) VALUES ( " +
@@ -54,7 +53,7 @@ namespace OpenWifi {
return true; return true;
} }
catch (const Poco::Exception &E) { catch (const Poco::Exception &E) {
Logger().warning(fmt::format("{}: Failed with: {}", std::string(__func__), E.displayText())); poco_warning(Logger(),fmt::format("{}: Failed with: {}", std::string(__func__), E.displayText()));
} }
return false; return false;
} }
@@ -97,7 +96,7 @@ namespace OpenWifi {
return true; return true;
} }
catch (const Poco::Exception &E) { catch (const Poco::Exception &E) {
Logger().warning(fmt::format("{}: Failed with: {}", std::string(__func__), E.displayText())); poco_warning(Logger(),fmt::format("{}: Failed with: {}", std::string(__func__), E.displayText()));
} }
return false; return false;
} }
@@ -124,7 +123,7 @@ namespace OpenWifi {
return true; return true;
} }
catch (const Poco::Exception &E) { catch (const Poco::Exception &E) {
Logger().warning(fmt::format("{}: Failed with: {}", std::string(__func__), E.displayText())); poco_warning(Logger(),fmt::format("{}: Failed with: {}", std::string(__func__), E.displayText()));
} }
return false; return false;
} }
@@ -157,7 +156,7 @@ bool Storage::DeleteStatisticsData(std::string &SerialNumber, uint64_t FromDate,
return true; return true;
} }
catch (const Poco::Exception &E) { catch (const Poco::Exception &E) {
Logger().warning(fmt::format("{}: Failed with: {}", std::string(__func__), E.displayText())); poco_warning(Logger(),(fmt::format("{}: Failed with: {}", std::string(__func__), E.displayText())));
} }
return false; return false;
} }
@@ -172,7 +171,7 @@ bool Storage::DeleteStatisticsData(std::string &SerialNumber, uint64_t FromDate,
Delete.execute(); Delete.execute();
return true; return true;
} catch (const Poco::Exception &E) { } catch (const Poco::Exception &E) {
Logger().warning(fmt::format("{}: Failed with: {}", std::string(__func__), E.displayText())); poco_warning(Logger(),fmt::format("{}: Failed with: {}", std::string(__func__), E.displayText()));
} }
return false; return false;
} }

View File

@@ -180,6 +180,14 @@ listdevices() {
jq < ${result_file} jq < ${result_file}
} }
listdevices() {
curl ${FLAGS} -X GET "https://${OWGW}/api/v1/devices" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-H "Authorization: Bearer ${token}" > ${result_file}
jq < ${result_file}
}
ldevs() { ldevs() {
curl ${FLAGS} -X GET "https://${OWGW}/api/v1/devices?offset=$1&limit=$2" \ curl ${FLAGS} -X GET "https://${OWGW}/api/v1/devices?offset=$1&limit=$2" \
-H "Content-Type: application/json" \ -H "Content-Type: application/json" \
@@ -191,7 +199,8 @@ ldevs() {
deletedevice() { deletedevice() {
curl ${FLAGS} -X DELETE "https://${OWGW}/api/v1/device/$1" \ curl ${FLAGS} -X DELETE "https://${OWGW}/api/v1/device/$1" \
-H "Accept: application/json" \ -H "Accept: application/json" \
-H "Authorization: Bearer ${token}" -H "Authorization: Bearer ${token}" > ${result_file}
jq < ${result_file}
} }
deleteoui() { deleteoui() {
@@ -237,7 +246,8 @@ setloglevel() {
-H "Content-Type: application/json" \ -H "Content-Type: application/json" \
-H "Accept: application/json" \ -H "Accept: application/json" \
-H "Authorization: Bearer ${token}" \ -H "Authorization: Bearer ${token}" \
-d "$payload" -d "$payload" > ${result_file}
jq < ${result_file}
} }
getloglevels() { getloglevels() {
@@ -246,7 +256,8 @@ getloglevels() {
-H "Content-Type: application/json" \ -H "Content-Type: application/json" \
-H "Accept: application/json" \ -H "Accept: application/json" \
-H "Authorization: Bearer ${token}" \ -H "Authorization: Bearer ${token}" \
-d "$payload" -d "$payload" > ${result_file}
jq < ${result_file}
} }
getloglevelnames() { getloglevelnames() {
@@ -255,7 +266,8 @@ getloglevelnames() {
-H "Content-Type: application/json" \ -H "Content-Type: application/json" \
-H "Accept: application/json" \ -H "Accept: application/json" \
-H "Authorization: Bearer ${token}" \ -H "Authorization: Bearer ${token}" \
-d "$payload" -d "$payload" > ${result_file}
jq < ${result_file}
} }
getsubsystemnames() { getsubsystemnames() {
@@ -264,7 +276,8 @@ getsubsystemnames() {
-H "Content-Type: application/json" \ -H "Content-Type: application/json" \
-H "Accept: application/json" \ -H "Accept: application/json" \
-H "Authorization: Bearer ${token}" \ -H "Authorization: Bearer ${token}" \
-d "$payload" -d "$payload" > ${result_file}
jq < ${result_file}
} }
systeminfo() { systeminfo() {
@@ -294,7 +307,8 @@ getdevicestatus() {
getdevicecomplete() { getdevicecomplete() {
curl ${FLAGS} -X GET "https://${OWGW}/api/v1/device/$1?completeInfo=true" \ curl ${FLAGS} -X GET "https://${OWGW}/api/v1/device/$1?completeInfo=true" \
-H "accept: application/json" \ -H "Content-Type: application/json" \
-H "Accept: application/json" \
-H "Authorization: Bearer ${token}" > ${result_file} -H "Authorization: Bearer ${token}" > ${result_file}
jq < ${result_file} jq < ${result_file}
} }
@@ -507,7 +521,7 @@ deviceserialnumbers() {
} }
deviceswithstatus() { deviceswithstatus() {
curl ${FLAGS} -X GET "https://${OWGW}/api/v1/devices?deviceWithStatus=true" \ curl ${FLAGS} -X GET "https://${OWGW}/api/v1/devices?deviceWithStatus=true&limit=500" \
-H "Content-Type: application/json" \ -H "Content-Type: application/json" \
-H "Accept: application/json" \ -H "Accept: application/json" \
-H "Authorization: Bearer ${token}" > ${result_file} -H "Authorization: Bearer ${token}" > ${result_file}
@@ -654,7 +668,7 @@ telemetry_to_kafka() {
runscript() { runscript() {
payload="$(printf '{ "serialNumber": "%s", "type": "%s" , "kafka": true, "timeout": 30, "scriptId": "cli-manual", "script" : "%s" }' "$1" "$2" "$3" )" payload="$(printf '{ "serialNumber": "%s", "type": "%s" , "kafka": true, "timeout": 30, "scriptId": "cli-manual", "script" : "%s" }' "$1" "$2" "$3" )"
curl ${FLAGS} -X POST "https://${OWGW}/api/v1/device/$1/telemetry" \ curl ${FLAGS} -X POST "https://${OWGW}/api/v1/device/$1/script" \
-H "Content-Type: application/json" \ -H "Content-Type: application/json" \
-H "Accept: application/json" \ -H "Accept: application/json" \
-H "Authorization: Bearer ${token}" \ -H "Authorization: Bearer ${token}" \
@@ -705,6 +719,14 @@ getradiusconfig() {
jq < ${result_file} jq < ${result_file}
} }
connectionstatistics() {
curl ${FLAGS} -X GET "https://${OWGW}/api/v1/devices?connectionStatistics=true" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-H "Authorization: Bearer ${token}" > ${result_file}
jq < ${result_file}
}
check_response() { check_response() {
if [ -s "$1" ]; then if [ -s "$1" ]; then
@@ -970,5 +992,6 @@ case "$1" in
"getradiusconfig") login; getradiusconfig ; logout;; "getradiusconfig") login; getradiusconfig ; logout;;
"setradiusconfig") login; setradiusconfig $2; logout;; "setradiusconfig") login; setradiusconfig $2; logout;;
"deviceping") login; deviceping $2; logout;; "deviceping") login; deviceping $2; logout;;
"connectionstatistics") login; connectionstatistics $2; logout;;
*) help ;; *) help ;;
esac esac