Compare commits

...

71 Commits

Author SHA1 Message Date
i-chvets
691d3399f8 Merge pull request #426 from Telecominfraproject/version_update
fix: Version update - release 4.1.1
2025-09-11 12:24:22 -04:00
Ivan Chvets
6542726ac3 Merge branch 'master' of github.com:Telecominfraproject/wlan-cloud-ucentralgw into version_update 2025-09-11 11:59:42 -04:00
Ivan Chvets
4bc753f8b5 fix: Version update - release 4.1.1
Signed-off-by: Ivan Chvets <ivan.chvets@kinarasystems.com>
2025-09-11 11:56:05 -04:00
i-chvets
e3a513fa6a Merge pull request #425 from Telecominfraproject/WIFI-15016_fix_schema_sync
WIFI 15016 fix: Sync schema.
2025-09-11 11:54:50 -04:00
Ivan Chvets
b151239a5c fix: Sync schema.
https://telecominfraproject.atlassian.net/browse/WIFI-15016

Signed-off-by: Ivan Chvets <ivan.chvets@kinarasystems.com>
2025-09-11 11:23:14 -04:00
Carsten Schafer
862dab38d1 Merge pull request #423 from Telecominfraproject/WIFI-14903-ssl-upgrade-via-debian-bookworm
Wifi 14903 ssl upgrade via debian bookworm
2025-09-02 13:54:50 -04:00
Carsten Schafer
ee2e9a19c0 Remove warning and fix RTTY PONG flags
Signed-off-by: Carsten Schafer <Carsten.Schafer@kinarasystems.com>
2025-09-02 13:28:11 -04:00
Carsten Schafer
8b28fa0435 Some more cleanup - remove code using deprecated functions
Signed-off-by: Carsten Schafer <Carsten.Schafer@kinarasystems.com>
2025-08-26 13:04:30 -04:00
Carsten Schafer
aeef70a121 Return PONG in response to PING
Signed-off-by: Carsten Schafer <Carsten.Schafer@kinarasystems.com>
2025-08-26 09:09:52 -04:00
Carsten Schafer
42c421ec12 Handle scenario where 3+ readable events including continuation frames all resulted in a final frame of 0 length
Signed-off-by: Carsten Schafer <Carsten.Schafer@kinarasystems.com>
2025-08-25 11:01:08 -04:00
Carsten Schafer
98bfb4b24d Fix package manager and resolver warnings
Signed-off-by: Carsten Schafer <Carsten.Schafer@kinarasystems.com>
2025-08-25 10:50:34 -04:00
Carsten Schafer
6b64089f55 Be able to more readily configure some useful settings via docker compose
Signed-off-by: Carsten Schafer <Carsten.Schafer@kinarasystems.com>
2025-08-25 10:45:23 -04:00
Carsten Schafer
1f6e42b57c Merge remote-tracking branch 'origin/master' into WIFI-14903-ssl-upgrade-via-debian-bookworm 2025-08-22 13:31:21 -04:00
Carsten Schafer
f857d61377 Merge remote-tracking branch 'origin/WIFI-14903-ssl-upgrade-via-debian-bookworm' into WIFI-14903-ssl-upgrade-via-debian-bookworm 2025-08-22 13:30:55 -04:00
Carsten Schafer
66d580d047 Work with new WS behaviour
Signed-off-by: Carsten Schafer <Carsten.Schafer@kinarasystems.com>
2025-08-22 13:30:07 -04:00
Carsten Schafer
567c671c22 Merge pull request #414 from Telecominfraproject/staging-WIFI-14588-Cloud-package-manager3
WIFI-14588: Cloud Package manager
2025-08-22 09:16:31 -04:00
Adam Capparelli
9e3735ced8 Switch to newer poco.
Signed-off-by: Adam Capparelli <adam.capparelli@alumni.utoronto.ca>
2025-08-21 13:03:58 -04:00
Carsten Schafer
18b169e517 Resolve conflict
Signed-off-by: Carsten Schafer <Carsten.Schafer@kinarasystems.com>
2025-08-21 09:38:16 -04:00
Carsten Schafer
cab0d8aee6 Remove test code
Signed-off-by: Carsten Schafer <Carsten.Schafer@kinarasystems.com>
2025-08-21 09:37:07 -04:00
Adam Capparelli
680b6a16e3 Fix more compilation errors.
Signed-off-by: Adam Capparelli <adam.capparelli@alumni.utoronto.ca>
2025-08-21 09:07:13 -04:00
Adam Capparelli
218694872f Fix some compile errors.
Signed-off-by: Adam Capparelli <adam.capparelli@alumni.utoronto.ca>
2025-08-21 08:47:39 -04:00
Carsten Schafer
6ae1eeb2ea Upgrade to debian bookworm, resolve compile issues, work around IOExceptions test
Signed-off-by: Carsten Schafer <Carsten.Schafer@kinarasystems.com>
2025-08-20 14:10:16 -04:00
Carsten Schafer
f537e701a0 Merge remote-tracking branch 'origin/master' into WIFI-14903-diagnose-ssl-err 2025-08-19 11:39:51 -04:00
Adam Capparelli
d4dfb7b620 Merge pull request #422 from Telecominfraproject/WIFI-14979-Update-owgw-built-in-schema
WIFI-14979-Update-owgw-built-in-schema: Add HaLow to wifi band enums.
2025-08-18 13:39:51 -04:00
Adam Capparelli
446cbf270f Add description to enable field.
Signed-off-by: Adam Capparelli <adam.capparelli@alumni.utoronto.ca>
2025-08-18 13:22:45 -04:00
Adam Capparelli
06ffee27b1 Add HaLow to wifi band enums.
Signed-off-by: Adam Capparelli <adam.capparelli@alumni.utoronto.ca>
2025-08-18 13:15:49 -04:00
i-chvets
fa3c325bfa Merge pull request #420 from Telecominfraproject/schema_sync
feat: Schema sync.
2025-08-14 16:35:56 -04:00
i-chvets
182a442582 Merge pull request #421 from Telecominfraproject/add_enroll_openapi
feat: Added reenroll to openapi.
2025-08-14 16:33:39 -04:00
Ivan Chvets
3b7a24ea30 feat: Added reenroll to openapi.
Signed-off-by: Ivan Chvets <ivan.chvets@kinarasystems.com>
2025-08-14 11:45:36 -04:00
Ivan Chvets
1c5909613f feat: Schema sync.
Signed-off-by: Ivan Chvets <ivan.chvets@kinarasystems.com>
2025-08-14 11:33:42 -04:00
Carsten Schafer
8e5e51a52a Correct call to poco_warning
Signed-off-by: Carsten Schafer <Carsten.Schafer@kinarasystems.com>
2025-08-11 15:49:08 -04:00
Carsten Schafer
b4699e9178 Add extra logging for SSL errors
Signed-off-by: Carsten Schafer <Carsten.Schafer@kinarasystems.com>
2025-08-11 15:35:48 -04:00
Carsten Schafer
438309714f Merge pull request #418 from Telecominfraproject/WIFI-14953-add-entire-trust-chain-for-rtty
WIFI-14953 Add entire trust chain for rtty use
2025-08-06 11:00:04 -04:00
Carsten Schafer
a9130eeb75 Read from proper client cas file
Signed-off-by: Carsten Schafer <Carsten.Schafer@kinarasystems.com>
2025-08-06 09:13:04 -04:00
Carsten Schafer
33068fca9e Declare the variable
Signed-off-by: Carsten Schafer <Carsten.Schafer@kinarasystems.com>
2025-08-05 11:15:51 -04:00
Carsten Schafer
d329151f6c Fix typo
Signed-off-by: Carsten Schafer <Carsten.Schafer@kinarasystems.com>
2025-08-05 10:46:45 -04:00
Carsten Schafer
ec846006bb Add entire trust chain for rtty use
Signed-off-by: Carsten Schafer <Carsten.Schafer@kinarasystems.com>
2025-08-05 10:24:33 -04:00
Kumiko18
bd48079a8d WIFI-14588: Cloud Package manager
1. Added independent package north/south bound API for package listing/installing/deleting
  2. Added modified openapi schema for swagger

Signed-off-by: Kumiko18 <alex18_huang@accton.com>
2025-07-25 01:58:37 +00:00
i-chvets
242261de0a Merge pull request #413 from Telecominfraproject/WIFI-14820-fix_wifi_frames_schema_update
WIFI-14820: fix: Added new parameters to wifi-frames
2025-07-14 15:53:41 -04:00
Ivan Chvets
31a4edead5 fix: Added new parameters to wifi-frames
https://telecominfraproject.atlassian.net/browse/WIFI-14820

Signed-off-by: Ivan Chvets <ivan.chvets@kinarasystems.com>
2025-07-14 14:00:47 -04:00
Carsten Schafer
f7b697f219 Merge pull request #412 from Telecominfraproject/PKI2-132_feat_ap_reenroll_command-fix
fix: ucentral reenroll command is reenroll not re-enroll
2025-07-10 10:14:49 -04:00
Carsten Schafer
e020da75fc fix: ucentral reenroll command is reenroll not re-enroll
Signed-off-by: Carsten Schafer <Carsten.Schafer@kinarasystems.com>
2025-07-10 09:50:45 -04:00
i-chvets
89702f56e0 Merge pull request #411 from Telecominfraproject/PKI2-132_feat_ap_reenroll_command
feat: Added reneroll command handler.
2025-07-03 08:24:14 -04:00
Ivan Chvets
0ac97442c0 feat: Added reneroll command handler.
https://telecominfraproject.atlassian.net/browse/PKI2-132

Signed-off-by: Ivan Chvets <ivan.chvets@kinarasystems.com>
2025-07-02 17:53:54 -04:00
i-chvets
e38b4c8a13 Merge pull request #410 from Telecominfraproject/PKI2-131_feat_add_issuer_name
PKI2-131: feat: Added issuer name to certificate data.
2025-07-02 16:55:40 -04:00
Ivan Chvets
9c5bbee834 feat: Added issuer name to certificate data.
https://telecominfraproject.atlassian.net/browse/PKI2-131

Signed-off-by: Ivan Chvets <ivan.chvets@kinarasystems.com>
2025-07-02 16:32:46 -04:00
i-chvets
a5d1eebe6d Merge pull request #405 from Telecominfraproject/version_update
WIFI-14521: fix: Version update - release 4.0.0
2025-04-24 16:56:09 -04:00
Ivan Chvets
ee14f064c8 Merge branch 'master' of github.com:Telecominfraproject/wlan-cloud-ucentralgw into version_update 2025-04-24 16:36:14 -04:00
i-chvets
dbf52c1f23 Merge pull request #406 from Telecominfraproject/WIFI-14521-ci-changes
WIFI-14521 Update to ubuntu-latest for GH runner
2025-04-24 16:18:31 -04:00
Carsten Schafer
9dc6a6bf97 Update to ubuntu-latest for GH runner
Signed-off-by: Carsten Schafer <Carsten.Schafer@kinarasystems.com>
2025-04-24 15:30:49 -04:00
Ivan Chvets
1c0556f8bf fix: Version update - release 4.0.0
Signed-off-by: Ivan Chvets <ivan.chvets@kinarasystems.com>
2025-04-24 14:09:12 -04:00
i-chvets
d298139525 Merge pull request #403 from Telecominfraproject/wifi-14521_feat_use_clientcas_for_validation
WIFI-14521: feat: Added processing of clientcas
2025-04-09 11:50:04 -04:00
Ivan Chvets
a37c961f5b feat: Added processing of clientcas
https://telecominfraproject.atlassian.net/browse/WIFI-14521

Summary of changes:
- Updated code to add certificates from clientcas to trust chain and
  validate client certificates against it.

Signed-off-by: Ivan Chvets <ivan.chvets@kinarasystems.com>
2025-04-09 10:30:52 -04:00
Nicolas Alfonso De Pineda Gutierrez
75bcbd748c Merge pull request #398 from Telecominfraproject/WIFI-14349-plat_cache.json-isnt-being-read-correctly-and-can-result-in-huge-memory-ussages-under-very-specific-situations
WIFI-14349-plat_cache.json-isnt-being-read-correctly-and-can-result-in-huge-memory-ussages-under-very-specific-situations
2025-01-21 16:00:14 +01:00
Nicolas de Pineda
b6eba2a96d fix: plat_cache.json not being read correctly
https://telecominfraproject.atlassian.net/browse/WIFI-14349

Summary of changes:
- Resolved an issue where a string field was being read as JSON, causing the output to be incorrectly surrounded by quotation marks.

Signed-off-by: Nicolas de Pineda <nicolas.depineda@galgus.ai>
2025-01-21 09:42:31 +01:00
i-chvets
17082803d4 Merge pull request #397 from Telecominfraproject/OLS-433-fix-switch-schema-sync
OLS-433: fix: updated internal switch schema
2024-12-10 10:23:27 -05:00
Ivan Chvets
26b9a96506 fix: updated internal switch schema
https://telecominfraproject.atlassian.net/browse/OLS-433

Summary of changes:
- Updated internal switch schema.

Signed-off-by: Ivan Chvets <ivan.chvets@kinarasystems.com>
2024-12-10 08:53:01 -05:00
i-chvets
5ce8dae9ec Merge pull request #393 from Telecominfraproject/OLS-433-fix-switch-schema-sync
OLS-433: fix: updated internal switch schema
2024-12-04 15:49:07 -05:00
i-chvets
7da135c1e5 Merge pull request #394 from Telecominfraproject/OLS-380-fix-file-upload
OSL-380: fix: modified code for file upload transactions
2024-12-04 15:48:47 -05:00
Carsten Schafer
50ee4ba5cb Merge pull request #395 from Telecominfraproject/version_update
fix: release 3.2.1 version update
2024-12-04 12:17:39 -05:00
Ivan Chvets
3a8109d7ad fix: release 3.2.1 version update
https://telecominfraproject.atlassian.net/browse/WIFI-14165

Signed-off-by: Ivan Chvets <ivan.chvets@kinarasystems.com>
2024-12-04 12:10:44 -05:00
Ivan Chvets
56232966ec fix: modified code for file upload transactions
https://telecominfraproject.atlassian.net/browse/OLS-380

Summary of changes:
- Modified code to have two distinct transaction in storage file upload.

Signed-off-by: Ivan Chvets <ivan.chvets@kinarasystems.com>
2024-11-29 13:09:34 -05:00
Ivan Chvets
1ecf98d712 fix: updated internal switch schema
https://telecominfraproject.atlassian.net/browse/OLS-433

Summary of changes:
- Updated internal switch schema.

Signed-off-by: Ivan Chvets <ivan.chvets@kinarasystems.com>
2024-11-29 11:56:05 -05:00
Gopi Raga
f5b60ced61 Merge pull request #392 from Telecominfraproject/WIFI-14292-fix-json-parse-error
WIFI-14292: fix: json parsing error
2024-11-17 11:20:00 +05:30
Ivan Chvets
e4d141bb8e fix: json parsing error
https://telecominfraproject.atlassian.net/browse/WIFI-14292

Summary of changes:
- Removed code that was incorrectly added to JSON string.

Signed-off-by: Ivan Chvets <ivan.chvets@kinarasystems.com>
2024-11-15 13:17:12 -05:00
i-chvets
25b4288050 Merge pull request #391 from Telecominfraproject/WIFI-14254-doc-update
WIFI-14254: doc: update protocol.md
2024-10-31 10:39:24 -04:00
Ivan Chvets
82430c2d5d doc: update protocol.md
https://telecominfraproject.atlassian.net/browse/WIFI-14254

Summary of changes:
- Updated PROTOCOL.md with compressed configuration message
  specification.

Signed-off-by: Ivan Chvets <ivan.chvets@kinarasystems.com>
2024-10-31 10:14:21 -04:00
i-chvets
7b68ec0536 Merge pull request #390 from Telecominfraproject/WIFI-14227-feat-compressed-config
WIFI-14229: feat: compressed config
2024-10-30 12:08:45 -04:00
Ivan Chvets
839f4fec44 feat: compressed config
https://telecominfraproject.atlassian.net/browse/WIFI-14229

Summary of changes:
- Modified code to compress configuration data, if capabilities object
  has compress command indicator enabled.
- Added encode and compress function to utilities.

Signed-off-by: Ivan Chvets <ivan.chvets@kinarasystems.com>
2024-10-30 11:44:02 -04:00
i-chvets
c4178209bb Merge pull request #388 from Telecominfraproject/version_update
WIFI-14165: Release 3.2 version update
2024-09-30 10:12:32 -04:00
Ivan Chvets
79ab67db50 fix: release 3.2 version update
https://telecominfraproject.atlassian.net/browse/WIFI-14165

Signed-off-by: Ivan Chvets <ivan.chvets@kinarasystems.com>
2024-09-30 09:39:44 -04:00
36 changed files with 1150 additions and 300 deletions

View File

@@ -21,7 +21,7 @@ defaults:
jobs: jobs:
docker: docker:
runs-on: ubuntu-20.04 runs-on: ubuntu-latest
env: env:
DOCKER_REGISTRY_URL: tip-tip-wlan-cloud-ucentral.jfrog.io DOCKER_REGISTRY_URL: tip-tip-wlan-cloud-ucentral.jfrog.io
DOCKER_REGISTRY_USERNAME: ucentral DOCKER_REGISTRY_USERNAME: ucentral

View File

@@ -11,7 +11,7 @@ defaults:
jobs: jobs:
helm-package: helm-package:
runs-on: ubuntu-20.04 runs-on: ubuntu-latest
env: env:
HELM_REPO_URL: https://tip.jfrog.io/artifactory/tip-wlan-cloud-ucentral-helm/ HELM_REPO_URL: https://tip.jfrog.io/artifactory/tip-wlan-cloud-ucentral-helm/
HELM_REPO_USERNAME: ucentral HELM_REPO_USERNAME: ucentral

2
.gitignore vendored
View File

@@ -29,4 +29,4 @@ helm/charts/*
!helm/charts/.gitkeep !helm/charts/.gitkeep
/portal-test/ /portal-test/
/src/ow_version.h /src/ow_version.h
.vscode/*

View File

@@ -1,5 +1,5 @@
cmake_minimum_required(VERSION 3.13) cmake_minimum_required(VERSION 3.13)
project(owgw VERSION 3.1.0) project(owgw VERSION 4.1.1)
set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED True) set(CMAKE_CXX_STANDARD_REQUIRED True)

View File

@@ -1,5 +1,5 @@
ARG DEBIAN_VERSION=11.5-slim ARG DEBIAN_VERSION=bookworm
ARG POCO_VERSION=poco-tip-v2 ARG POCO_VERSION=poco-tip-v4-tag
ARG CPPKAFKA_VERSION=tip-v1 ARG CPPKAFKA_VERSION=tip-v1
ARG VALIJASON_VERSION=tip-v1.0.2 ARG VALIJASON_VERSION=tip-v1.0.2
ARG APP_NAME=owgw ARG APP_NAME=owgw
@@ -100,7 +100,7 @@ RUN mkdir -p $APP_ROOT $APP_CONFIG && \
RUN apt-get update && apt-get install --no-install-recommends -y \ RUN apt-get update && apt-get install --no-install-recommends -y \
librdkafka++1 gosu gettext ca-certificates bash jq curl wget \ librdkafka++1 gosu gettext ca-certificates bash jq curl wget \
libmariadb-dev-compat libpq5 unixodbc postgresql-client libfmt7 sqlite3 libmariadb-dev-compat libpq5 unixodbc postgresql-client libfmt9 sqlite3
COPY readiness_check /readiness_check COPY readiness_check /readiness_check
COPY test_scripts/curl/cli /cli COPY test_scripts/curl/cli /cli

View File

@@ -324,6 +324,20 @@ should respond with message indicating failure or success.
} }
``` ```
If AP supports compressed configuration feature by inidcating `compress_cmd=true` in its capabilities, controller
will send a compressed configuration message where configuration payload (i.e. contents of `params`) is compressed
and encoded in base64 format:
```json
{ "jsonrpc" : "2.0",
"method" : "configure",
"params" : {
"compress_64" : "<b64 encoded zlib compressed payload>",
"compress_sz" : "<size of uncompressed data in bytes>"
},
"id" : <some number>
}
```
The device should answer: The device should answer:
```json ```json
{ "jsonrpc" : "2.0", { "jsonrpc" : "2.0",
@@ -866,6 +880,32 @@ The device should answer:
} }
``` ```
#### Controller wants the device to perform re-enrollment
Controller sends this command to trigger re-enrollment, i.e. update of operational certificate. Extreme care must be taken.
```json
{ "jsonrpc" : "2.0" ,
"method" : "reenroll" ,
"params" : {
"serial" : <serial number>,
"when" : Optional - <UTC time when to apply this config, 0 mean immediate, this is a suggestion>
},
"id" : <some number>
}
```
The device should answer:
```json
{ "jsonrpc" : "2.0" ,
"result" : {
"serial" : <serial number> ,
"status" : {
"error" : <0 or the value of $? from the shell running the command, 255 signifies a timeout>,
"txt" : <text describing the error or success>
},
"id" : <same number as request>
}
```
#### Controller wants the device to switch to another controller #### Controller wants the device to switch to another controller
Controller sends this when the device should change the controller it connects to without looking up a new redirector. Controller sends this when the device should change the controller it connects to without looking up a new redirector.

View File

@@ -32,6 +32,7 @@ if [[ "$TEMPLATE_CONFIG" = 'true' ]]; then
FILEUPLOADER_HOST_KEY_PASSWORD=${FILEUPLOADER_HOST_KEY_PASSWORD:-"mypassword"} \ FILEUPLOADER_HOST_KEY_PASSWORD=${FILEUPLOADER_HOST_KEY_PASSWORD:-"mypassword"} \
FILEUPLOADER_PATH=${FILEUPLOADER_PATH:-"\${APP_ROOT}/uploads"} \ FILEUPLOADER_PATH=${FILEUPLOADER_PATH:-"\${APP_ROOT}/uploads"} \
FILEUPLOADER_URI=${FILEUPLOADER_URI:-"https://localhost:16003"} \ FILEUPLOADER_URI=${FILEUPLOADER_URI:-"https://localhost:16003"} \
FILEUPLOADER_MAXSIZE=${FILEUPLOADER_MAXSIZE:-"10000"} \
SERVICE_KEY=${SERVICE_KEY:-"\${APP_ROOT}/certs/restapi-key.pem"} \ SERVICE_KEY=${SERVICE_KEY:-"\${APP_ROOT}/certs/restapi-key.pem"} \
SERVICE_KEY_PASSWORD=${SERVICE_KEY_PASSWORD:-"mypassword"} \ SERVICE_KEY_PASSWORD=${SERVICE_KEY_PASSWORD:-"mypassword"} \
SYSTEM_DATA=${SYSTEM_DATA:-"\${APP_ROOT}/data"} \ SYSTEM_DATA=${SYSTEM_DATA:-"\${APP_ROOT}/data"} \
@@ -76,6 +77,7 @@ if [[ "$TEMPLATE_CONFIG" = 'true' ]]; then
CERTIFICATES_ALLOWMISMATCH=${CERTIFICATES_ALLOWMISMATCH:-"false"} \ CERTIFICATES_ALLOWMISMATCH=${CERTIFICATES_ALLOWMISMATCH:-"false"} \
IPINFO_DEFAULT_COUNTRY=${IPINFO_DEFAULT_COUNTRY:-"US"} \ IPINFO_DEFAULT_COUNTRY=${IPINFO_DEFAULT_COUNTRY:-"US"} \
DEVICE_SESSION_TIMEOUT=${DEVICE_SESSION_TIMEOUT:-"600"} \ DEVICE_SESSION_TIMEOUT=${DEVICE_SESSION_TIMEOUT:-"600"} \
LOGGING_LEVEL=${LOGGING_LEVEL:-"information"} \
envsubst < /"${APP_NAME}".properties.tmpl > "${APP_CONFIG}"/"${APP_NAME}".properties envsubst < /"${APP_NAME}".properties.tmpl > "${APP_CONFIG}"/"${APP_NAME}".properties
fi fi

View File

@@ -1576,6 +1576,15 @@ components:
format: base64 format: base64
description: This is a base64 encoded string of the certificate bundle (the current bundle .tar.gz file from the PKI portal) description: This is a base64 encoded string of the certificate bundle (the current bundle .tar.gz file from the PKI portal)
ReenrollRequest:
type: object
properties:
serialNumber:
type: string
when:
type: integer
format: int64
PowerCycleRequest: PowerCycleRequest:
type: object type: object
properties: properties:
@@ -1600,6 +1609,74 @@ components:
maximum: 60000 maximum: 60000
description: off time in milliseconds description: off time in milliseconds
PackageGetResponse:
type: object
properties:
serial:
type: string
status:
type: object
properties:
package:
type: string
text:
type: string
uuid:
type: number
PackageInstallRequest:
type: object
properties:
serialNumber:
type: string
packages:
type: array
items:
type: object
properties:
name:
type: string
url:
type: string
PackageInstallResponse:
type: object
properties:
serial:
type: string
status:
type: object
properties:
error:
type: number
packages:
type: array
items:
type: object
properties:
name:
type: string
result:
type: string
text:
type: string
uuid:
type: number
PackageRemoveRequest:
type: object
properties:
serialNumber:
type: string
packages:
type: array
items:
type: object
properties:
name:
type: string
paths: paths:
/devices: /devices:
get: get:
@@ -3056,6 +3133,32 @@ paths:
404: 404:
$ref: '#/components/responses/NotFound' $ref: '#/components/responses/NotFound'
/device/{serialNumber}/reenroll:
post:
tags:
- Commands
summary: Reenroll operational certificate for the device.
operationId: reenrollCertificate
parameters:
- in: path
name: serialNumber
schema:
type: string
required: true
requestBody:
description: Reenroll operational certificate for the device
content:
application/json:
schema:
$ref: '#/components/schemas/ReenrollRequest'
responses:
200:
$ref: '#/components/responses/Success'
403:
$ref: '#/components/responses/Unauthorized'
404:
$ref: '#/components/responses/NotFound'
/device/{serialNumber}/powercycle: /device/{serialNumber}/powercycle:
post: post:
tags: tags:
@@ -3084,6 +3187,98 @@ paths:
404: 404:
$ref: '#/components/responses/NotFound' $ref: '#/components/responses/NotFound'
/device/{serialNumber}/package:
get:
tags:
- Commands
summary: Get package installed on the remote device.
operationId: getDevicePackages
parameters:
- in: path
name: serialNumber
schema:
type: string
required: true
- in: query
name: pkgName
schema:
type: string
required: true
description: The name or identifier of the package to retrieve.
responses:
200:
description: Successful command execution
content:
application/json:
schema:
$ref: '#/components/schemas/PackageGetResponse'
403:
$ref: '#/components/responses/Unauthorized'
404:
$ref: '#/components/responses/NotFound'
post:
tags:
- Commands
summary: Install IPK files to remote device.
operationId: postDevicePackages
parameters:
- in: path
name: serialNumber
schema:
type: string
required: true
requestBody:
description: Packages to be installed
content:
application/json:
schema:
$ref: '#/components/schemas/PackageInstallRequest'
responses:
200:
description: Successful command execution
content:
application/json:
schema:
$ref: '#/components/schemas/PackageInstallResponse'
400:
$ref: '#/components/responses/BadRequest'
403:
$ref: '#/components/responses/Unauthorized'
404:
$ref: '#/components/responses/NotFound'
delete:
tags:
- Commands
summary: Remove install packages from remote device.
operationId: deleteDevicePackages
parameters:
- in: path
name: serialNumber
schema:
type: string
required: true
requestBody:
description: Packages to be removed
content:
application/json:
schema:
$ref: '#/components/schemas/PackageRemoveRequest'
responses:
200:
content:
application/json:
schema:
$ref: '#/components/schemas/PackageInstallResponse'
400:
$ref: '#/components/responses/BadRequest'
403:
$ref: '#/components/responses/Unauthorized'
404:
$ref: '#/components/responses/NotFound'
/ouis: /ouis:
get: get:
tags: tags:

View File

@@ -52,7 +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.maxsize = 10000 # maxsize in KB
openwifi.fileuploader.maxsize = ${FILEUPLOADER_MAXSIZE}
openwifi.fileuploader.uri = ${FILEUPLOADER_URI} openwifi.fileuploader.uri = ${FILEUPLOADER_URI}
# #
@@ -182,4 +183,4 @@ archiver.db.3.keep = 7
######################################################################## ########################################################################
logging.type = console logging.type = console
logging.path = $OWGW_ROOT/logs logging.path = $OWGW_ROOT/logs
logging.level = information logging.level = ${LOGGING_LEVEL}

View File

@@ -7,6 +7,7 @@
#include <Poco/Net/Context.h> #include <Poco/Net/Context.h>
#include <Poco/Net/HTTPServerRequestImpl.h> #include <Poco/Net/HTTPServerRequestImpl.h>
#include <Poco/Net/HTTPServerResponseImpl.h> #include <Poco/Net/HTTPServerResponseImpl.h>
#include <Poco/JSON/JSONException.h>
#include <Poco/Net/NetException.h> #include <Poco/Net/NetException.h>
#include <Poco/Net/SSLException.h> #include <Poco/Net/SSLException.h>
#include <Poco/Net/SecureStreamSocketImpl.h> #include <Poco/Net/SecureStreamSocketImpl.h>
@@ -39,7 +40,7 @@ namespace OpenWifi {
Poco::Net::HTTPServerResponse &response, Poco::Net::HTTPServerResponse &response,
uint64_t session_id, Poco::Logger &L, uint64_t session_id, Poco::Logger &L,
std::pair<std::shared_ptr<Poco::Net::SocketReactor>, std::shared_ptr<LockedDbSession>> R) std::pair<std::shared_ptr<Poco::Net::SocketReactor>, std::shared_ptr<LockedDbSession>> R)
: Logger_(L) { : Logger_(L), IncomingFrame_(0) {
Reactor_ = R.first; Reactor_ = R.first;
DbSession_ = R.second; DbSession_ = R.second;
@@ -54,6 +55,7 @@ namespace OpenWifi {
WS_->setNoDelay(false); WS_->setNoDelay(false);
WS_->setKeepAlive(true); WS_->setKeepAlive(true);
WS_->setBlocking(false); WS_->setBlocking(false);
IncomingFrame_.resize(0);
uuid_ = MicroServiceRandom(std::numeric_limits<std::uint64_t>::max()-1); uuid_ = MicroServiceRandom(std::numeric_limits<std::uint64_t>::max()-1);
AP_WS_Server()->IncrementConnectionCount(); AP_WS_Server()->IncrementConnectionCount();
@@ -213,6 +215,7 @@ namespace OpenWifi {
} }
State_.certificateExpiryDate = PeerCert.expiresOn().timestamp().epochTime(); State_.certificateExpiryDate = PeerCert.expiresOn().timestamp().epochTime();
State_.certificateIssuerName = PeerCert.issuerName();
poco_trace(Logger_, poco_trace(Logger_,
fmt::format("TLS-CONNECTION({}): Session={} CN={} Completed. (t={})", CId_, fmt::format("TLS-CONNECTION({}): Session={} CN={} Completed. (t={})", CId_,
@@ -599,36 +602,95 @@ namespace OpenWifi {
EndConnection(); EndConnection();
} }
void AP_WS_Connection::ProcessIncomingFrame() { void AP_WS_Connection::ProcessWSFinalPayload() {
Poco::Buffer<char> IncomingFrame(0); auto IncomingSize = IncomingFrame_.size();
if (IncomingSize == 0) {
poco_debug(Logger_,
fmt::format("ProcessWSFrame({}): Final Acc. Frame received but empty",
CId_));
return;
}
IncomingFrame_.append(0);
poco_trace(Logger_,
fmt::format("ProcessWSFrame({}): Final Acc. Frame received (len={}, Msg={}",
CId_, IncomingSize, IncomingFrame_.begin()));
Poco::JSON::Parser parser;
auto ParsedMessage = parser.parse(IncomingFrame_.begin());
auto IncomingJSON = ParsedMessage.extract<Poco::JSON::Object::Ptr>();
if (IncomingJSON->has(uCentralProtocol::JSONRPC)) {
if (IncomingJSON->has(uCentralProtocol::METHOD) &&
IncomingJSON->has(uCentralProtocol::PARAMS)) {
ProcessJSONRPCEvent(IncomingJSON);
} else if (IncomingJSON->has(uCentralProtocol::RESULT) &&
IncomingJSON->has(uCentralProtocol::ID)) {
poco_trace(Logger_, fmt::format("RPC-RESULT({}): payload: {}", CId_,
IncomingFrame_.begin()));
ProcessJSONRPCResult(IncomingJSON);
} else {
poco_warning(
Logger_,
fmt::format("INVALID-PAYLOAD({}): Payload is not JSON-RPC 2.0: {}",
CId_, IncomingFrame_.begin()));
}
} else if (IncomingJSON->has(uCentralProtocol::RADIUS)) {
ProcessIncomingRadiusData(IncomingJSON);
} else {
std::ostringstream iS;
IncomingJSON->stringify(iS);
poco_warning(
Logger_,
fmt::format("FRAME({}): illegal transaction header, missing 'jsonrpc': {}",
CId_, iS.str()));
Errors_++;
}
IncomingFrame_.clear();
IncomingFrame_.resize(0);
}
void AP_WS_Connection::ProcessIncomingFrame() {
Poco::Buffer<char> CurrentFrame(0);
bool KillConnection = false;
int flags = 0;
int IncomingSize = 0;
bool KillConnection=false;
try { try {
int Op, flags; IncomingSize = WS_->receiveFrame(CurrentFrame, flags);
auto IncomingSize = WS_->receiveFrame(IncomingFrame, flags); int Op;
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) {
poco_trace(Logger_,
fmt::format("EMPTY({}): Non-blocking try-again empty frame (len={}, flags={})",
CId_, IncomingSize, flags));
} else if (IncomingSize == 0 && flags == 0) {
poco_information(Logger_, poco_information(Logger_,
fmt::format("DISCONNECT({}): device has disconnected. Session={}", fmt::format("DISCONNECT({}): device has disconnected. Session={}",
CId_, State_.sessionId)); CId_, State_.sessionId));
return EndConnection(); return EndConnection();
} }
IncomingFrame.append(0); if (IncomingSize > 0) {
State_.RX += IncomingSize;
State_.RX += IncomingSize; AP_WS_Server()->AddRX(IncomingSize);
AP_WS_Server()->AddRX(IncomingSize); IncomingFrame_.append(CurrentFrame);
}
State_.MessageCount++; State_.MessageCount++;
State_.LastContact = Utils::Now(); State_.LastContact = Utils::Now();
poco_trace(Logger_,
fmt::format("FRAME({}): Frame rx (op={} len={}, flags={}, acc.len={})",
CId_, Op, IncomingSize, flags, IncomingFrame_.size()));
switch (Op) { 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("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);
if (KafkaManager()->Enabled()) { if (KafkaManager()->Enabled()) {
Poco::JSON::Object PingObject; Poco::JSON::Object PingObject;
@@ -642,49 +704,32 @@ namespace OpenWifi {
PingDetails.set("locale", State_.locale); PingDetails.set("locale", State_.locale);
PingObject.set(uCentralProtocol::PING, PingDetails); PingObject.set(uCentralProtocol::PING, PingDetails);
poco_trace(Logger_,fmt::format("Sending PING for {}", SerialNumber_)); poco_trace(Logger_,fmt::format("Sending PING for {}", SerialNumber_));
KafkaManager()->PostMessage(KafkaTopics::CONNECTION, SerialNumber_,PingObject); KafkaManager()->PostMessage(KafkaTopics::CONNECTION, SerialNumber_,
PingObject);
} }
return;
} 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;
} break;
case Poco::Net::WebSocket::FRAME_OP_CONT: {
poco_trace(Logger_, fmt::format("CONTINUATION({}): registered.", CId_));
} break;
case Poco::Net::WebSocket::FRAME_OP_BINARY: {
poco_trace(Logger_, fmt::format("BINARY({}): Invalid frame type.", CId_));
KillConnection=true;
return;
} break; } break;
case Poco::Net::WebSocket::FRAME_OP_TEXT: { case Poco::Net::WebSocket::FRAME_OP_TEXT: {
poco_trace(Logger_, poco_trace(Logger_,
fmt::format("FRAME({}): Frame received (length={}, flags={}). Msg={}", fmt::format("TEXT({}): Frame received (len={}, flags={}). Msg={}",
CId_, IncomingSize, flags, IncomingFrame.begin())); CId_, IncomingSize, flags,
CurrentFrame.begin() == nullptr ? "" : CurrentFrame.begin()));
Poco::JSON::Parser parser;
auto ParsedMessage = parser.parse(IncomingFrame.begin());
auto IncomingJSON = ParsedMessage.extract<Poco::JSON::Object::Ptr>();
if (IncomingJSON->has(uCentralProtocol::JSONRPC)) {
if (IncomingJSON->has(uCentralProtocol::METHOD) &&
IncomingJSON->has(uCentralProtocol::PARAMS)) {
ProcessJSONRPCEvent(IncomingJSON);
} else if (IncomingJSON->has(uCentralProtocol::RESULT) &&
IncomingJSON->has(uCentralProtocol::ID)) {
poco_trace(Logger_, fmt::format("RPC-RESULT({}): payload: {}", CId_,
IncomingFrame.begin()));
ProcessJSONRPCResult(IncomingJSON);
} else {
poco_warning(
Logger_,
fmt::format("INVALID-PAYLOAD({}): Payload is not JSON-RPC 2.0: {}",
CId_, IncomingFrame.begin()));
}
} else if (IncomingJSON->has(uCentralProtocol::RADIUS)) {
ProcessIncomingRadiusData(IncomingJSON);
} else {
std::ostringstream iS;
IncomingJSON->stringify(iS);
poco_warning(
Logger_,
fmt::format("FRAME({}): illegal transaction header, missing 'jsonrpc': {}",
CId_, iS.str()));
Errors_++;
}
} break; } break;
case Poco::Net::WebSocket::FRAME_OP_CLOSE: { case Poco::Net::WebSocket::FRAME_OP_CLOSE: {
@@ -700,25 +745,31 @@ namespace OpenWifi {
return; return;
} }
} }
// Check for final frame and process accumulated payload
if (!KillConnection && (flags & Poco::Net::WebSocket::FRAME_FLAG_FIN) != 0) {
ProcessWSFinalPayload();
}
} catch (const Poco::Net::ConnectionResetException &E) { } catch (const Poco::Net::ConnectionResetException &E) {
poco_warning(Logger_, poco_warning(Logger_,
fmt::format("ConnectionResetException({}): Text:{} Payload:{} Session:{}", fmt::format("ConnectionResetException({}): Text:{} Payload:{} Session:{}",
CId_, E.displayText(), CId_, E.displayText(),
IncomingFrame.begin() == nullptr ? "" : IncomingFrame.begin(), CurrentFrame.begin() == nullptr ? "" : CurrentFrame.begin(),
State_.sessionId)); State_.sessionId));
KillConnection=true; KillConnection=true;
} catch (const Poco::JSON::JSONException &E) { } catch (const Poco::JSON::JSONException &E) {
poco_warning(Logger_, poco_warning(Logger_,
fmt::format("JSONException({}): Text:{} Payload:{} Session:{}", CId_, fmt::format("JSONException({}): Text:{} Payload:{} Session:{}", CId_,
E.displayText(), E.displayText(),
IncomingFrame.begin() == nullptr ? "" : IncomingFrame.begin(), CurrentFrame.begin() == nullptr ? "" : CurrentFrame.begin(),
State_.sessionId)); State_.sessionId));
KillConnection=true; KillConnection=true;
} catch (const Poco::Net::WebSocketException &E) { } catch (const Poco::Net::WebSocketException &E) {
poco_warning(Logger_, poco_warning(Logger_,
fmt::format("WebSocketException({}): Text:{} Payload:{} Session:{}", CId_, fmt::format("WebSocketException({}): Text:{} Payload:{} Session:{}", CId_,
E.displayText(), E.displayText(),
IncomingFrame.begin() == nullptr ? "" : IncomingFrame.begin(), CurrentFrame.begin() == nullptr ? "" : CurrentFrame.begin(),
State_.sessionId)); State_.sessionId));
KillConnection=true; KillConnection=true;
} catch (const Poco::Net::SSLConnectionUnexpectedlyClosedException &E) { } catch (const Poco::Net::SSLConnectionUnexpectedlyClosedException &E) {
@@ -727,42 +778,42 @@ namespace OpenWifi {
fmt::format( fmt::format(
"SSLConnectionUnexpectedlyClosedException({}): Text:{} Payload:{} Session:{}", "SSLConnectionUnexpectedlyClosedException({}): Text:{} Payload:{} Session:{}",
CId_, E.displayText(), CId_, E.displayText(),
IncomingFrame.begin() == nullptr ? "" : IncomingFrame.begin(), CurrentFrame.begin() == nullptr ? "" : CurrentFrame.begin(),
State_.sessionId)); State_.sessionId));
KillConnection=true; KillConnection=true;
} catch (const Poco::Net::SSLException &E) { } catch (const Poco::Net::SSLException &E) {
poco_warning(Logger_, poco_warning(Logger_,
fmt::format("SSLException({}): Text:{} Payload:{} Session:{}", CId_, fmt::format("SSLException({}): Text:{} Payload:{} Session:{}", CId_,
E.displayText(), E.displayText(),
IncomingFrame.begin() == nullptr ? "" : IncomingFrame.begin(), CurrentFrame.begin() == nullptr ? "" : CurrentFrame.begin(),
State_.sessionId)); State_.sessionId));
KillConnection=true; KillConnection=true;
} catch (const Poco::Net::NetException &E) { } catch (const Poco::Net::NetException &E) {
poco_warning(Logger_, poco_warning(Logger_,
fmt::format("NetException({}): Text:{} Payload:{} Session:{}", CId_, fmt::format("NetException({}): Text:{} Payload:{} Session:{}", CId_,
E.displayText(), E.displayText(),
IncomingFrame.begin() == nullptr ? "" : IncomingFrame.begin(), CurrentFrame.begin() == nullptr ? "" : CurrentFrame.begin(),
State_.sessionId)); State_.sessionId));
KillConnection=true; KillConnection=true;
} catch (const Poco::IOException &E) { } catch (const Poco::IOException &E) {
poco_warning(Logger_, poco_warning(Logger_,
fmt::format("IOException({}): Text:{} Payload:{} Session:{}", CId_, fmt::format("IOException({}): Text:{} Payload:{} Session:{}", CId_,
E.displayText(), E.displayText(),
IncomingFrame.begin() == nullptr ? "" : IncomingFrame.begin(), CurrentFrame.begin() == nullptr ? "" : CurrentFrame.begin(),
State_.sessionId)); State_.sessionId));
KillConnection=true; KillConnection=true;
} catch (const Poco::Exception &E) { } catch (const Poco::Exception &E) {
poco_warning(Logger_, poco_warning(Logger_,
fmt::format("Exception({}): Text:{} Payload:{} Session:{}", CId_, fmt::format("Exception({}): Text:{} Payload:{} Session:{}", CId_,
E.displayText(), E.displayText(),
IncomingFrame.begin() == nullptr ? "" : IncomingFrame.begin(), CurrentFrame.begin() == nullptr ? "" : CurrentFrame.begin(),
State_.sessionId)); State_.sessionId));
KillConnection=true; KillConnection=true;
} catch (const std::exception &E) { } catch (const std::exception &E) {
poco_warning(Logger_, poco_warning(Logger_,
fmt::format("std::exception({}): Text:{} Payload:{} Session:{}", CId_, fmt::format("std::exception({}): Text:{} Payload:{} Session:{}", CId_,
E.what(), E.what(),
IncomingFrame.begin() == nullptr ? "" : IncomingFrame.begin(), CurrentFrame.begin() == nullptr ? "" : CurrentFrame.begin(),
State_.sessionId)); State_.sessionId));
KillConnection=true; KillConnection=true;
} catch (...) { } catch (...) {
@@ -775,7 +826,9 @@ namespace OpenWifi {
if (!KillConnection && Errors_ < 10) if (!KillConnection && Errors_ < 10)
return; return;
poco_warning(Logger_, fmt::format("DISCONNECTING({}): ConnectionException: {} Errors: {}", CId_, KillConnection, Errors_ )); poco_warning(Logger_,
fmt::format("DISCONNECTING({}): ConnectionException: {} Errors: {}",
CId_, KillConnection, Errors_ ));
EndConnection(); EndConnection();
} }
@@ -920,4 +973,4 @@ namespace OpenWifi {
} }
} }
} // namespace OpenWifi } // namespace OpenWifi

View File

@@ -22,7 +22,7 @@
namespace OpenWifi { namespace OpenWifi {
class AP_WS_Connection { class AP_WS_Connection {
static constexpr int BufSize = 256000; static constexpr int BufSize = 512000;
public: public:
explicit AP_WS_Connection(Poco::Net::HTTPServerRequest &request, explicit AP_WS_Connection(Poco::Net::HTTPServerRequest &request,
@@ -33,6 +33,7 @@ namespace OpenWifi {
void EndConnection(); 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 ProcessWSFinalPayload();
void ProcessIncomingFrame(); void ProcessIncomingFrame();
void ProcessIncomingRadiusData(const Poco::JSON::Object::Ptr &Doc); void ProcessIncomingRadiusData(const Poco::JSON::Object::Ptr &Doc);
@@ -145,6 +146,7 @@ namespace OpenWifi {
std::uint64_t uuid_=0; std::uint64_t uuid_=0;
bool Simulated_=false; bool Simulated_=false;
std::atomic_uint64_t LastContact_=0; std::atomic_uint64_t LastContact_=0;
Poco::Buffer<char> IncomingFrame_;
static inline std::atomic_uint64_t ConcurrentStartingDevices_ = 0; static inline std::atomic_uint64_t ConcurrentStartingDevices_ = 0;
@@ -175,4 +177,4 @@ namespace OpenWifi {
}; };
} // namespace OpenWifi } // namespace OpenWifi

View File

@@ -105,7 +105,7 @@ namespace OpenWifi {
Restrictions_.developer = Capabilities->getValue<bool>("developer"); Restrictions_.developer = Capabilities->getValue<bool>("developer");
} }
if(Capabilities->has("secure-rtty")) { if (Capabilities->has("secure-rtty")) {
RTTYMustBeSecure_ = Capabilities->getValue<bool>("secure-rtty"); RTTYMustBeSecure_ = Capabilities->getValue<bool>("secure-rtty");
} }

View File

@@ -71,14 +71,18 @@ namespace OpenWifi {
bool AP_WS_Server::ValidateCertificate(const std::string &ConnectionId, bool AP_WS_Server::ValidateCertificate(const std::string &ConnectionId,
const Poco::Crypto::X509Certificate &Certificate) { const Poco::Crypto::X509Certificate &Certificate) {
if (IsCertOk()) { if (IsCertOk()) {
if (!Certificate.issuedBy(*IssuerCert_)) { // validate certificate agains trusted chain
poco_warning( for (const auto &cert : ClientCasCerts_) {
Logger(), if (Certificate.issuedBy(cert)) {
fmt::format("CERTIFICATE({}): issuer mismatch. Local='{}' Incoming='{}'", return true;
ConnectionId, IssuerCert_->issuerName(), Certificate.issuerName())); }
return false;
} }
return true; poco_warning(
Logger(),
fmt::format(
"CERTIFICATE({}): issuer mismatch. Certificate not issued by any trusted CA",
ConnectionId)
);
} }
return false; return false;
} }
@@ -116,7 +120,6 @@ namespace OpenWifi {
P.verificationDepth = 9; P.verificationDepth = 9;
P.loadDefaultCAs = Svr.RootCA().empty(); P.loadDefaultCAs = Svr.RootCA().empty();
P.cipherList = "ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH"; P.cipherList = "ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH";
P.dhUse2048Bits = true;
P.caLocation = Svr.Cas(); P.caLocation = Svr.Cas();
auto Context = Poco::AutoPtr<Poco::Net::Context>( auto Context = Poco::AutoPtr<Poco::Net::Context>(
@@ -133,6 +136,13 @@ namespace OpenWifi {
Context->addChainCertificate(Issuing); Context->addChainCertificate(Issuing);
Context->addCertificateAuthority(Issuing); Context->addCertificateAuthority(Issuing);
// add certificates from clientcas to trust chain
ClientCasCerts_ = Poco::Net::X509Certificate::readPEM(Svr.ClientCas());
for (const auto &cert : ClientCasCerts_) {
Context->addChainCertificate(cert);
Context->addCertificateAuthority(cert);
}
Poco::Crypto::RSAKey Key("", Svr.KeyFile(), Svr.KeyFilePassword()); Poco::Crypto::RSAKey Key("", Svr.KeyFile(), Svr.KeyFilePassword());
Context->usePrivateKey(Key); Context->usePrivateKey(Key);
@@ -784,4 +794,4 @@ namespace OpenWifi {
return false; return false;
} }
} // namespace OpenWifi } // namespace OpenWifi

View File

@@ -223,6 +223,7 @@ namespace OpenWifi {
mutable std::array<std::mutex,MACHashMax> SerialNumbersMutex_; mutable std::array<std::mutex,MACHashMax> SerialNumbersMutex_;
std::unique_ptr<Poco::Crypto::X509Certificate> IssuerCert_; std::unique_ptr<Poco::Crypto::X509Certificate> IssuerCert_;
std::vector<Poco::Crypto::X509Certificate> ClientCasCerts_;
std::list<std::unique_ptr<Poco::Net::HTTPServer>> WebServers_; std::list<std::unique_ptr<Poco::Net::HTTPServer>> WebServers_;
Poco::ThreadPool DeviceConnectionPool_{"ws:dev-pool", 4, 256}; Poco::ThreadPool DeviceConnectionPool_{"ws:dev-pool", 4, 256};
Poco::Net::SocketReactor Reactor_; Poco::Net::SocketReactor Reactor_;

View File

@@ -111,7 +111,7 @@ namespace OpenWifi {
i >> cache; i >> cache;
for (const auto &[Type, Platform] : cache.items()) { for (const auto &[Type, Platform] : cache.items()) {
Platforms_[Type] = Poco::toLower(to_string(Platform)); Platforms_[Type] = Poco::toLower(Platform.get<std::string>());
} }
} catch (...) { } catch (...) {
} }

View File

@@ -315,4 +315,4 @@ namespace OpenWifi {
poco_notice(Logger(), "Stopped..."); poco_notice(Logger(), "Stopped...");
} }
} // namespace OpenWifi } // namespace OpenWifi

View File

@@ -54,8 +54,8 @@ namespace OpenWifi::RESTAPI_RPC {
std::chrono::milliseconds WaitTimeInMs, Poco::JSON::Object *ObjectToReturn, std::chrono::milliseconds WaitTimeInMs, Poco::JSON::Object *ObjectToReturn,
RESTAPIHandler *Handler, Poco::Logger &Logger, bool Deferred) { RESTAPIHandler *Handler, Poco::Logger &Logger, bool Deferred) {
Logger.information(fmt::format("{},{}: New {} command. User={} Serial={}. ", Cmd.UUID, Logger.information(fmt::format("{},{}: New {} command. User={} Serial={} Details={}. ", Cmd.UUID,
RPCID, Cmd.Command, Cmd.SubmittedBy, Cmd.SerialNumber)); RPCID, Cmd.Command, Cmd.SubmittedBy, Cmd.SerialNumber, Cmd.Details));
Cmd.Submitted = Utils::Now(); Cmd.Submitted = Utils::Now();
Cmd.Executed = 0; Cmd.Executed = 0;

View File

@@ -91,6 +91,31 @@ namespace OpenWifi {
TransactionId_, UUID, RPC, Poco::Thread::current()->id())); TransactionId_, UUID, RPC, Poco::Thread::current()->id()));
return Rtty(UUID, RPC, 60000ms, Restrictions); return Rtty(UUID, RPC, 60000ms, Restrictions);
}; };
case APCommands::Commands::package:{
GWObjects::DeviceRestrictions Restrictions;
std::string pkg_name = "";
if (!AP_WS_Server()->Connected(SerialNumberInt_, Restrictions)) {
CallCanceled(Command_.c_str(), RESTAPI::Errors::DeviceNotConnected);
return BadRequest(RESTAPI::Errors::DeviceNotConnected);
}
Poco::URI uri(Request->getURI());
for (const auto &param : uri.getQueryParameters()) {
if (param.first == "pkgName") {
pkg_name = param.second;
}
}
if (pkg_name.empty()) {
return BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
}
auto UUID = MicroServiceCreateUUID();
auto RPC = CommandManager()->Next_RPC_ID();
poco_debug(
Logger_,
fmt::format(
"Command Package TID={} can proceed. Identified as {} and RPCID as {}. thr_id={}",
TransactionId_, UUID, RPC, Poco::Thread::current()->id()));
return GetPackages(UUID, RPC, pkg_name, 300000ms, Restrictions);
}
default: default:
return BadRequest(RESTAPI::Errors::InvalidCommand); return BadRequest(RESTAPI::Errors::InvalidCommand);
} }
@@ -128,6 +153,21 @@ namespace OpenWifi {
return DeleteChecks(); return DeleteChecks();
case APCommands::Commands::statistics: case APCommands::Commands::statistics:
return DeleteStatistics(); return DeleteStatistics();
case APCommands::Commands::package: {
GWObjects::DeviceRestrictions Restrictions;
if (!AP_WS_Server()->Connected(SerialNumberInt_, Restrictions)) {
CallCanceled(Command_.c_str(), RESTAPI::Errors::DeviceNotConnected);
return BadRequest(RESTAPI::Errors::DeviceNotConnected);
}
auto UUID = MicroServiceCreateUUID();
auto RPC = CommandManager()->Next_RPC_ID();
poco_debug(
Logger_,
fmt::format(
"Command RTTY TID={} can proceed. Identified as {} and RPCID as {}. thr_id={}",
TransactionId_, UUID, RPC, Poco::Thread::current()->id()));
return DeletePackages(UUID, RPC, 300000ms, Restrictions);
}
default: default:
return BadRequest(RESTAPI::Errors::InvalidCommand); return BadRequest(RESTAPI::Errors::InvalidCommand);
} }
@@ -170,7 +210,8 @@ namespace OpenWifi {
{APCommands::Commands::powercycle, false, true, &RESTAPI_device_commandHandler::PowerCycle, 60000ms}, {APCommands::Commands::powercycle, false, true, &RESTAPI_device_commandHandler::PowerCycle, 60000ms},
{APCommands::Commands::fixedconfig, false, true, &RESTAPI_device_commandHandler::FixedConfig, 120000ms}, {APCommands::Commands::fixedconfig, false, true, &RESTAPI_device_commandHandler::FixedConfig, 120000ms},
{APCommands::Commands::cablediagnostics, false, true, &RESTAPI_device_commandHandler::CableDiagnostics, 120000ms}, {APCommands::Commands::cablediagnostics, false, true, &RESTAPI_device_commandHandler::CableDiagnostics, 120000ms},
{APCommands::Commands::reenroll, false, true, &RESTAPI_device_commandHandler::ReEnroll, 120000ms},
{APCommands::Commands::package, false, true, &RESTAPI_device_commandHandler::PackageInstall, 120000ms},
}; };
void RESTAPI_device_commandHandler::DoPost() { void RESTAPI_device_commandHandler::DoPost() {
@@ -408,6 +449,210 @@ namespace OpenWifi {
BadRequest(RESTAPI::Errors::NoRecordsDeleted); BadRequest(RESTAPI::Errors::NoRecordsDeleted);
} }
void RESTAPI_device_commandHandler::GetPackages(const std::string &CMD_UUID, uint64_t CMD_RPC,
const std::string pkg_name,
[[maybe_unused]] std::chrono::milliseconds timeout,
[[maybe_unused]] const GWObjects::DeviceRestrictions &Restrictions) {
poco_debug(Logger_, fmt::format("GET-PACKAGES: TID={}, user={} serial={}. thr_id={}",
TransactionId_, Requester(), SerialNumber_,
Poco::Thread::current()->id()));
if (IsDeviceSimulated(SerialNumber_)) {
return BadRequest(RESTAPI::Errors::SimulatedDeviceNotSupported);
}
Poco::JSON::Object Params;
Params.set(uCentralProtocol::OPERATION, "list");
Params.set(uCentralProtocol::SERIAL, SerialNumber_);
Params.set(uCentralProtocol::PACKAGE, pkg_name);
std::stringstream ParamStream;
Params.stringify(ParamStream);
GWObjects::CommandDetails Cmd;
Cmd.SerialNumber = SerialNumber_;
Cmd.UUID = CMD_UUID;
Cmd.SubmittedBy = Requester();
Cmd.Command = uCentralProtocol::PACKAGE;
Cmd.RunAt = 0;
Cmd.Details = ParamStream.str();
RESTAPI_RPC::WaitForCommand(CMD_RPC, APCommands::Commands::package, false, Cmd, Params,
*Request, *Response, timeout, nullptr, nullptr, Logger_);
Poco::JSON::Object O, P;
Cmd.to_json(O);
Poco::Dynamic::Var resultsVar = O.get("results");
Poco::JSON::Object::Ptr resultsObj = resultsVar.extract<Poco::JSON::Object::Ptr>();
return ReturnObject(*resultsObj);
}
void RESTAPI_device_commandHandler::PackageInstall(
const std::string &CMD_UUID, uint64_t CMD_RPC,
[[maybe_unused]] std::chrono::milliseconds timeout,
[[maybe_unused]] const GWObjects::DeviceRestrictions &Restrictions) {
if (UserInfo_.userinfo.userRole != SecurityObjects::ROOT &&
UserInfo_.userinfo.userRole != SecurityObjects::ADMIN) {
CallCanceled("INSTALLPACKAGE", CMD_UUID, CMD_RPC, RESTAPI::Errors::ACCESS_DENIED);
return UnAuthorized(RESTAPI::Errors::ACCESS_DENIED);
}
poco_debug(Logger_, fmt::format("INSTALL-PACKAGES({},{}): TID={} user={} serial={}", CMD_UUID,
CMD_RPC, TransactionId_, Requester(), SerialNumber_));
if (IsDeviceSimulated(SerialNumber_)) {
CallCanceled("INSTALL-PACKAGES", CMD_UUID, CMD_RPC, RESTAPI::Errors::SimulatedDeviceNotSupported);
return BadRequest(RESTAPI::Errors::SimulatedDeviceNotSupported);
}
const auto &Obj = ParsedBody_;
if (!Obj->has(RESTAPI::Protocol::SERIALNUMBER)) {
return BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
}
auto SNum = Obj->get(RESTAPI::Protocol::SERIALNUMBER).toString();
if (SerialNumber_ != SNum) {
CallCanceled("INSTALL-PACKAGES", CMD_UUID, CMD_RPC, RESTAPI::Errors::SerialNumberMismatch);
return BadRequest(RESTAPI::Errors::SerialNumberMismatch);
}
std::ostringstream os;
ParsedBody_->stringify(os);
poco_information(Logger_, fmt::format("INSTALL_OBJECT: {} for device {}", os.str(), SerialNumber_));
GWObjects::PackageInstall PI;
if (!PI.from_json(ParsedBody_)) {
return BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
}
Poco::JSON::Array::Ptr ArrayObj = Poco::SharedPtr<Poco::JSON::Array>(new Poco::JSON::Array);
for (const auto &i : PI.pkgs) {
Poco::JSON::Object::Ptr Obj =
Poco::SharedPtr<Poco::JSON::Object>(new Poco::JSON::Object);
i.to_json(*Obj);
ArrayObj->add(Obj);
}
Poco::JSON::Object Params;
Params.set(uCentralProtocol::OPERATION, "install");
Params.set(uCentralProtocol::SERIAL, SerialNumber_);
Params.set(uCentralProtocol::PACKAGES, ArrayObj);
std::ostringstream os2;
Params.stringify(os2);
poco_information(Logger_, fmt::format("INSTALL_OBJECT2: {} for device {}", os2.str(), SerialNumber_));
std::stringstream ParamStream;
Params.stringify(ParamStream);
GWObjects::CommandDetails Cmd;
Cmd.SerialNumber = SerialNumber_;
Cmd.UUID = CMD_UUID;
Cmd.SubmittedBy = Requester();
Cmd.Command = uCentralProtocol::PACKAGE;
Cmd.RunAt = 0;
Cmd.Details = ParamStream.str();
RESTAPI_RPC::WaitForCommand(CMD_RPC, APCommands::Commands::package, false, Cmd, Params,
*Request, *Response, timeout, nullptr, nullptr, Logger_);
Poco::JSON::Object O, P;
Cmd.to_json(O);
Poco::Dynamic::Var resultsVar = O.get("results");
Poco::JSON::Object::Ptr resultsObj = resultsVar.extract<Poco::JSON::Object::Ptr>();
return ReturnObject(*resultsObj);
}
void RESTAPI_device_commandHandler::DeletePackages(
const std::string &CMD_UUID, uint64_t CMD_RPC,
[[maybe_unused]] std::chrono::milliseconds timeout,
[[maybe_unused]] const GWObjects::DeviceRestrictions &Restrictions) {
if (UserInfo_.userinfo.userRole != SecurityObjects::ROOT &&
UserInfo_.userinfo.userRole != SecurityObjects::ADMIN) {
CallCanceled("DELETE-PACKAGES", CMD_UUID, CMD_RPC, RESTAPI::Errors::ACCESS_DENIED);
return UnAuthorized(RESTAPI::Errors::ACCESS_DENIED);
}
poco_debug(Logger_, fmt::format("DELETE-PACKAGES({},{}): TID={} user={} serial={}", CMD_UUID,
CMD_RPC, TransactionId_, Requester(), SerialNumber_));
if (IsDeviceSimulated(SerialNumber_)) {
CallCanceled("DELETE-PACKAGES", CMD_UUID, CMD_RPC, RESTAPI::Errors::SimulatedDeviceNotSupported);
return BadRequest(RESTAPI::Errors::SimulatedDeviceNotSupported);
}
const auto &Obj = ParsedBody_;
if (!Obj->has(RESTAPI::Protocol::SERIALNUMBER)) {
return BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
}
auto SNum = Obj->get(RESTAPI::Protocol::SERIALNUMBER).toString();
if (SerialNumber_ != SNum) {
CallCanceled("DELETE-PACKAGES", CMD_UUID, CMD_RPC, RESTAPI::Errors::SerialNumberMismatch);
return BadRequest(RESTAPI::Errors::SerialNumberMismatch);
}
std::ostringstream os;
ParsedBody_->stringify(os);
poco_information(Logger_, fmt::format("DELETE_OBJECT: {} for device {}", os.str(), SerialNumber_));
GWObjects::PackageRemove PR;
if (!PR.from_json(ParsedBody_)) {
return BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
}
Poco::JSON::Array::Ptr ArrayObj = Poco::SharedPtr<Poco::JSON::Array>(new Poco::JSON::Array);
for (const auto &i : PR.pkgs) {
Poco::JSON::Object::Ptr Obj =
Poco::SharedPtr<Poco::JSON::Object>(new Poco::JSON::Object);
i.to_json(*Obj);
ArrayObj->add(Obj);
}
Poco::JSON::Object Params;
Params.set(uCentralProtocol::OPERATION, "delete");
Params.set(uCentralProtocol::SERIAL, SerialNumber_);
Params.set(uCentralProtocol::PACKAGES, ArrayObj);
std::ostringstream os2;
Params.stringify(os2);
poco_information(Logger_, fmt::format("DELETE_OBJECT2: {} for device {}", os2.str(), SerialNumber_));
std::stringstream ParamStream;
Params.stringify(ParamStream);
GWObjects::CommandDetails Cmd;
Cmd.SerialNumber = SerialNumber_;
Cmd.UUID = CMD_UUID;
Cmd.SubmittedBy = Requester();
Cmd.Command = uCentralProtocol::PACKAGE;
Cmd.RunAt = 0;
Cmd.Details = ParamStream.str();
RESTAPI_RPC::WaitForCommand(CMD_RPC, APCommands::Commands::package, false, Cmd, Params,
*Request, *Response, timeout, nullptr, nullptr, Logger_);
Poco::JSON::Object O, P;
Cmd.to_json(O);
Poco::Dynamic::Var resultsVar = O.get("results");
Poco::JSON::Object::Ptr resultsObj = resultsVar.extract<Poco::JSON::Object::Ptr>();
return ReturnObject(*resultsObj);
}
void RESTAPI_device_commandHandler::Ping( void RESTAPI_device_commandHandler::Ping(
const std::string &CMD_UUID, uint64_t CMD_RPC, std::chrono::milliseconds timeout, const std::string &CMD_UUID, uint64_t CMD_RPC, std::chrono::milliseconds timeout,
[[maybe_unused]] const GWObjects::DeviceRestrictions &Restrictions) { [[maybe_unused]] const GWObjects::DeviceRestrictions &Restrictions) {
@@ -694,9 +939,31 @@ namespace OpenWifi {
Params.stringify(ParamStream); Params.stringify(ParamStream);
Cmd.Details = ParamStream.str(); Cmd.Details = ParamStream.str();
// retrieve capabilities and encode/compress parameters, if required
Poco::JSON::Object ConfigParams = Params;
GWObjects::Capabilities Caps;
if (StorageService()->GetDeviceCapabilities(SerialNumber_, Caps)) {
Poco::JSON::Object CapsJson;
Caps.to_json(CapsJson);
auto DeviceCaps = CapsJson.getObject(uCentralProtocol::CAPABILITIES);
if (DeviceCaps->has("compress_cmd") && DeviceCaps->get("compress_cmd")) {
// compressed command capability present and it is set, compress parameters
Poco::JSON::Object CompressedParams;
std::string CompressedBase64Data;
std::uint64_t UncompressedDataLen = ParamStream.str().length();
if (Utils::CompressAndEncodeBase64(ParamStream.str(), CompressedBase64Data)) {
// set compressed, base 64 encoded data and length of uncompressed data
CompressedParams.set(uCentralProtocol::COMPRESS_64, CompressedBase64Data);
CompressedParams.set(uCentralProtocol::COMPRESS_SZ, UncompressedDataLen);
ConfigParams = CompressedParams;
}
}
}
// AP_WS_Server()->SetPendingUUID(SerialNumber_, NewUUID); // AP_WS_Server()->SetPendingUUID(SerialNumber_, NewUUID);
RESTAPI_RPC::WaitForCommand(CMD_RPC, APCommands::Commands::configure, true, RESTAPI_RPC::WaitForCommand(CMD_RPC, APCommands::Commands::configure, true,
Cmd, Params, *Request, *Response, timeout, Cmd, ConfigParams, *Request, *Response, timeout,
nullptr, this, Logger_); nullptr, this, Logger_);
if(!Cmd.Executed) { if(!Cmd.Executed) {
@@ -1629,4 +1896,45 @@ namespace OpenWifi {
*ParsedBody_, *Request, *Response, timeout, nullptr, this, *ParsedBody_, *Request, *Response, timeout, nullptr, this,
Logger_); Logger_);
} }
void RESTAPI_device_commandHandler::ReEnroll(
const std::string &CMD_UUID, uint64_t CMD_RPC,
[[maybe_unused]] std::chrono::milliseconds timeout,
[[maybe_unused]] const GWObjects::DeviceRestrictions &Restrictions) {
if(UserInfo_.userinfo.userRole != SecurityObjects::ROOT &&
UserInfo_.userinfo.userRole != SecurityObjects::ADMIN) {
CallCanceled("REENROLL", CMD_UUID, CMD_RPC, RESTAPI::Errors::ACCESS_DENIED);
return UnAuthorized(RESTAPI::Errors::ACCESS_DENIED);
}
poco_debug(Logger_, fmt::format("REENROLL({},{}): TID={} user={} serial={}", CMD_UUID,
CMD_RPC, TransactionId_, Requester(), SerialNumber_));
if(IsDeviceSimulated(SerialNumber_)) {
CallCanceled("REENROLL", CMD_UUID, CMD_RPC, RESTAPI::Errors::SimulatedDeviceNotSupported);
return BadRequest(RESTAPI::Errors::SimulatedDeviceNotSupported);
}
GWObjects::ReEnroll PR;
if(!PR.from_json(ParsedBody_)) {
return BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
}
GWObjects::CommandDetails Cmd;
Cmd.SerialNumber = SerialNumber_;
Cmd.SubmittedBy = Requester();
Cmd.UUID = CMD_UUID;
Cmd.Command = uCentralProtocol::REENROLL;
std::ostringstream os;
ParsedBody_->stringify(os);
Cmd.Details = os.str();
Cmd.RunAt = PR.when;
Cmd.ErrorCode = 0;
Cmd.WaitingForFile = 0;
return RESTAPI_RPC::WaitForCommand(CMD_RPC, APCommands::Commands::reenroll, false, Cmd,
*ParsedBody_, *Request, *Response, timeout, nullptr, this,
Logger_);
}
} // namespace OpenWifi } // namespace OpenWifi

View File

@@ -33,6 +33,13 @@ namespace OpenWifi {
void GetStatus(); void GetStatus();
void GetChecks(); void GetChecks();
void DeleteChecks(); void DeleteChecks();
void GetPackages(const std::string &UUID, uint64_t RPC,
std::string pkg_name,
std::chrono::milliseconds timeout,
const GWObjects::DeviceRestrictions &R);
void DeletePackages(const std::string &UUID, uint64_t RPC,
std::chrono::milliseconds timeout,
const GWObjects::DeviceRestrictions &R);
bool IsDeviceSimulated(std::string &Serial); bool IsDeviceSimulated(std::string &Serial);
@@ -74,6 +81,10 @@ namespace OpenWifi {
const GWObjects::DeviceRestrictions &R); const GWObjects::DeviceRestrictions &R);
void CableDiagnostics(const std::string &UUID, uint64_t RPC, std::chrono::milliseconds timeout, void CableDiagnostics(const std::string &UUID, uint64_t RPC, std::chrono::milliseconds timeout,
const GWObjects::DeviceRestrictions &R); const GWObjects::DeviceRestrictions &R);
void ReEnroll(const std::string &UUID, uint64_t RPC, std::chrono::milliseconds timeout,
const GWObjects::DeviceRestrictions &R);
void PackageInstall(const std::string &UUID, uint64_t RPC, std::chrono::milliseconds timeout,
const GWObjects::DeviceRestrictions &R);
static auto PathName() { static auto PathName() {
return std::list<std::string>{"/api/v1/device/{serialNumber}/{command}"}; return std::list<std::string>{"/api/v1/device/{serialNumber}/{command}"};

View File

@@ -12,9 +12,9 @@
#include "Daemon.h" #include "Daemon.h"
#ifdef TIP_GATEWAY_SERVICE #ifdef TIP_GATEWAY_SERVICE
#include "AP_WS_Server.h" #include "AP_WS_Server.h"
#include "StorageService.h"
#include "CapabilitiesCache.h" #include "CapabilitiesCache.h"
#include "RADIUSSessionTracker.h" #include "RADIUSSessionTracker.h"
#include "StorageService.h"
#endif #endif
#include "RESTAPI_GWobjects.h" #include "RESTAPI_GWobjects.h"
@@ -31,7 +31,8 @@ namespace OpenWifi::GWObjects {
field_to_json(Obj, "serialNumber", SerialNumber); field_to_json(Obj, "serialNumber", SerialNumber);
#ifdef TIP_GATEWAY_SERVICE #ifdef TIP_GATEWAY_SERVICE
field_to_json(Obj, "deviceType", StorageService()->GetPlatform(SerialNumber)); field_to_json(Obj, "deviceType", StorageService()->GetPlatform(SerialNumber));
field_to_json(Obj, "blackListed", StorageService()->IsBlackListed(Utils::MACToInt(SerialNumber))); field_to_json(Obj, "blackListed",
StorageService()->IsBlackListed(Utils::MACToInt(SerialNumber)));
#endif #endif
field_to_json(Obj, "macAddress", MACAddress); field_to_json(Obj, "macAddress", MACAddress);
field_to_json(Obj, "manufacturer", Manufacturer); field_to_json(Obj, "manufacturer", Manufacturer);
@@ -70,12 +71,12 @@ namespace OpenWifi::GWObjects {
#ifdef TIP_GATEWAY_SERVICE #ifdef TIP_GATEWAY_SERVICE
ConnectionState ConState; ConnectionState ConState;
#ifdef USE_MEDUSA_CLIENT #ifdef USE_MEDUSA_CLIENT
auto Res = GS()->GetState(SerialNumber); auto Res = GS()->GetState(SerialNumber);
if (Res.has_value()) { if (Res.has_value()) {
Res.value().to_json(SerialNumber,Obj); Res.value().to_json(SerialNumber, Obj);
#else #else
if (AP_WS_Server()->GetState(SerialNumber, ConState)) { if (AP_WS_Server()->GetState(SerialNumber, ConState)) {
ConState.to_json(SerialNumber,Obj); ConState.to_json(SerialNumber, Obj);
#endif #endif
} else { } else {
field_to_json(Obj, "ipAddress", ""); field_to_json(Obj, "ipAddress", "");
@@ -172,17 +173,16 @@ namespace OpenWifi::GWObjects {
field_to_json(Obj, "recorded", Recorded); field_to_json(Obj, "recorded", Recorded);
} }
bool HealthCheck::from_json(const Poco::JSON::Object::Ptr &Obj) { bool HealthCheck::from_json(const Poco::JSON::Object::Ptr &Obj) {
try { try {
field_from_json(Obj, "UUID", UUID); field_from_json(Obj, "UUID", UUID);
field_from_json(Obj, "sanity", Sanity); field_from_json(Obj, "sanity", Sanity);
field_from_json(Obj, "recorded", Recorded); field_from_json(Obj, "recorded", Recorded);
return true; return true;
} catch(...) { } catch (...) {
}
} return false;
return false; }
}
void DefaultFirmware::to_json(Poco::JSON::Object &Obj) const { void DefaultFirmware::to_json(Poco::JSON::Object &Obj) const {
field_to_json(Obj, "deviceType", deviceType); field_to_json(Obj, "deviceType", deviceType);
@@ -275,7 +275,8 @@ namespace OpenWifi::GWObjects {
return false; return false;
} }
void ConnectionState::to_json([[maybe_unused]] const std::string &SerialNumber, Poco::JSON::Object &Obj) { void ConnectionState::to_json([[maybe_unused]] const std::string &SerialNumber,
Poco::JSON::Object &Obj) {
field_to_json(Obj, "ipAddress", Address); field_to_json(Obj, "ipAddress", Address);
field_to_json(Obj, "txBytes", TX); field_to_json(Obj, "txBytes", TX);
field_to_json(Obj, "rxBytes", RX); field_to_json(Obj, "rxBytes", RX);
@@ -297,14 +298,15 @@ namespace OpenWifi::GWObjects {
field_to_json(Obj, "connectionCompletionTime", connectionCompletionTime); field_to_json(Obj, "connectionCompletionTime", connectionCompletionTime);
field_to_json(Obj, "totalConnectionTime", Utils::Now() - started); field_to_json(Obj, "totalConnectionTime", Utils::Now() - started);
field_to_json(Obj, "certificateExpiryDate", certificateExpiryDate); field_to_json(Obj, "certificateExpiryDate", certificateExpiryDate);
field_to_json(Obj, "certificateIssuerName", certificateIssuerName);
field_to_json(Obj, "connectReason", connectReason); field_to_json(Obj, "connectReason", connectReason);
field_to_json(Obj, "uptime", uptime); field_to_json(Obj, "uptime", uptime);
field_to_json(Obj, "compatible", Compatible); field_to_json(Obj, "compatible", Compatible);
#ifdef TIP_GATEWAY_SERVICE #ifdef TIP_GATEWAY_SERVICE
hasRADIUSSessions = RADIUSSessionTracker()->HasSessions(SerialNumber); hasRADIUSSessions = RADIUSSessionTracker()->HasSessions(SerialNumber);
#endif #endif
field_to_json(Obj, "hasRADIUSSessions", hasRADIUSSessions ); field_to_json(Obj, "hasRADIUSSessions", hasRADIUSSessions);
field_to_json(Obj, "hasGPS", hasGPS); field_to_json(Obj, "hasGPS", hasGPS);
field_to_json(Obj, "sanity", sanity); field_to_json(Obj, "sanity", sanity);
field_to_json(Obj, "memoryUsed", memoryUsed); field_to_json(Obj, "memoryUsed", memoryUsed);
@@ -334,44 +336,45 @@ namespace OpenWifi::GWObjects {
} }
} }
bool ConnectionState::from_json(const Poco::JSON::Object::Ptr &Obj) { bool ConnectionState::from_json(const Poco::JSON::Object::Ptr &Obj) {
try { try {
field_from_json(Obj, "compatible", Compatible); field_from_json(Obj, "compatible", Compatible);
field_from_json(Obj, "ipAddress", Address); field_from_json(Obj, "ipAddress", Address);
field_from_json(Obj, "txBytes", TX); field_from_json(Obj, "txBytes", TX);
field_from_json(Obj, "rxBytes", RX); field_from_json(Obj, "rxBytes", RX);
field_from_json(Obj, "messageCount", MessageCount); field_from_json(Obj, "messageCount", MessageCount);
field_from_json(Obj, "UUID", UUID); field_from_json(Obj, "UUID", UUID);
field_from_json(Obj, "connected", Connected); field_from_json(Obj, "connected", Connected);
field_from_json(Obj, "firmware", Firmware); field_from_json(Obj, "firmware", Firmware);
field_from_json(Obj, "lastContact", LastContact); field_from_json(Obj, "lastContact", LastContact);
field_from_json(Obj, "associations_2G", Associations_2G); field_from_json(Obj, "associations_2G", Associations_2G);
field_from_json(Obj, "associations_5G", Associations_5G); field_from_json(Obj, "associations_5G", Associations_5G);
field_from_json(Obj, "associations_6G", Associations_6G); field_from_json(Obj, "associations_6G", Associations_6G);
field_from_json(Obj, "webSocketClients", webSocketClients); field_from_json(Obj, "webSocketClients", webSocketClients);
field_from_json(Obj, "websocketPackets", websocketPackets); field_from_json(Obj, "websocketPackets", websocketPackets);
field_from_json(Obj, "kafkaClients", kafkaClients); field_from_json(Obj, "kafkaClients", kafkaClients);
field_from_json(Obj, "kafkaPackets", kafkaPackets); field_from_json(Obj, "kafkaPackets", kafkaPackets);
field_from_json(Obj, "locale", locale); field_from_json(Obj, "locale", locale);
field_from_json(Obj, "started", started); field_from_json(Obj, "started", started);
field_from_json(Obj, "sessionId", sessionId); field_from_json(Obj, "sessionId", sessionId);
field_from_json(Obj, "connectionCompletionTime", connectionCompletionTime); field_from_json(Obj, "connectionCompletionTime", connectionCompletionTime);
field_from_json(Obj, "totalConnectionTime", totalConnectionTime); field_from_json(Obj, "totalConnectionTime", totalConnectionTime);
field_from_json(Obj, "certificateExpiryDate", certificateExpiryDate); field_from_json(Obj, "certificateExpiryDate", certificateExpiryDate);
field_from_json(Obj, "connectReason", connectReason); field_from_json(Obj, "certificateIssuerName", certificateIssuerName);
field_from_json(Obj, "uptime", uptime); field_from_json(Obj, "connectReason", connectReason);
field_from_json(Obj, "hasRADIUSSessions", hasRADIUSSessions ); field_from_json(Obj, "uptime", uptime);
field_from_json(Obj, "hasGPS", hasGPS); field_from_json(Obj, "hasRADIUSSessions", hasRADIUSSessions);
field_from_json(Obj, "sanity", sanity); field_from_json(Obj, "hasGPS", hasGPS);
field_from_json(Obj, "memoryUsed", memoryUsed); field_from_json(Obj, "sanity", sanity);
field_from_json(Obj, "sanity", sanity); field_from_json(Obj, "memoryUsed", memoryUsed);
field_from_json(Obj, "load", load); field_from_json(Obj, "sanity", sanity);
field_from_json(Obj, "temperature", temperature); field_from_json(Obj, "load", load);
return true; field_from_json(Obj, "temperature", temperature);
} catch(const Poco::Exception &E) { return true;
} } catch (const Poco::Exception &E) {
return false; }
} return false;
}
void DeviceConnectionStatistics::to_json(Poco::JSON::Object &Obj) const { void DeviceConnectionStatistics::to_json(Poco::JSON::Object &Obj) const {
field_to_json(Obj, "averageConnectionTime", averageConnectionTime); field_to_json(Obj, "averageConnectionTime", averageConnectionTime);
@@ -819,4 +822,103 @@ namespace OpenWifi::GWObjects {
} }
return false; return false;
} }
bool ReEnroll::from_json(const Poco::JSON::Object::Ptr &Obj) {
try {
field_from_json(Obj, "serial", serialNumber);
field_from_json(Obj, "when", when);
return true;
} catch (const Poco::Exception &E) {
}
return false;
}
bool PackageInfo::from_json(const Poco::JSON::Object::Ptr &Obj) {
try {
field_from_json(Obj, "name", name);
field_from_json(Obj, "version", version);
return true;
} catch (const Poco::Exception &E) {
}
return false;
}
void PackageInfo::to_json(Poco::JSON::Object &Obj) const {
field_to_json(Obj, "name", name);
field_to_json(Obj, "version", version);
}
void PackageList::to_json(Poco::JSON::Object &Obj) const {
Obj.set("serialNumber", serialNumber);
Poco::JSON::Array packageJsonArray;
for (const auto &pkg : packageArray) {
Poco::JSON::Object pkgObj;
pkg.to_json(pkgObj);
packageJsonArray.add(pkgObj);
}
Obj.set("packageArray", packageJsonArray);
Obj.set("FirstUpdate", Poco::UInt64(FirstUpdate));
Obj.set("LastUpdate", Poco::UInt64(LastUpdate));
}
bool ToBeInstalled::from_json(const Poco::JSON::Object::Ptr &Obj) {
try {
field_from_json(Obj, "name", name);
field_from_json(Obj, "url", url);
Poco::URI uri(url);
std::string scheme = uri.getScheme();
if (scheme != "http" && scheme != "https") {
return false;
}
return true;
} catch (const Poco::Exception &E) {
}
return false;
}
void ToBeInstalled::to_json(Poco::JSON::Object &Obj) const {
Obj.set("name", name);
Obj.set("url", url);
}
bool PackageInstall::from_json(const Poco::JSON::Object::Ptr &Obj) {
try {
field_from_json(Obj, "serialNumber", serialNumber);
field_from_json(Obj, "when", when);
field_from_json(Obj, "packages", pkgs);
return true;
} catch (const Poco::Exception &E) {
}
return false;
}
bool ToBeRemoved::from_json(const Poco::JSON::Object::Ptr &Obj) {
try {
field_from_json(Obj, "name", name);
return true;
} catch (const Poco::Exception &E) {
}
return false;
}
void ToBeRemoved::to_json(Poco::JSON::Object &Obj) const {
Obj.set("name", name);
}
bool PackageRemove::from_json(const Poco::JSON::Object::Ptr &Obj) {
try {
field_from_json(Obj, "serialNumber", serialNumber);
field_from_json(Obj, "packages", pkgs);
return true;
} catch (const Poco::Exception &E) {
}
return false;
}
} // namespace OpenWifi::GWObjects } // namespace OpenWifi::GWObjects

View File

@@ -42,6 +42,7 @@ namespace OpenWifi::GWObjects {
uint64_t sessionId = 0; uint64_t sessionId = 0;
double connectionCompletionTime = 0.0; double connectionCompletionTime = 0.0;
std::uint64_t certificateExpiryDate = 0; std::uint64_t certificateExpiryDate = 0;
std::string certificateIssuerName;
std::uint64_t hasRADIUSSessions = 0; std::uint64_t hasRADIUSSessions = 0;
bool hasGPS = false; bool hasGPS = false;
std::uint64_t sanity=0; std::uint64_t sanity=0;
@@ -545,6 +546,57 @@ namespace OpenWifi::GWObjects {
std::uint64_t when; std::uint64_t when;
std::vector<std::string> ports; std::vector<std::string> ports;
bool from_json(const Poco::JSON::Object::Ptr &Obj);
};
struct ReEnroll {
std::string serialNumber;
std::uint64_t when;
bool from_json(const Poco::JSON::Object::Ptr &Obj);
};
struct PackageInfo {
std::string name;
std::string version;
bool from_json(const Poco::JSON::Object::Ptr &Obj);
void to_json(Poco::JSON::Object &Obj) const;
};
struct PackageList {
std::string serialNumber;
std::vector<PackageInfo> packageArray;
uint64_t FirstUpdate = 0;
uint64_t LastUpdate = 0;
std::string packageStringArray;
bool from_json(const Poco::JSON::Array::Ptr &Obj);
void to_json(Poco::JSON::Object &Obj) const;
};
struct ToBeInstalled {
std::string name;
std::string url;
bool from_json(const Poco::JSON::Object::Ptr &Obj);
void to_json(Poco::JSON::Object &Obj) const;
};
struct PackageInstall {
std::string serialNumber;
std::uint64_t when;
std::vector<ToBeInstalled> pkgs;
bool from_json(const Poco::JSON::Object::Ptr &Obj);
void to_json(Poco::JSON::Object &Obj) const;
};
struct ToBeRemoved {
std::string name;
bool from_json(const Poco::JSON::Object::Ptr &Obj);
void to_json(Poco::JSON::Object &Obj) const;
};
struct PackageRemove {
std::string serialNumber;
std::uint64_t when;
std::vector<ToBeRemoved> pkgs;
bool from_json(const Poco::JSON::Object::Ptr &Obj); bool from_json(const Poco::JSON::Object::Ptr &Obj);
}; };
} // namespace OpenWifi::GWObjects } // namespace OpenWifi::GWObjects

View File

@@ -120,14 +120,16 @@ namespace OpenWifi {
Poco::Buffer<char> IncomingFrame(0); Poco::Buffer<char> IncomingFrame(0);
try { try {
int Op, flags; int Op, flags, IncomingSize;
int IncomingSize;
IncomingSize = WS_->receiveFrame(IncomingFrame, flags); IncomingSize = WS_->receiveFrame(IncomingFrame, flags);
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 == -1) {
poco_information( poco_trace(Logger(),
Logger(), fmt::format("TELEMETRY-EMPTY({}): Empty frame, non-blocking try-again.", CId_));
} else if (IncomingSize == 0 && flags == 0 && Op == 0) {
poco_information(Logger(),
fmt::format("TELEMETRY-DISCONNECT({}): device has disconnected.", CId_)); fmt::format("TELEMETRY-DISCONNECT({}): device has disconnected.", CId_));
MustDisconnect = true; MustDisconnect = true;
} else { } else {
@@ -136,12 +138,14 @@ namespace OpenWifi {
fmt::format("TELEMETRY-WS-PING({}): received. PONG sent back.", CId_)); 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) {
poco_information( poco_information(Logger(),
Logger(),
fmt::format("TELEMETRY-DISCONNECT({}): device wants to disconnect.", CId_)); fmt::format("TELEMETRY-DISCONNECT({}): device wants to disconnect.", CId_));
MustDisconnect = true; MustDisconnect = true;
} else if (Op == Poco::Net::WebSocket::FRAME_OP_CONT) {
poco_information(Logger(),
fmt::format("TELEMETRY-CONT({}): rx {} bytes.", CId_, IncomingSize));
} }
} }
} catch (...) { } catch (...) {
@@ -154,4 +158,4 @@ namespace OpenWifi {
SendTelemetryShutdown(); SendTelemetryShutdown();
} }
} // namespace OpenWifi } // namespace OpenWifi

View File

@@ -276,7 +276,8 @@ static std::string DefaultAPSchema = R"foo(
"sae-mixed", "sae-mixed",
"wpa3", "wpa3",
"wpa3-192", "wpa3-192",
"wpa3-mixed" "wpa3-mixed",
"mpsk-radius"
], ],
"examples": [ "examples": [
"psk2" "psk2"
@@ -376,18 +377,21 @@ static std::string DefaultAPSchema = R"foo(
"properties": { "properties": {
"port-mirror": { "port-mirror": {
"description": "Enable mirror of traffic from multiple minotor ports to a single analysis port.", "description": "Enable mirror of traffic from multiple minotor ports to a single analysis port.",
"type": "object", "type": "array",
"properties": { "items": {
"monitor-ports": { "type": "object",
"description": "The list of ports that we want to mirror.", "properties": {
"type": "array", "monitor-ports": {
"items": { "description": "The list of ports that we want to mirror.",
"type": "array",
"items": {
"type": "string"
}
},
"analysis-port": {
"description": "The port that mirror'ed packets should be sent to.",
"type": "string" "type": "string"
} }
},
"analysis-port": {
"description": "The port that mirror'ed packets should be sent to.",
"type": "string"
} }
} }
}, },
@@ -549,7 +553,8 @@ static std::string DefaultAPSchema = R"foo(
"5G", "5G",
"5G-lower", "5G-lower",
"5G-upper", "5G-upper",
"6G" "6G",
"HaLow"
] ]
}, },
"bandwidth": { "bandwidth": {
@@ -622,6 +627,10 @@ static std::string DefaultAPSchema = R"foo(
], ],
"default": 80 "default": 80
}, },
"enable": {
"description": "Specifies radio is enabled/disabled.",
"type": "boolean"
},
"require-mode": { "require-mode": {
"description": "Stations that do no fulfill these HT modes will be rejected.", "description": "Stations that do no fulfill these HT modes will be rejected.",
"type": "string", "type": "string",
@@ -2306,7 +2315,8 @@ static std::string DefaultAPSchema = R"foo(
"5G", "5G",
"5G-lower", "5G-lower",
"5G-upper", "5G-upper",
"6G" "6G",
"HaLow"
] ]
} }
}, },
@@ -2410,6 +2420,11 @@ static std::string DefaultAPSchema = R"foo(
"encryption": { "encryption": {
"$ref": "#/$defs/interface.ssid.encryption" "$ref": "#/$defs/interface.ssid.encryption"
}, },
"enhanced-mpsk": {
"description": "Optionally disable MPSK",
"type": "boolean",
"default": true
},
"multi-psk": { "multi-psk": {
"anyOf": [ "anyOf": [
{ {
@@ -3739,7 +3754,8 @@ static std::string DefaultAPSchema = R"foo(
"5G", "5G",
"5G-lower", "5G-lower",
"5G-upper", "5G-upper",
"6G" "6G",
"HaLow"
] ]
} }
}, },
@@ -3949,8 +3965,10 @@ static std::string DefaultAPSchema = R"foo(
"inactive-deauth", "inactive-deauth",
"key-mismatch", "key-mismatch",
"beacon-report", "beacon-report",
"radar-detected" "radar-detected",
] "ft-finish",
"sta-authorized"
]
} }
} }
} }
@@ -4438,7 +4456,8 @@ static std::string DefaultSWITCHSchema = R"foo(
"sae-mixed", "sae-mixed",
"wpa3", "wpa3",
"wpa3-192", "wpa3-192",
"wpa3-mixed" "wpa3-mixed",
"mpsk-radius"
], ],
"examples": [ "examples": [
"psk2" "psk2"
@@ -4652,16 +4671,22 @@ static std::string DefaultSWITCHSchema = R"foo(
"type": "object", "type": "object",
"properties": { "properties": {
"port-mirror": { "port-mirror": {
"type": "object", "description": "Enable mirror of traffic from multiple minotor ports to a single analysis port.",
"properties": { "type": "array",
"monitor-ports": { "items": {
"type": "array", "type": "object",
"items": { "properties": {
"monitor-ports": {
"description": "The list of ports that we want to mirror.",
"type": "array",
"items": {
"type": "string"
}
},
"analysis-port": {
"description": "The port that mirror'ed packets should be sent to.",
"type": "string" "type": "string"
} }
},
"analysis-port": {
"type": "string"
} }
} }
}, },
@@ -4881,7 +4906,8 @@ static std::string DefaultSWITCHSchema = R"foo(
"5G", "5G",
"5G-lower", "5G-lower",
"5G-upper", "5G-upper",
"6G" "6G",
"HaLow"
] ]
}, },
"bandwidth": { "bandwidth": {
@@ -4947,6 +4973,10 @@ static std::string DefaultSWITCHSchema = R"foo(
], ],
"default": 80 "default": 80
}, },
"enable": {
"description": "Specifies radio is enabled/disabled.",
"type": "boolean"
},
"require-mode": { "require-mode": {
"type": "string", "type": "string",
"enum": [ "enum": [
@@ -6519,7 +6549,8 @@ static std::string DefaultSWITCHSchema = R"foo(
"5G", "5G",
"5G-lower", "5G-lower",
"5G-upper", "5G-upper",
"6G" "6G",
"HaLow"
] ]
} }
}, },
@@ -6609,6 +6640,11 @@ static std::string DefaultSWITCHSchema = R"foo(
"encryption": { "encryption": {
"$ref": "#/$defs/interface.ssid.encryption" "$ref": "#/$defs/interface.ssid.encryption"
}, },
"enhanced-mpsk": {
"description": "Optionally disable MPSK",
"type": "boolean",
"default": true
},
"multi-psk": { "multi-psk": {
"anyOf": [ "anyOf": [
{ {
@@ -7742,7 +7778,8 @@ static std::string DefaultSWITCHSchema = R"foo(
"5G", "5G",
"5G-lower", "5G-lower",
"5G-upper", "5G-upper",
"6G" "6G",
"HaLow"
] ]
} }
}, },
@@ -7911,7 +7948,9 @@ static std::string DefaultSWITCHSchema = R"foo(
"inactive-deauth", "inactive-deauth",
"key-mismatch", "key-mismatch",
"beacon-report", "beacon-report",
"radar-detected" "radar-detected",
"ft-finish",
"sta-authorized"
] ]
} }
} }

View File

@@ -845,4 +845,4 @@ namespace OpenWifi {
} }
} }
} // namespace OpenWifi } // namespace OpenWifi

View File

@@ -14,6 +14,7 @@
#include <iostream> #include <iostream>
#include <random> #include <random>
#include <vector> #include <vector>
#include <optional>
// This must be defined for poco_debug and poco_trace macros to function. // This must be defined for poco_debug and poco_trace macros to function.
@@ -40,6 +41,7 @@ namespace OpenWifi {
#include "Poco/Util/OptionSet.h" #include "Poco/Util/OptionSet.h"
#include "Poco/Util/PropertyFileConfiguration.h" #include "Poco/Util/PropertyFileConfiguration.h"
#include "Poco/Util/ServerApplication.h" #include "Poco/Util/ServerApplication.h"
#include "Poco/ThreadPool.h"
#include "framework/OpenWifiTypes.h" #include "framework/OpenWifiTypes.h"

View File

@@ -5,6 +5,7 @@
#pragma once #pragma once
#include <string> #include <string>
#include <optional>
#include "framework/OpenWifiTypes.h" #include "framework/OpenWifiTypes.h"

View File

@@ -35,7 +35,6 @@ namespace OpenWifi {
P.verificationDepth = 9; P.verificationDepth = 9;
P.loadDefaultCAs = root_ca_.empty(); P.loadDefaultCAs = root_ca_.empty();
P.cipherList = "ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH"; P.cipherList = "ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH";
P.dhUse2048Bits = true;
P.caLocation = cas_; P.caLocation = cas_;
// P.securityLevel = // P.securityLevel =
@@ -68,6 +67,16 @@ namespace OpenWifi {
Context->addCertificateAuthority(Issuing); Context->addCertificateAuthority(Issuing);
} }
if (!client_cas_.empty()) {
// add certificates specified in clientcas
std::vector<Poco::Crypto::X509Certificate> Certs =
Poco::Net::X509Certificate::readPEM(client_cas_);
for (const auto &cert : Certs) {
Context->addChainCertificate(cert);
Context->addCertificateAuthority(cert);
}
}
Poco::Crypto::RSAKey Key("", key_file_, key_file_password_); Poco::Crypto::RSAKey Key("", key_file_, key_file_password_);
Context->usePrivateKey(Key); Context->usePrivateKey(Key);
@@ -334,4 +343,4 @@ namespace OpenWifi {
} }
} }
} // namespace OpenWifi } // namespace OpenWifi

View File

@@ -45,6 +45,7 @@ namespace OpenWifi {
[[nodiscard]] inline auto KeyFile() const { return key_file_; }; [[nodiscard]] inline auto KeyFile() const { return key_file_; };
[[nodiscard]] inline auto CertFile() const { return cert_file_; }; [[nodiscard]] inline auto CertFile() const { return cert_file_; };
[[nodiscard]] inline auto RootCA() const { return root_ca_; }; [[nodiscard]] inline auto RootCA() const { return root_ca_; };
[[nodiscard]] inline auto ClientCas() const { return client_cas_; };
[[nodiscard]] inline auto KeyFilePassword() const { return key_file_password_; }; [[nodiscard]] inline auto KeyFilePassword() const { return key_file_password_; };
[[nodiscard]] inline auto IssuerCertFile() const { return issuer_cert_file_; }; [[nodiscard]] inline auto IssuerCertFile() const { return issuer_cert_file_; };
[[nodiscard]] inline auto Name() const { return name_; }; [[nodiscard]] inline auto Name() const { return name_; };

View File

@@ -210,10 +210,16 @@ namespace OpenWifi {
n = Client->second->WS_->receiveFrame(IncomingFrame, flags); n = Client->second->WS_->receiveFrame(IncomingFrame, flags);
auto Op = flags & Poco::Net::WebSocket::FRAME_OP_BITMASK; auto Op = flags & Poco::Net::WebSocket::FRAME_OP_BITMASK;
if (n == -1) {
poco_warning(Logger(),
fmt::format("UI-EMPTY({}): {} Empty Frame flags {}.",
Client->second->Id_, Client->second->UserName_, flags));
return;
}
if (n == 0) { if (n == 0) {
poco_debug(Logger(), poco_debug(Logger(),
fmt::format("CLOSE({}): {} UI Client is closing WS connection.", fmt::format("CLOSE({}): {} UI Client is closing WS connection.",
Client->second->Id_, Client->second->UserName_)); Client->second->Id_, Client->second->UserName_));
return EndConnection(Client); return EndConnection(Client);
} }
@@ -221,7 +227,7 @@ namespace OpenWifi {
case Poco::Net::WebSocket::FRAME_OP_PING: { case Poco::Net::WebSocket::FRAME_OP_PING: {
Client->second->WS_->sendFrame("", 0, Client->second->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);
} break; } break;
case Poco::Net::WebSocket::FRAME_OP_PONG: { case Poco::Net::WebSocket::FRAME_OP_PONG: {
} break; } break;
@@ -231,6 +237,11 @@ namespace OpenWifi {
Client->second->Id_, Client->second->UserName_)); Client->second->Id_, Client->second->UserName_));
return EndConnection(Client); return EndConnection(Client);
} break; } break;
case Poco::Net::WebSocket::FRAME_OP_CONT: {
poco_warning(Logger(),
fmt::format("CONT({}): {} Unexpected CONT Frame - Ignoring.",
Client->second->Id_, Client->second->UserName_));
} break;
case Poco::Net::WebSocket::FRAME_OP_TEXT: { case Poco::Net::WebSocket::FRAME_OP_TEXT: {
constexpr const char *DropMessagesCommand = "drop-notifications"; constexpr const char *DropMessagesCommand = "drop-notifications";
IncomingFrame.append(0); IncomingFrame.append(0);
@@ -319,4 +330,4 @@ namespace OpenWifi {
} }
} }
} // namespace OpenWifi } // namespace OpenWifi

View File

@@ -433,6 +433,10 @@ namespace OpenWifi::RESTAPI::Errors {
static const struct msg InvalidRRMAction { 1192, "Invalid RRM Action." }; static const struct msg InvalidRRMAction { 1192, "Invalid RRM Action." };
static const struct msg InvalidPackageURL { 1193, "Invalid URL, must start with http:// or https://." };
static const struct msg FailedToDownload { 1194, "Failed to download package." };
static const struct msg FailedToDecompress { 1195, "Failed to decompress package data."};
static const struct msg SimulationDoesNotExist { static const struct msg SimulationDoesNotExist {
7000, "Simulation Instance ID does not exist." 7000, "Simulation Instance ID does not exist."
}; };
@@ -550,6 +554,10 @@ namespace OpenWifi::RESTAPI::Protocol {
static const char *DEBUG = "debug"; static const char *DEBUG = "debug";
static const char *SCRIPT = "script"; static const char *SCRIPT = "script";
static const char *TIMEOUT = "timeout"; static const char *TIMEOUT = "timeout";
static const char *PACKAGE = "package";
static const char *PACKAGES = "packages";
static const char *PACKAGEINST = "packageInstall";
static const char *PACKAGEDEL = "packageDelete";
static const char *NEWPASSWORD = "newPassword"; static const char *NEWPASSWORD = "newPassword";
static const char *USERS = "users"; static const char *USERS = "users";
@@ -583,6 +591,7 @@ namespace OpenWifi::RESTAPI::Protocol {
static const char *FIXEDCONFIG = "fixedconfig"; static const char *FIXEDCONFIG = "fixedconfig";
static const char *CABLEDIAGNOSTICS = "cable-diagnostics"; static const char *CABLEDIAGNOSTICS = "cable-diagnostics";
static const char *REENROLL = "reenroll";
} // namespace OpenWifi::RESTAPI::Protocol } // namespace OpenWifi::RESTAPI::Protocol
namespace OpenWifi::uCentralProtocol { namespace OpenWifi::uCentralProtocol {
@@ -611,6 +620,7 @@ namespace OpenWifi::uCentralProtocol {
static const char *CFGPENDING = "cfgpending"; static const char *CFGPENDING = "cfgpending";
static const char *RECOVERY = "recovery"; static const char *RECOVERY = "recovery";
static const char *COMPRESS_64 = "compress_64"; static const char *COMPRESS_64 = "compress_64";
static const char *COMPRESS_SZ = "compress_sz";
static const char *CAPABILITIES = "capabilities"; static const char *CAPABILITIES = "capabilities";
static const char *REQUEST_UUID = "request_uuid"; static const char *REQUEST_UUID = "request_uuid";
static const char *SANITY = "sanity"; static const char *SANITY = "sanity";
@@ -667,6 +677,9 @@ namespace OpenWifi::uCentralProtocol {
static const char *SIGNATURE = "signature"; static const char *SIGNATURE = "signature";
static const char *INFO = "info"; static const char *INFO = "info";
static const char *DATE = "date"; static const char *DATE = "date";
static const char *PACKAGE = "package";
static const char *PACKAGES = "packages";
static const char *CATEGORY = "category";
static const char *SERIALNUMBER = "serialNumber"; static const char *SERIALNUMBER = "serialNumber";
static const char *COMPATIBLE = "compatible"; static const char *COMPATIBLE = "compatible";
@@ -697,7 +710,9 @@ namespace OpenWifi::uCentralProtocol {
static const char *FIXEDCONFIG = "fixedconfig"; static const char *FIXEDCONFIG = "fixedconfig";
static const char *CABLEDIAGNOSTICS = "cable-diagnostics"; static const char *CABLEDIAGNOSTICS = "cable-diagnostics";
static const char *REENROLL = "reenroll";
static const char *OPERATION = "op";
} // namespace OpenWifi::uCentralProtocol } // namespace OpenWifi::uCentralProtocol
namespace OpenWifi::uCentralProtocol::Events { namespace OpenWifi::uCentralProtocol::Events {
@@ -732,7 +747,7 @@ namespace OpenWifi::uCentralProtocol::Events {
ET_EVENT, ET_EVENT,
ET_WIFISCAN, ET_WIFISCAN,
ET_ALARM, ET_ALARM,
ET_REBOOTLOG ET_REBOOTLOG,
}; };
inline EVENT_MSG EventFromString(const std::string &Method) { inline EVENT_MSG EventFromString(const std::string &Method) {
@@ -796,6 +811,8 @@ namespace OpenWifi::APCommands {
powercycle, powercycle,
fixedconfig, fixedconfig,
cablediagnostics, cablediagnostics,
reenroll,
package,
unknown unknown
}; };
@@ -811,7 +828,8 @@ namespace OpenWifi::APCommands {
RESTAPI::Protocol::PING, RESTAPI::Protocol::SCRIPT, RESTAPI::Protocol::PING, RESTAPI::Protocol::SCRIPT,
RESTAPI::Protocol::RRM, RESTAPI::Protocol::CERTUPDATE, RESTAPI::Protocol::RRM, RESTAPI::Protocol::CERTUPDATE,
RESTAPI::Protocol::TRANSFER, RESTAPI::Protocol::POWERCYCLE, RESTAPI::Protocol::TRANSFER, RESTAPI::Protocol::POWERCYCLE,
RESTAPI::Protocol::FIXEDCONFIG, RESTAPI::Protocol::CABLEDIAGNOSTICS RESTAPI::Protocol::FIXEDCONFIG, RESTAPI::Protocol::CABLEDIAGNOSTICS,
RESTAPI::Protocol::REENROLL, RESTAPI::Protocol::PACKAGE
}; };
inline const char *to_string(Commands Cmd) { return uCentralAPCommands[(uint8_t)Cmd]; } inline const char *to_string(Commands Cmd) { return uCentralAPCommands[(uint8_t)Cmd]; }

View File

@@ -590,6 +590,26 @@ namespace OpenWifi::Utils {
return false; return false;
} }
//
// Compress given data using utility function and encode it in base64 format.
//
bool CompressAndEncodeBase64(const std::string& UnCompressedData, std::string& CompressedBase64Data) {
unsigned long CompressedDataSize = UnCompressedData.size();
std::vector<Bytef> CompressedData(CompressedDataSize);
auto status = compress(&CompressedData[0], &CompressedDataSize,
(Bytef*) UnCompressedData.c_str(), UnCompressedData.size());
if (status == Z_OK) {
CompressedBase64Data = OpenWifi::Utils::base64encode(&CompressedData[0], CompressedDataSize);
}
else {
// failed to compress data
return false;
}
return true;
}
bool IsAlphaNumeric(const std::string &s) { bool IsAlphaNumeric(const std::string &s) {
return std::all_of(s.begin(), s.end(), [](char c) -> bool { return isalnum(c); }); return std::all_of(s.begin(), s.end(), [](char c) -> bool { return isalnum(c); });
} }
@@ -868,78 +888,15 @@ namespace OpenWifi::Utils {
return password; return password;
} }
// Function to query NAPTR records for a domain and return them in a vector /*
std::vector<NAPTRRecord> getNAPTRRecords(const std::string& domain) { Note that these 2 functions aren't used. They have been removed due to this deprecation warning:
std::vector<NAPTRRecord> naptrRecords; // Function to query NAPTR records for a domain and return them in a vector
#47 3.825 /owgw/src/framework/utils.cpp: In function 'std::vector<OpenWifi::Utils::NAPTRRecord> OpenWifi::Utils::getNAPTRRecords(const std::string&)':
unsigned char buf[4096]; #47 3.825 /owgw/src/framework/utils.cpp:915:28: warning: 'int ns_sprintrr(const ns_msg*, const ns_rr*, const char*, const char*, char*, size_t)' is deprecated [-Wdeprecated-declarations]
ns_msg handle;
ns_initparse(buf, NS_PACKETSZ, &handle);
// Query NAPTR records for the given domain
int response = res_query(domain.c_str(), ns_c_in, ns_t_naptr, buf, sizeof(buf));
if (response < 0) {
return naptrRecords;
}
if(ns_initparse(buf, response, &handle) < 0) {
return naptrRecords;
}
// Iterate through the DNS response and extract NAPTR records
int count = ns_msg_count(handle, ns_s_an);
for (int i = 0; i < count; ++i) {
ns_rr rr;
if (ns_parserr(&handle, ns_s_an, i, &rr) == 0) {
char rdata[256];
ns_sprintrr(&handle, &rr, nullptr, nullptr, rdata, sizeof(rdata));
NAPTRRecord record;
std::istringstream os(rdata);
os >> record.name >> record.ttl >> record.rclass >> record.rtype >> record.order >> record.preference >> record.flags
>> record.service >> record.regexp >> record.replacement;
naptrRecords.push_back(record);
}
}
return naptrRecords;
}
std::vector<SrvRecord> getSRVRecords(const std::string& domain) { std::vector<SrvRecord> getSRVRecords(const std::string& domain) {
std::vector<SrvRecord> srvRecords; #47 3.833 /owgw/src/framework/utils.cpp: In function 'std::vector<OpenWifi::Utils::SrvRecord> OpenWifi::Utils::getSRVRecords(const std::string&)':
#47 3.833 /owgw/src/framework/utils.cpp:952:28: warning: 'int ns_sprintrr(const ns_msg*, const ns_rr*, const char*, const char*, char*, size_t)' is deprecated [-Wdeprecated-declarations]
// Buffer to hold the DNS response */
unsigned char buf[4096];
ns_msg handle;
ns_initparse(buf, NS_PACKETSZ, &handle);
// Query NAPTR records for the given domain
int response = res_query(domain.c_str(), ns_c_in, ns_t_srv, buf, sizeof(buf));
if (response < 0) {
std::cerr << "DNS query failed for " << domain << ": " << hstrerror(h_errno) << std::endl;
return srvRecords;
}
if(ns_initparse(buf, response, &handle) < 0) {
return srvRecords;
}
// Iterate through the DNS response and extract NAPTR records
int count = ns_msg_count(handle, ns_s_an);
for (int i = 0; i < count; ++i) {
ns_rr rr;
if (ns_parserr(&handle, ns_s_an, i, &rr) == 0) {
char rdata[256];
ns_sprintrr(&handle, &rr, nullptr, nullptr, rdata, sizeof(rdata));
SrvRecord record;
std::istringstream os(rdata);
os >> record.name >> record.ttl >> record.rclass >> record.rtype >> record.pref >> record.weight >>
record.port >> record.srvname ;
srvRecords.push_back(record);
}
}
return srvRecords;
}
} // namespace OpenWifi::Utils } // namespace OpenWifi::Utils

View File

@@ -151,6 +151,8 @@ namespace OpenWifi::Utils {
bool ExtractBase64CompressedData(const std::string &CompressedData, bool ExtractBase64CompressedData(const std::string &CompressedData,
std::string &UnCompressedData, uint64_t compress_sz); std::string &UnCompressedData, uint64_t compress_sz);
bool CompressAndEncodeBase64(const std::string& UnCompressedData, std::string& CompressedData);
inline bool match(const char* first, const char* second) inline bool match(const char* first, const char* second)
{ {
// If we reach at the end of both strings, we are done // If we reach at the end of both strings, we are done
@@ -296,8 +298,10 @@ namespace OpenWifi::Utils {
std::string replacement; std::string replacement;
}; };
// Function to query NAPTR records for a domain and return them in a vector // removed due to deprecation: see utils.cpp
std::vector<NAPTRRecord> getNAPTRRecords(const std::string& domain); // Function to query NAPTR records for a domain and return them in a vector
//std::vector<NAPTRRecord> getNAPTRRecords(const std::string& domain);
struct SrvRecord { struct SrvRecord {
std::string name; std::string name;
std::string ttl; std::string ttl;
@@ -309,7 +313,8 @@ namespace OpenWifi::Utils {
std::string srvname; std::string srvname;
}; };
std::vector<SrvRecord> getSRVRecords(const std::string& domain); // removed due to deprecation: see utils.cpp
// std::vector<SrvRecord> getSRVRecords(const std::string& domain);
struct HostNameServerResult{ struct HostNameServerResult{
std::string Hostname; std::string Hostname;

View File

@@ -14,6 +14,7 @@
#include "nlohmann/json.hpp" #include "nlohmann/json.hpp"
#include "Poco/NObserver.h" #include "Poco/NObserver.h"
#include <Poco/Net/Context.h>
#include "Poco/Net/SocketNotification.h" #include "Poco/Net/SocketNotification.h"
#include "Poco/Net/NetException.h" #include "Poco/Net/NetException.h"
#include "Poco/Net/WebSocketImpl.h" #include "Poco/Net/WebSocketImpl.h"
@@ -71,6 +72,7 @@ namespace OpenWifi {
const auto &RootCas = const auto &RootCas =
MicroServiceConfigPath("ucentral.websocket.host.0.rootca", ""); MicroServiceConfigPath("ucentral.websocket.host.0.rootca", "");
const auto &Cas = MicroServiceConfigPath("ucentral.websocket.host.0.cas", ""); const auto &Cas = MicroServiceConfigPath("ucentral.websocket.host.0.cas", "");
const auto &ClientCasFile = MicroServiceConfigPath("ucentral.websocket.host.0.clientcas", "");
Poco::Net::Context::Params P; Poco::Net::Context::Params P;
@@ -86,6 +88,7 @@ namespace OpenWifi {
Poco::Crypto::X509Certificate Cert(CertFileName); Poco::Crypto::X509Certificate Cert(CertFileName);
Poco::Crypto::X509Certificate Root(RootCaFileName); Poco::Crypto::X509Certificate Root(RootCaFileName);
Poco::Crypto::X509Certificate Issuing(IssuerFileName); Poco::Crypto::X509Certificate Issuing(IssuerFileName);
std::vector<Poco::Crypto::X509Certificate> ClientCasCerts;
Poco::Crypto::RSAKey Key("", KeyFileName, KeyPassword); Poco::Crypto::RSAKey Key("", KeyFileName, KeyPassword);
DeviceSecureContext->useCertificate(Cert); DeviceSecureContext->useCertificate(Cert);
@@ -93,7 +96,11 @@ namespace OpenWifi {
DeviceSecureContext->addCertificateAuthority(Root); DeviceSecureContext->addCertificateAuthority(Root);
DeviceSecureContext->addChainCertificate(Issuing); DeviceSecureContext->addChainCertificate(Issuing);
DeviceSecureContext->addCertificateAuthority(Issuing); DeviceSecureContext->addCertificateAuthority(Issuing);
DeviceSecureContext->addCertificateAuthority(Root); ClientCasCerts = Poco::Net::X509Certificate::readPEM(ClientCasFile);
for (const auto &cert : ClientCasCerts) {
DeviceSecureContext->addChainCertificate(cert);
DeviceSecureContext->addCertificateAuthority(cert);
}
DeviceSecureContext->enableSessionCache(true); DeviceSecureContext->enableSessionCache(true);
DeviceSecureContext->setSessionCacheSize(0); DeviceSecureContext->setSessionCacheSize(0);
DeviceSecureContext->setSessionTimeout(120); DeviceSecureContext->setSessionTimeout(120);
@@ -573,14 +580,16 @@ namespace OpenWifi {
try { try {
Client = Clients_.find(pNf->socket().impl()->sockfd()); Client = Clients_.find(pNf->socket().impl()->sockfd());
if (Client == end(Clients_)) { if (Client == end(Clients_)) {
poco_warning(Logger(), fmt::format("Cannot find client socket: {}", poco_warning(Logger(),
pNf->socket().impl()->sockfd())); fmt::format("Cannot find client socket: {}",
pNf->socket().impl()->sockfd()));
return; return;
} }
Connection = Client->second; Connection = Client->second;
if(Connection->WSSocket_==nullptr || Connection->WSSocket_->impl()==nullptr) { if(Connection->WSSocket_==nullptr || Connection->WSSocket_->impl()==nullptr) {
poco_warning(Logger(), fmt::format("WebSocket is no valid: {}", poco_warning(Logger(),
Connection->SerialNumber_)); fmt::format("WebSocket is not valid: {}",
Connection->SerialNumber_));
return; return;
} }
@@ -589,15 +598,25 @@ namespace OpenWifi {
auto ReceivedBytes = Connection->WSSocket_->receiveFrame(FrameBuffer, sizeof(FrameBuffer), flags); auto ReceivedBytes = Connection->WSSocket_->receiveFrame(FrameBuffer, sizeof(FrameBuffer), flags);
auto Op = flags & Poco::Net::WebSocket::FRAME_OP_BITMASK; auto Op = flags & Poco::Net::WebSocket::FRAME_OP_BITMASK;
if (ReceivedBytes == -1) {
poco_trace(Logger(),
fmt::format("WS-EMPTY{}: Non-blocking try-again empty Frame: flags {}",
Connection->SerialNumber_, flags));
return;
}
switch (Op) { switch (Op) {
case Poco::Net::WebSocket::FRAME_OP_PING: { case Poco::Net::WebSocket::FRAME_OP_PING: {
Connection->WSSocket_->sendFrame("", 0, Connection->WSSocket_->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);
} break; } break;
case Poco::Net::WebSocket::FRAME_OP_PONG: { case Poco::Net::WebSocket::FRAME_OP_PONG: {
} break; } break;
case Poco::Net::WebSocket::FRAME_OP_TEXT: { case Poco::Net::WebSocket::FRAME_OP_TEXT: {
if (ReceivedBytes == 0) { if (ReceivedBytes == 0) {
EndConnection(Connection,__func__,__LINE__); EndConnection(Connection,__func__,__LINE__);
@@ -624,19 +643,29 @@ namespace OpenWifi {
} }
} }
} break; } break;
case Poco::Net::WebSocket::FRAME_OP_BINARY: { case Poco::Net::WebSocket::FRAME_OP_BINARY: {
if (ReceivedBytes == 0) { if (ReceivedBytes == 0) {
EndConnection(Connection,__func__,__LINE__); EndConnection(Connection,__func__,__LINE__);
return; return;
} else { } else {
poco_trace(Logger(), poco_trace(Logger(),
fmt::format("Sending {} key strokes to device.", ReceivedBytes)); fmt::format("Sending {} key strokes to device.", ReceivedBytes));
if (!RTTYS_server().KeyStrokes(Connection, FrameBuffer, ReceivedBytes)) { if (!RTTYS_server().KeyStrokes(Connection, FrameBuffer, ReceivedBytes)) {
EndConnection(Connection,__func__,__LINE__); EndConnection(Connection,__func__,__LINE__);
return; return;
} }
} }
} break; } break;
case Poco::Net::WebSocket::FRAME_OP_CONT: {
// may have to handle this, but not sure whether it's a continuation for text or
// binary, seems to be a hole in the protocol.
poco_warning(Logger(),
fmt::format("CONT Frame {} received, ignoring for now.",
ReceivedBytes));
}
case Poco::Net::WebSocket::FRAME_OP_CLOSE: { case Poco::Net::WebSocket::FRAME_OP_CLOSE: {
EndConnection(Connection,__func__,__LINE__); EndConnection(Connection,__func__,__LINE__);
return; return;
@@ -682,8 +711,8 @@ namespace OpenWifi {
if (Connection->WSSocket_ != nullptr && Connection->WSSocket_->impl()!= nullptr) { if (Connection->WSSocket_ != nullptr && Connection->WSSocket_->impl()!= nullptr) {
try { try {
Connection->WSSocket_->sendFrame(Buf, len, Connection->WSSocket_->sendFrame(Buf, len,
Poco::Net::WebSocket::FRAME_FLAG_FIN | (int) Poco::Net::WebSocket::FRAME_FLAG_FIN |
Poco::Net::WebSocket::FRAME_OP_BINARY); (int) Poco::Net::WebSocket::FRAME_OP_BINARY);
return; return;
} catch (...) { } catch (...) {
poco_error(Logger(), "SendData shutdown."); poco_error(Logger(), "SendData shutdown.");
@@ -985,8 +1014,9 @@ namespace OpenWifi {
} }
bool RTTYS_server::SendToClient(Poco::Net::WebSocket &WebSocket, const u_char *Buf, int len) { bool RTTYS_server::SendToClient(Poco::Net::WebSocket &WebSocket, const u_char *Buf, int len) {
WebSocket.sendFrame( WebSocket.sendFrame(Buf, len,
Buf, len, Poco::Net::WebSocket::FRAME_FLAG_FIN | Poco::Net::WebSocket::FRAME_OP_BINARY); (int) Poco::Net::WebSocket::FRAME_FLAG_FIN |
(int) Poco::Net::WebSocket::FRAME_OP_BINARY);
return true; return true;
} }
@@ -1117,4 +1147,4 @@ namespace OpenWifi {
RTTYS_EndPoint::~RTTYS_EndPoint() { RTTYS_EndPoint::~RTTYS_EndPoint() {
} }
} // namespace OpenWifi } // namespace OpenWifi

View File

@@ -644,8 +644,6 @@ namespace OpenWifi {
uint64_t Size = FileContent.str().size(); uint64_t Size = FileContent.str().size();
Poco::Data::Session Sess = Pool_->get(); Poco::Data::Session Sess = Pool_->get();
Sess.begin();
Poco::Data::Statement Statement(Sess);
if (Size < FileUploader()->MaxSize()) { if (Size < FileUploader()->MaxSize()) {
@@ -666,11 +664,14 @@ namespace OpenWifi {
Insert.execute(); Insert.execute();
Sess.commit(); Sess.commit();
} else { } else {
poco_warning(Logger(), fmt::format("File {} is too large.", UUID)); poco_warning(Logger(),
fmt::format("File {} is too large ({} >= {} max bytes).",
UUID, Size, FileUploader()->MaxSize()));
} }
Sess.commit();
// update CommandList here to ensure that file us uploaded // update CommandList here to ensure that file us uploaded
Sess.begin();
Poco::Data::Statement Statement(Sess);
std::string StatementStr; std::string StatementStr;
StatementStr = StatementStr =
"UPDATE CommandList SET WaitingForFile=?, AttachDate=?, AttachSize=? WHERE UUID=?"; "UPDATE CommandList SET WaitingForFile=?, AttachDate=?, AttachSize=? WHERE UUID=?";
@@ -825,4 +826,4 @@ namespace OpenWifi {
return false; return false;
} }
} // namespace OpenWifi } // namespace OpenWifi

View File

@@ -202,15 +202,14 @@ namespace OpenWifi {
std::string st; std::string st;
std::string whereClause = ""; std::string whereClause = "";
if(!platform.empty()) { if (!platform.empty()) {
if (includeProvisioned == false) { if (includeProvisioned == false) {
//whereClause = fmt::format("WHERE entity='' and venue='' and DeviceType='" + platform + "'");
whereClause = fmt::format("WHERE entity='' and venue='' and DeviceType='" + platform + "'"); whereClause = fmt::format("WHERE entity='' and venue='' and DeviceType='{}'", platform);
} else { } else {
whereClause = fmt::format("WHERE DeviceType='" + platform + "'"); //whereClause = fmt::format("WHERE DeviceType='" + platform + "'");
whereClause = fmt::format("WHERE DeviceType='{}'", platform);
} }
//st = "SELECT SerialNumber From Devices WHERE DeviceType='" + platform + "' "; //st = "SELECT SerialNumber From Devices WHERE DeviceType='" + platform + "' ";
} else { } else {
if (includeProvisioned == false) { if (includeProvisioned == false) {
@@ -218,7 +217,7 @@ namespace OpenWifi {
} }
//st = "SELECT SerialNumber From Devices "; //st = "SELECT SerialNumber From Devices ";
} }
st = fmt::format("SELECT SerialNumber From Devices {}", whereClause); st = fmt::format("SELECT SerialNumber From Devices {}", whereClause);
if (orderBy.empty()) if (orderBy.empty())
@@ -896,9 +895,9 @@ namespace OpenWifi {
if (includeProvisioned == false) { if (includeProvisioned == false) {
whereClause = fmt::format("WHERE DeviceType='{}' and entity='' and venue=''",platform); whereClause = fmt::format("WHERE DeviceType='{}' and entity='' and venue=''",platform);
} else { } else {
whereClause = fmt::format("WHERE DeviceType='{}'", platform); whereClause = fmt::format("WHERE DeviceType='{}'", platform);
} }
} }
st = st =
@@ -907,7 +906,7 @@ namespace OpenWifi {
ComputeRange(From, HowMany)); ComputeRange(From, HowMany));
//Logger().information(fmt::format(" GetDevices st is {} ", st)); //Logger().information(fmt::format(" GetDevices st is {} ", st));
Select << ConvertParams(st), Poco::Data::Keywords::into(Records); Select << ConvertParams(st), Poco::Data::Keywords::into(Records);
Select.execute(); Select.execute();

View File

@@ -49,8 +49,7 @@ namespace OpenWifi {
"Data TEXT, " "Data TEXT, "
"Recorded BIGINT, " "Recorded BIGINT, "
"INDEX StatSerial0 (SerialNumber)), ", "INDEX StatSerial0 (SerialNumber)), ",
"INDEX StatSerial (SerialNumber ASC, Recorded ASC))", "INDEX StatSerial (SerialNumber ASC, Recorded ASC))", Poco::Data::Keywords::now;
Poco::Data::Keywords::now;
} }
return 0; return 0;
} catch (const Poco::Exception &E) { } catch (const Poco::Exception &E) {
@@ -154,8 +153,7 @@ namespace OpenWifi {
"alter table devices add column lastRecordedContact bigint", "alter table devices add column lastRecordedContact bigint",
"alter table devices add column simulated boolean", "alter table devices add column simulated boolean",
"alter table devices add column certificateExpiryDate bigint", "alter table devices add column certificateExpiryDate bigint",
"alter table devices add column connectReason TEXT" "alter table devices add column connectReason TEXT"};
};
for (const auto &i : Script) { for (const auto &i : Script) {
try { try {
@@ -279,9 +277,7 @@ namespace OpenWifi {
Poco::Data::Keywords::now; Poco::Data::Keywords::now;
} }
std::vector<std::string> Script{ std::vector<std::string> Script{"alter table DefaultConfigs add column Platform text"};
"alter table DefaultConfigs add column Platform text"
};
for (const auto &i : Script) { for (const auto &i : Script) {
try { try {