mirror of
https://github.com/Telecominfraproject/wlan-cloud-ucentralgw.git
synced 2025-11-01 11:17:52 +00:00
Compare commits
137 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d67e0c573e | ||
|
|
75d89d263d | ||
|
|
30a9eb1f68 | ||
|
|
5b5d609d6b | ||
|
|
d7c79f4eaf | ||
|
|
e97e13d1b1 | ||
|
|
9d7f4da504 | ||
|
|
a3b6e7c315 | ||
|
|
451680cd5a | ||
|
|
7be48c3cfc | ||
|
|
dcfb9b0b03 | ||
|
|
5a378a2332 | ||
|
|
6d9315a0a8 | ||
|
|
660dada3d7 | ||
|
|
20cbf1837a | ||
|
|
483edf9cda | ||
|
|
3fb78edb01 | ||
|
|
0920d4ace2 | ||
|
|
d66325fc35 | ||
|
|
4f7e39b33c | ||
|
|
7fd0655d22 | ||
|
|
5b02f509b6 | ||
|
|
537ed0c05b | ||
|
|
765210bb1d | ||
|
|
0bf2cc3d8b | ||
|
|
e359711ee3 | ||
|
|
b03f1a0ea6 | ||
|
|
4049e43079 | ||
|
|
b59d1cb4da | ||
|
|
c3a709c2b9 | ||
|
|
5d89107827 | ||
|
|
3c15c6dc4f | ||
|
|
7b33a692b2 | ||
|
|
b118dcbcec | ||
|
|
02a0eef44a | ||
|
|
c7ed7fb264 | ||
|
|
1d88bb50d9 | ||
|
|
3b613ea159 | ||
|
|
d00d409fca | ||
|
|
8382818e2d | ||
|
|
ed4670d239 | ||
|
|
cca3619e91 | ||
|
|
9a834c29a2 | ||
|
|
2b06a0bcf6 | ||
|
|
03dabed878 | ||
|
|
e133a9c3ab | ||
|
|
23b33fab20 | ||
|
|
909b4c889e | ||
|
|
a04c5336d2 | ||
|
|
4df1bf985d | ||
|
|
26a89f3eb5 | ||
|
|
b055711993 | ||
|
|
fcdb7423ef | ||
|
|
f286d5fb48 | ||
|
|
0d70601c64 | ||
|
|
a493defc99 | ||
|
|
fb3e1288ae | ||
|
|
ce52e05104 | ||
|
|
920b922121 | ||
|
|
3732cfd07e | ||
|
|
9e772b8c91 | ||
|
|
92252d09dc | ||
|
|
28636c3e1e | ||
|
|
8e44f1e85c | ||
|
|
b77d40fbf8 | ||
|
|
574172b8bf | ||
|
|
794b31591d | ||
|
|
66aee07105 | ||
|
|
86685f17d6 | ||
|
|
08f683c15a | ||
|
|
7fea477f55 | ||
|
|
f22b3e3995 | ||
|
|
3a1011a662 | ||
|
|
6595b37ae4 | ||
|
|
05b6a9474b | ||
|
|
1de94be447 | ||
|
|
aa8486c71b | ||
|
|
e75d3cfdbb | ||
|
|
1a0a6d4a70 | ||
|
|
071922c555 | ||
|
|
4e4b69e672 | ||
|
|
3d8f7c1162 | ||
|
|
2bf60dbb3f | ||
|
|
44bc27e9d4 | ||
|
|
f328a72b85 | ||
|
|
4cbceb9366 | ||
|
|
921267c00a | ||
|
|
d63cbce602 | ||
|
|
094bba4747 | ||
|
|
5bee5b1372 | ||
|
|
45357ad567 | ||
|
|
8e984a8f0e | ||
|
|
4e7babc25f | ||
|
|
1acabd4986 | ||
|
|
d839646dd8 | ||
|
|
31b52f9bd2 | ||
|
|
97bc19b949 | ||
|
|
c252e6c5c7 | ||
|
|
cef012c333 | ||
|
|
6513980525 | ||
|
|
adc055f3e8 | ||
|
|
6d991e5a48 | ||
|
|
ec5031ca83 | ||
|
|
19e4e92d92 | ||
|
|
37feb6a44c | ||
|
|
2aaab1207b | ||
|
|
7896b071da | ||
|
|
e073576692 | ||
|
|
65ad9ff96e | ||
|
|
08e7900889 | ||
|
|
8554481186 | ||
|
|
2b246fe1ee | ||
|
|
bd37534223 | ||
|
|
aa862d3fcf | ||
|
|
c6c6eaa4a5 | ||
|
|
ffe86a3994 | ||
|
|
52123f7dcc | ||
|
|
e430c522ba | ||
|
|
93c236aa79 | ||
|
|
c802e35c12 | ||
|
|
a59d49e096 | ||
|
|
5756d59519 | ||
|
|
35aa6fb99d | ||
|
|
fa6d0aa714 | ||
|
|
91147f3fbb | ||
|
|
15f3eaa02e | ||
|
|
6305e92399 | ||
|
|
3714fd5f05 | ||
|
|
19497b88ce | ||
|
|
6a35dc93bf | ||
|
|
8004aa6676 | ||
|
|
2c654d3471 | ||
|
|
df67141a98 | ||
|
|
071330d7f8 | ||
|
|
90f23dca73 | ||
|
|
500688edb7 | ||
|
|
222b98d019 |
171
.github/workflows/ci.yml
vendored
171
.github/workflows/ci.yml
vendored
@@ -1,19 +1,19 @@
|
||||
name: CI
|
||||
name: Build Docker image
|
||||
|
||||
on:
|
||||
push:
|
||||
paths-ignore:
|
||||
- 'openapi/**'
|
||||
- '**.md'
|
||||
- 'version'
|
||||
- 'package*.json'
|
||||
- 'helm/*.yaml'
|
||||
- 'CMakeLists.txt'
|
||||
branches:
|
||||
- master
|
||||
- 'release/*'
|
||||
tags:
|
||||
- 'v*'
|
||||
- kinara
|
||||
pull_request:
|
||||
branches:
|
||||
- master
|
||||
- 'release/*'
|
||||
- kinara
|
||||
|
||||
defaults:
|
||||
run:
|
||||
@@ -21,81 +21,102 @@ defaults:
|
||||
|
||||
jobs:
|
||||
docker:
|
||||
runs-on: ubuntu-20.04
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
DOCKER_REGISTRY_URL: tip-tip-wlan-cloud-ucentral.jfrog.io
|
||||
DOCKER_REGISTRY_USERNAME: ucentral
|
||||
ECR_REGISTRY: 471112855615.dkr.ecr.us-east-1.amazonaws.com
|
||||
ECR_REPOSITORY: owgw
|
||||
AWS_REGION: us-east-1
|
||||
|
||||
steps:
|
||||
- name: Checkout actions repo
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
repository: Telecominfraproject/.github
|
||||
path: github
|
||||
- name: Checkout source
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
path: build
|
||||
token: ${{ secrets.GIT_PUSH_PAT }}
|
||||
persist-credentials: true
|
||||
|
||||
- name: Build and push Docker image
|
||||
uses: ./github/composite-actions/docker-image-build
|
||||
with:
|
||||
image_name: owgw
|
||||
registry: tip-tip-wlan-cloud-ucentral.jfrog.io
|
||||
registry_user: ucentral
|
||||
registry_password: ${{ secrets.DOCKER_REGISTRY_PASSWORD }}
|
||||
- name: Checkout dot github repo
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
repository: kinarasystems/.github
|
||||
ref: main
|
||||
path: tools
|
||||
token: ${{ secrets.GIT_PUSH_PAT }}
|
||||
|
||||
- name: Notify on failure via Slack
|
||||
if: failure() && github.ref == 'refs/heads/master'
|
||||
uses: rtCamp/action-slack-notify@v2
|
||||
env:
|
||||
SLACK_USERNAME: GitHub Actions failure notifier
|
||||
SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK }}
|
||||
SLACK_COLOR: "${{ job.status }}"
|
||||
SLACK_ICON: https://raw.githubusercontent.com/quintessence/slack-icons/master/images/github-logo-slack-icon.png
|
||||
SLACK_TITLE: Docker build failed for OWGW service
|
||||
- name: Bump version and checkin
|
||||
if: github.ref == 'refs/heads/kinara'
|
||||
id: bump-version
|
||||
run: |
|
||||
cd build
|
||||
../tools/utils/setup-git-credentials "${{ secrets.GIT_PUSH_PAT}}"
|
||||
../tools/utils/ver-bump -b -a -p -V kv -y helm/Chart.yaml -Y helm/values.yaml -M CMakeLists.txt
|
||||
|
||||
trigger-testing:
|
||||
if: startsWith(github.ref, 'refs/pull/')
|
||||
- name: Configure AWS credentials
|
||||
uses: aws-actions/configure-aws-credentials@v4
|
||||
with:
|
||||
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
||||
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
||||
aws-region: ${{ env.AWS_REGION }}
|
||||
|
||||
- name: Login to Amazon ECR
|
||||
id: login-ecr
|
||||
uses: aws-actions/amazon-ecr-login@v2
|
||||
|
||||
- name: Build, tag, and push image to Amazon ECR
|
||||
id: build-image
|
||||
env:
|
||||
ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
|
||||
IMAGE_TAG: ${{ github.sha }}
|
||||
GITHUB_REF: ${{ github.ref }}
|
||||
run: |
|
||||
cd build
|
||||
version=$(cat version)
|
||||
../tools/utils/docker_build \
|
||||
-m kinara \
|
||||
-b "$GITHUB_REF" \
|
||||
-t "$IMAGE_TAG" \
|
||||
-r "$ECR_REGISTRY/$ECR_REPOSITORY" \
|
||||
-v "kv${version}"
|
||||
|
||||
- name: Notify via Teams
|
||||
#if: failure() && github.ref == 'refs/heads/kinara'
|
||||
if: always()
|
||||
uses: skitionek/notify-microsoft-teams@master
|
||||
with:
|
||||
webhook_url: ${{ secrets.MS_TEAMS_WEBHOOK }}
|
||||
needs: ${{ toJson(needs) }}
|
||||
job: ${{ toJson(job) }}
|
||||
steps: ${{ toJson(steps) }}
|
||||
dry_run: False
|
||||
|
||||
deploy-to-dev:
|
||||
runs-on: ubuntu-latest
|
||||
needs: docker
|
||||
steps:
|
||||
- name: Get base branch name and set as output
|
||||
id: get_base_branch
|
||||
run: |
|
||||
echo "branch=$(echo ${GITHUB_BASE_REF##*/} | sed 's/master/main/g')" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Checkout actions repo
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
repository: Telecominfraproject/.github
|
||||
path: github
|
||||
|
||||
- name: Trigger testing of OpenWifi Docker Compose deployment and wait for result
|
||||
uses: ./github/composite-actions/trigger-workflow-and-wait
|
||||
env:
|
||||
BASE_BRANCH: ${{ steps.get_base_branch.outputs.branch }}
|
||||
with:
|
||||
owner: Telecominfraproject
|
||||
repo: wlan-testing
|
||||
workflow: ow_docker-compose.yml
|
||||
token: ${{ secrets.WLAN_TESTING_PAT }}
|
||||
ref: master
|
||||
inputs: '{"deployment_version": "${{ env.BASE_BRANCH }}", "owgw_version": "${{ github.sha }}", "owsec_version": "${{ env.BASE_BRANCH }}", "owfms_version": "${{ env.BASE_BRANCH }}", "owprov_version": "${{ env.BASE_BRANCH }}", "owanalytics_version": "${{ env.BASE_BRANCH }}", "owsub_version": "${{ env.BASE_BRANCH }}", "microservice": "owgw"}'
|
||||
|
||||
trigger-deploy-to-dev:
|
||||
runs-on: ubuntu-latest
|
||||
if: github.ref == 'refs/heads/master'
|
||||
if: github.ref == 'refs/heads/kinara'
|
||||
env:
|
||||
DEPLOY_NAME: owgw
|
||||
AWS_DEFAULT_REGION: us-east-1
|
||||
AWS_NAMESPACE: kic-dev1
|
||||
AWS_EKS_NAME: kinara-dev
|
||||
KUBECTL_VERSION: "v1.27.14"
|
||||
needs:
|
||||
- docker
|
||||
steps:
|
||||
- name: Checkout actions repo
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
repository: Telecominfraproject/.github
|
||||
path: github
|
||||
- name: Configure AWS credentials
|
||||
uses: aws-actions/configure-aws-credentials@v4
|
||||
with:
|
||||
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
||||
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
||||
aws-region: ${{ env.AWS_DEFAULT_REGION }}
|
||||
|
||||
- name: Trigger deployment of the latest version to dev instance and wait for result
|
||||
uses: ./github/composite-actions/trigger-workflow-and-wait
|
||||
with:
|
||||
owner: Telecominfraproject
|
||||
repo: wlan-testing
|
||||
workflow: ucentralgw-dev-deployment.yaml
|
||||
token: ${{ secrets.WLAN_TESTING_PAT }}
|
||||
ref: master
|
||||
inputs: '{"force_latest": "true"}'
|
||||
- name: Fetch kubeconfig
|
||||
run: |
|
||||
aws eks update-kubeconfig --name ${{ env.AWS_EKS_NAME }} --region ${{ env.AWS_DEFAULT_REGION }}
|
||||
|
||||
- name: Install kubectl
|
||||
run: |
|
||||
curl -s -LO "https://dl.k8s.io/release/${{ env.KUBECTL_VERSION }}/bin/linux/amd64/kubectl"
|
||||
sudo install -o root -g root -m 0755 kubectl /usr/local/bin/kubectl
|
||||
|
||||
- name: Rolling update of deployment
|
||||
run: |
|
||||
kubectl rollout restart deployment/${{ env.DEPLOY_NAME }} -n ${{ env.AWS_NAMESPACE }}
|
||||
|
||||
26
.github/workflows/cleanup.yml
vendored
26
.github/workflows/cleanup.yml
vendored
@@ -1,26 +0,0 @@
|
||||
name: Clean up PR Docker images
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
branches:
|
||||
- master
|
||||
types: [ closed ]
|
||||
|
||||
defaults:
|
||||
run:
|
||||
shell: bash
|
||||
|
||||
jobs:
|
||||
cleanup:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Cleanup Docker image with PR branch tag
|
||||
run: |
|
||||
export PR_BRANCH_TAG=$(echo ${GITHUB_HEAD_REF#refs/heads/} | tr '/' '-')
|
||||
|
||||
if [[ ! $PR_BRANCH_TAG =~ (main|master|release-*) ]]; then
|
||||
echo "PR branch is $PR_BRANCH_TAG, deleting Docker image"
|
||||
curl -s -uucentral:${{ secrets.DOCKER_REGISTRY_PASSWORD }} -X DELETE "https://tip.jfrog.io/artifactory/tip-wlan-cloud-ucentral/owgw/$PR_BRANCH_TAG"
|
||||
else
|
||||
echo "PR branch is $PR_BRANCH_TAG, not deleting Docker image"
|
||||
fi
|
||||
24
.github/workflows/enforce-jira-issue-key.yml
vendored
24
.github/workflows/enforce-jira-issue-key.yml
vendored
@@ -1,24 +0,0 @@
|
||||
name: Ensure Jira issue is linked
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types: [opened, edited, reopened, synchronize]
|
||||
branches:
|
||||
- 'release/*'
|
||||
|
||||
jobs:
|
||||
check_for_issue_key:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout actions repo
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
repository: Telecominfraproject/.github
|
||||
path: github
|
||||
|
||||
- name: Run JIRA check
|
||||
uses: ./github/composite-actions/enforce-jira-issue-key
|
||||
with:
|
||||
jira_base_url: ${{ secrets.TIP_JIRA_URL }}
|
||||
jira_user_email: ${{ secrets.TIP_JIRA_USER_EMAIL }}
|
||||
jira_api_token: ${{ secrets.TIP_JIRA_API_TOKEN }}
|
||||
41
.github/workflows/openapi-pages.yml
vendored
41
.github/workflows/openapi-pages.yml
vendored
@@ -1,41 +0,0 @@
|
||||
name: Update OpenAPI docs on GitHub Pages
|
||||
|
||||
on:
|
||||
push:
|
||||
paths:
|
||||
- 'openapi/**'
|
||||
branches:
|
||||
- master
|
||||
workflow_dispatch:
|
||||
|
||||
defaults:
|
||||
run:
|
||||
shell: bash
|
||||
|
||||
jobs:
|
||||
docsgen:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Generate static HTML page with docs from OpenAPI definition
|
||||
run: |
|
||||
docker run --rm -v "${PWD}:/local" openapitools/openapi-generator-cli:v6.2.1 generate -i https://raw.githubusercontent.com/Telecominfraproject/wlan-cloud-ucentralgw/master/openapi/owgw.yaml -g html2 --skip-validate-spec -o /local/
|
||||
|
||||
- name: Update OpenAPI docs
|
||||
run: |
|
||||
mkdir tmp-docs
|
||||
mv index.html tmp-docs/index.html
|
||||
mkdir -p ~/.ssh
|
||||
ssh-keyscan -H github.com >> ~/.ssh/known_hosts
|
||||
echo https://tip-automation:${{ secrets.GIT_PUSH_PAT }}@github.com > ~/.git-credentials
|
||||
git config --global credential.helper store
|
||||
git config --global user.email "tip-automation@telecominfraproject.com"
|
||||
git config --global user.name "TIP Automation User"
|
||||
git pull
|
||||
git checkout gh-pages || git checkout -b gh-pages
|
||||
rm -rf docs
|
||||
mv tmp-docs docs
|
||||
git add docs
|
||||
git commit -m'Update OpenAPI docs for GitHub pages'
|
||||
git push --set-upstream origin gh-pages
|
||||
46
.github/workflows/release.yml
vendored
46
.github/workflows/release.yml
vendored
@@ -1,46 +0,0 @@
|
||||
name: Release chart package
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- 'v*'
|
||||
|
||||
defaults:
|
||||
run:
|
||||
shell: bash
|
||||
|
||||
jobs:
|
||||
helm-package:
|
||||
runs-on: ubuntu-20.04
|
||||
env:
|
||||
HELM_REPO_URL: https://tip.jfrog.io/artifactory/tip-wlan-cloud-ucentral-helm/
|
||||
HELM_REPO_USERNAME: ucentral
|
||||
steps:
|
||||
- name: Checkout uCentral assembly chart repo
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
path: wlan-cloud-ucentralgw
|
||||
|
||||
- name: Build package
|
||||
working-directory: wlan-cloud-ucentralgw/helm
|
||||
run: |
|
||||
helm plugin install https://github.com/aslafy-z/helm-git --version 0.10.0
|
||||
helm repo add bitnami https://charts.bitnami.com/bitnami
|
||||
helm repo update
|
||||
helm dependency update
|
||||
mkdir dist
|
||||
helm package . -d dist
|
||||
|
||||
- name: Generate GitHub release body
|
||||
working-directory: wlan-cloud-ucentralgw/helm
|
||||
run: |
|
||||
pip3 install yq -q
|
||||
echo "Docker image - tip-tip-wlan-cloud-ucentral.jfrog.io/owgw:$GITHUB_REF_NAME" > release.txt
|
||||
echo "Helm charted may be attached to this release" >> release.txt
|
||||
echo "Deployment artifacts may be found in https://github.com/Telecominfraproject/wlan-cloud-ucentral-deploy/tree/$GITHUB_REF_NAME" >> release.txt
|
||||
|
||||
- name: Create GitHub release
|
||||
uses: softprops/action-gh-release@v1
|
||||
with:
|
||||
body_path: wlan-cloud-ucentralgw/helm/release.txt
|
||||
files: wlan-cloud-ucentralgw/helm/dist/*
|
||||
3
.gitignore
vendored
3
.gitignore
vendored
@@ -21,10 +21,11 @@ _deps
|
||||
/docker-compose/.env
|
||||
/docker-compose/.env_*
|
||||
/cmake-build/
|
||||
/uploads/
|
||||
test_scripts/curl/token.json
|
||||
.vscode/c_cpp_properties.json
|
||||
test_scripts/curl/result.json
|
||||
*.swp
|
||||
helm/charts/*
|
||||
!helm/charts/.gitkeep
|
||||
/portal-test/
|
||||
/src/ow_version.h
|
||||
|
||||
2
.idea/.gitignore
generated
vendored
2
.idea/.gitignore
generated
vendored
@@ -6,3 +6,5 @@
|
||||
/dataSources.local.xml
|
||||
# Editor-based HTTP Client requests
|
||||
/httpRequests/
|
||||
# GitHub Copilot persisted chat sessions
|
||||
/copilot/chatSessions
|
||||
|
||||
3
.idea/misc.xml
generated
3
.idea/misc.xml
generated
@@ -1,5 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="Black">
|
||||
<option name="sdkName" value="Python 3.9 (wlan-cloud-ucentralgw)" />
|
||||
</component>
|
||||
<component name="CMakeWorkspace" PROJECT_DIR="$PROJECT_DIR$" />
|
||||
<component name="CidrRootsConfiguration">
|
||||
<excludeRoots>
|
||||
|
||||
62
BUILDING.md
62
BUILDING.md
@@ -1,5 +1,5 @@
|
||||
# Building from source
|
||||
In order to build the OWGW, you will need to install its dependencies, which includes the following:
|
||||
In order to build OWGW, you will need to install its dependencies, which includes the following:
|
||||
- cmake
|
||||
- boost
|
||||
- POCO 1.10.1 or later
|
||||
@@ -12,43 +12,43 @@ In order to build the OWGW, you will need to install its dependencies, which inc
|
||||
|
||||
The build is done in 2 parts. The first part is to build a local copy of the framework tailored to your environment. This
|
||||
framework is called [Poco](https://github.com/pocoproject/poco). The version used in this project has a couple of fixes
|
||||
from the master copy needed for cmake. Please use the version of this [Poco fix](https://github.com/AriliaWireless/poco). Building
|
||||
from the master copy needed for cmake. Please use the version of this [Poco fix](https://github.com/Telecominfraproject/wlan-cloud-lib-poco). Building
|
||||
Poco may take several minutes depending on the platform you are building on.
|
||||
|
||||
## Ubuntu
|
||||
These instructions have proven to work on Ubuntu 20.4.
|
||||
```bash
|
||||
sudo apt install git cmake g++ libssl-dev libmariadb-dev
|
||||
sudo apt install libpq-dev libaprutil1-dev apache2-dev libboost-all-dev
|
||||
sudo apt install librdkafka-dev // default-libmysqlclient-dev
|
||||
sudo apt install nlohmann-json-dev
|
||||
sudo apt install git cmake g++ libssl-dev libmariadb-dev \
|
||||
libpq-dev libaprutil1-dev apache2-dev libboost-all-dev \
|
||||
librdkafka-dev // default-libmysqlclient-dev \
|
||||
nlohmann-json-dev
|
||||
|
||||
cd ~
|
||||
git clone https://github.com/AriliaWireless/poco --branch poco-tip-v2
|
||||
git clone https://github.com/Telecominfraproject/wlan-cloud-lib-poco --branch poco-tip-v1 poco
|
||||
cd poco
|
||||
mkdir cmake-build
|
||||
cd cmake-build
|
||||
cmake ..
|
||||
cmake --build . --config Release
|
||||
sudo cmake --build . --target install
|
||||
cd ../..
|
||||
|
||||
cd ~
|
||||
git clone https://github.com/AriliaWireless/cppkafka --branch tip-v1
|
||||
git clone https://github.com/Telecominfraproject/wlan-cloud-lib-cppkafka --branch tip-v1 cppkafka
|
||||
cd cppkafka
|
||||
mkdir cmake-build
|
||||
cd cmake-build
|
||||
cmake ..
|
||||
cmake --build . --config Release
|
||||
sudo cmake --build . --target install
|
||||
cd ../..
|
||||
|
||||
cd ~
|
||||
git clone https://github.com/AriliaWireless/valijson --branch tip-v1
|
||||
git clone https://github.com/Telecominfraproject/wlan-cloud-lib-valijson --branch tip-v1 valijson
|
||||
cd valijson
|
||||
mkdir cmake-build
|
||||
cd cmake-build
|
||||
cmake ..
|
||||
cmake --build . --config Release
|
||||
sudo cmake --build . --target install
|
||||
cd ../..
|
||||
|
||||
git clone https://github.com/fmtlib/fmt --branch 9.0.0 /fmtlib
|
||||
cd fmtlib
|
||||
@@ -57,56 +57,59 @@ cd cmake-build
|
||||
cmake ..
|
||||
make
|
||||
make install
|
||||
cd ../..
|
||||
|
||||
cd ~
|
||||
git clone https://github.com/Telecominfraproject/wlan-cloud-ucentralgw
|
||||
cd wlan-cloud-ucentralgw
|
||||
mkdir cmake-build
|
||||
cd cmake-build
|
||||
cmake ..
|
||||
make -j 8
|
||||
cd ../..
|
||||
```
|
||||
|
||||
## Fedora
|
||||
The following instructions have proven to work on Fedora 33
|
||||
```bash
|
||||
sudo yum install cmake g++ openssl-devel mysql-devel mysql apr-util-devel boost boost-devel
|
||||
sudo yum install yaml-cpp-devel lua-devel
|
||||
sudo yum install cmake g++ openssl-devel mysql-devel mysql apr-util-devel boost boost-devel \
|
||||
yaml-cpp-devel lua-devel
|
||||
sudo dnf install postgresql.x86_64 librdkafka-devel
|
||||
sudo dnf install postgresql-devel json-devel
|
||||
|
||||
git clone https://github.com/AriliaWireless/poco --branch poco-tip-v2
|
||||
git clone https://github.com/Telecominfraproject/wlan-cloud-lib-poco --branch poco-tip-v1 poco
|
||||
cd poco
|
||||
mkdir cmake-build
|
||||
cd cmake-build
|
||||
cmake ..
|
||||
cmake --build . --config Release
|
||||
sudo cmake --build . --target install
|
||||
cd ../..
|
||||
|
||||
git clone https://github.com/AriliaWireless/cppkafka --branch tip-v1
|
||||
git clone https://github.com/Telecominfraproject/wlan-cloud-lib-cppkafka --branch tip-v1 cppkafka
|
||||
cd cppkafka
|
||||
mkdir cmake-build
|
||||
cd cmake-build
|
||||
cmake ..
|
||||
cmake --build . --config Release
|
||||
sudo cmake --build . --target install
|
||||
cd ../..
|
||||
|
||||
cd ~
|
||||
git clone https://github.com/AriliaWireless/valijson --branch tip-v1
|
||||
git clone https://github.com/Telecominfraproject/wlan-cloud-lib-valijson --branch tip-v1 valijson
|
||||
cd valijson
|
||||
mkdir cmake-build
|
||||
cd cmake-build
|
||||
cmake ..
|
||||
cmake --build . --config Release
|
||||
sudo cmake --build . --target install
|
||||
cd ../..
|
||||
|
||||
cd ~
|
||||
git clone https://github.com/Telecominfraproject/wlan-cloud-ucentralgw
|
||||
cd wlan-cloud-ucentralgw
|
||||
mkdir cmake-build
|
||||
cd cmake-build
|
||||
cmake ..
|
||||
make
|
||||
cd ../..
|
||||
```
|
||||
|
||||
## macOS Build
|
||||
@@ -125,7 +128,7 @@ brew install openssl \
|
||||
nlohmann-json \
|
||||
fmt
|
||||
|
||||
git clone https://github.com/AriliaWireless/poco --branch poco-tip-v2
|
||||
git clone https://github.com/Telecominfraproject/wlan-cloud-lib-poco --branch poco-tip-v1 poco
|
||||
pushd poco
|
||||
mkdir cmake-build
|
||||
push cmake-build
|
||||
@@ -135,7 +138,7 @@ sudo cmake --build . --target install
|
||||
popd
|
||||
popd
|
||||
|
||||
git clone https://github.com/AriliaWireless/cppkafka --branch tip-v1
|
||||
git clone https://github.com/Telecominfraproject/wlan-cloud-lib-cppkafka --branch tip-v1 cppkafka
|
||||
pushd cppkafka
|
||||
mkdir cmake-build
|
||||
pushd cmake-build
|
||||
@@ -145,10 +148,10 @@ sudo cmake --build . --target install
|
||||
popd
|
||||
popd
|
||||
|
||||
git clone https://github.com/AriliaWireless/valijson --branch tip-v1
|
||||
cd valijson
|
||||
git clone https://github.com/Telecominfraproject/wlan-cloud-lib-valijson --branch tip-v1 valijson
|
||||
pushd valijson
|
||||
mkdir cmake-build
|
||||
cd cmake-build
|
||||
pushd cmake-build
|
||||
cmake ..
|
||||
cmake --build . --config Release
|
||||
sudo cmake --build . --target install
|
||||
@@ -171,20 +174,23 @@ support. You can build with only SQLite support by not installing the packages f
|
||||
adding -DSMALL_BUILD=1 on the cmake build line.
|
||||
|
||||
```bash
|
||||
sudo apt install git cmake g++ libssl-dev libaprutil1-dev apache2-dev libboost-all-dev libyaml-cpp-dev
|
||||
git clone https://github.com/stephb9959/poco
|
||||
sudo apt install git cmake g++ libssl-dev libaprutil1-dev apache2-dev \
|
||||
libboost-all-dev libyaml-cpp-dev
|
||||
|
||||
git clone https://github.com/Telecominfraproject/wlan-cloud-lib-poco --branch poco-tip-v1 poco
|
||||
cd poco
|
||||
mkdir cmake-build
|
||||
cd cmake-build
|
||||
cmake ..
|
||||
cmake --build . --config Release
|
||||
sudo cmake --build . --target install
|
||||
cd ../..
|
||||
|
||||
cd ~
|
||||
git clone https://github.com/Telecominfraproject/wlan-cloud-ucentralgw
|
||||
cd wlan-cloud-ucentralgw
|
||||
mkdir cmake-build
|
||||
cd cmake-build
|
||||
cmake -DSMALL_BUILD=1 ..
|
||||
make
|
||||
cd ../..
|
||||
```
|
||||
|
||||
24
CHANGELOG.md
Normal file
24
CHANGELOG.md
Normal file
@@ -0,0 +1,24 @@
|
||||
## 3.0.8 (August 08, 2024)
|
||||
- chore: updated package.json, updated helm/Chart.yaml, updated helm/values.yaml, updated CMakeLists.txt, updated version, updated CHANGELOG.md, bumped 3.0.7 -> 3.0.8
|
||||
- Merge pull request #10 from kinarasystems/WIFI-13875-fix-use-dns
|
||||
|
||||
## 3.0.7 (August 07, 2024)
|
||||
- chore: updated package.json, updated helm/Chart.yaml, updated helm/values.yaml, updated CMakeLists.txt, updated version, updated CHANGELOG.md, bumped 3.0.6 -> 3.0.7
|
||||
- Merge branch 'Telecominfraproject:master' into kinara
|
||||
|
||||
## 3.0.6 (July 30, 2024)
|
||||
- chore: updated package.json, updated helm/Chart.yaml, updated helm/values.yaml, updated CMakeLists.txt, updated version, updated CHANGELOG.md, bumped 3.0.5 -> 3.0.6
|
||||
- chore: updated package.json, updated helm/Chart.yaml, updated helm/values.yaml, updated CMakeLists.txt, updated version, updated CHANGELOG.md, bumped 3.0.4 -> 3.0.5
|
||||
|
||||
## 3.0.5 (July 22, 2024)
|
||||
- chore: updated package.json, updated helm/Chart.yaml, updated helm/values.yaml, updated CMakeLists.txt, updated version, updated CHANGELOG.md, bumped 3.0.4 -> 3.0.5
|
||||
- Merge pull request #8 from kinarasystems/command
|
||||
|
||||
## 3.0.4 (July 17, 2024)
|
||||
- chore: updated package.json, updated helm/Chart.yaml, updated helm/values.yaml, updated CMakeLists.txt, updated version, updated CHANGELOG.md, bumped 3.0.3 -> 3.0.4
|
||||
- Merge pull request #7 from kinarasystems/fix_uptime_update_after_reboot
|
||||
|
||||
## 3.0.3 (June 19, 2024)
|
||||
- chore: updated package.json, updated helm/Chart.yaml, updated helm/values.yaml, updated CMakeLists.txt, updated version, created CHANGELOG.md, bumped 3.0.2 -> 3.0.3
|
||||
- Merge pull request #6 from kinarasystems/devices
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
cmake_minimum_required(VERSION 3.13)
|
||||
project(owgw VERSION 3.0.0)
|
||||
project(owgw VERSION 3.0.8)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
set(CMAKE_CXX_STANDARD 20)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED True)
|
||||
|
||||
if(UNIX AND APPLE)
|
||||
set(OPENSSL_ROOT_DIR /usr/local/opt/openssl)
|
||||
@@ -148,6 +149,7 @@ add_executable( owgw
|
||||
src/RESTAPI/RESTAPI_script_handler.cpp src/RESTAPI/RESTAPI_script_handler.h
|
||||
src/RESTAPI/RESTAPI_regulatory.cpp src/RESTAPI/RESTAPI_regulatory.h
|
||||
src/RESTAPI/RESTAPI_radiussessions_handler.cpp src/RESTAPI/RESTAPI_radiussessions_handler.h
|
||||
|
||||
src/storage/storage_blacklist.cpp src/storage/storage_tables.cpp src/storage/storage_logs.cpp
|
||||
src/storage/storage_command.cpp src/storage/storage_healthcheck.cpp src/storage/storage_statistics.cpp
|
||||
src/storage/storage_device.cpp src/storage/storage_capabilities.cpp src/storage/storage_defconfig.cpp
|
||||
|
||||
14
Dockerfile
14
Dockerfile
@@ -1,7 +1,7 @@
|
||||
ARG DEBIAN_VERSION=11.5-slim
|
||||
ARG POCO_VERSION=poco-tip-v2
|
||||
ARG CPPKAFKA_VERSION=tip-v1
|
||||
ARG VALIJASON_VERSION=tip-v1
|
||||
ARG VALIJASON_VERSION=tip-v1.0.2
|
||||
ARG APP_NAME=owgw
|
||||
ARG APP_HOME_DIR=/openwifi
|
||||
|
||||
@@ -17,8 +17,8 @@ FROM build-base AS poco-build
|
||||
|
||||
ARG POCO_VERSION
|
||||
|
||||
ADD https://api.github.com/repos/AriliaWireless/poco/git/refs/tags/${POCO_VERSION} version.json
|
||||
RUN git clone https://github.com/AriliaWireless/poco --branch ${POCO_VERSION} /poco
|
||||
ADD https://api.github.com/repos/Telecominfraproject/wlan-cloud-lib-poco/git/refs/tags/${POCO_VERSION} version.json
|
||||
RUN git clone https://github.com/Telecominfraproject/wlan-cloud-lib-poco --branch ${POCO_VERSION} /poco
|
||||
|
||||
WORKDIR /poco
|
||||
RUN mkdir cmake-build
|
||||
@@ -31,8 +31,8 @@ FROM build-base AS cppkafka-build
|
||||
|
||||
ARG CPPKAFKA_VERSION
|
||||
|
||||
ADD https://api.github.com/repos/AriliaWireless/cppkafka/git/refs/tags/${CPPKAFKA_VERSION} version.json
|
||||
RUN git clone https://github.com/AriliaWireless/cppkafka --branch ${CPPKAFKA_VERSION} /cppkafka
|
||||
ADD https://api.github.com/repos/Telecominfraproject/wlan-cloud-lib-cppkafka/git/refs/tags/${CPPKAFKA_VERSION} version.json
|
||||
RUN git clone https://github.com/Telecominfraproject/wlan-cloud-lib-cppkafka --branch ${CPPKAFKA_VERSION} /cppkafka
|
||||
|
||||
WORKDIR /cppkafka
|
||||
RUN mkdir cmake-build
|
||||
@@ -45,8 +45,8 @@ FROM build-base AS valijson-build
|
||||
|
||||
ARG VALIJASON_VERSION
|
||||
|
||||
ADD https://api.github.com/repos/AriliaWireless/valijson/git/refs/tags/${VALIJASON_VERSION} version.json
|
||||
RUN git clone https://github.com/AriliaWireless/valijson --branch ${VALIJASON_VERSION} /valijson
|
||||
ADD https://api.github.com/repos/Telecominfraproject/wlan-cloud-lib-valijson/git/refs/tags/${VALIJASON_VERSION} version.json
|
||||
RUN git clone https://github.com/Telecominfraproject/wlan-cloud-lib-valijson --branch ${VALIJASON_VERSION} /valijson
|
||||
|
||||
WORKDIR /valijson
|
||||
RUN mkdir cmake-build
|
||||
|
||||
33
PROTOCOL.md
33
PROTOCOL.md
@@ -355,6 +355,39 @@ The device should answer:
|
||||
- 1 : the device is busy but will reboot soon. `text` may indicate why.
|
||||
- 2 : the device will not reboot. `text` contains information as to why.
|
||||
|
||||
#### Controller wants to power-cycle PoE port(s)
|
||||
Controller sends this command to power-cycle 1 or more PoE ports
|
||||
```json
|
||||
{ "jsonrpc" : "2.0" ,
|
||||
"method" : "powercycle" ,
|
||||
"params" : {
|
||||
"serial" : <serial number> ,
|
||||
"ports" : [ { "name" : "Ethernet1", "cycle" : 5000}, { "name" : "Ethernet8", "cycle" : 10000 } ],
|
||||
"when" : Optional - <UTC time when to reboot, 0 mean immediately, this is a suggestion>
|
||||
},
|
||||
"id" : <some number>
|
||||
}
|
||||
```
|
||||
|
||||
The device should answer:
|
||||
```json
|
||||
{ "jsonrpc" : "2.0" ,
|
||||
"result" : {
|
||||
"serial" : <serial number> ,
|
||||
"status" : {
|
||||
"error" : 0 or an error number,
|
||||
"text" : [ "Error 1" , "Error 2" ],
|
||||
"when" : <time when this will be performed as UTC seconds>,
|
||||
},
|
||||
"id" : <same id from request>
|
||||
}
|
||||
```
|
||||
|
||||
###### Error codes
|
||||
- 0 : is rebooting at `when` seconds.
|
||||
- 1 : the device is busy but will reboot soon. `text` may indicate why.
|
||||
- 2 : the device will not reboot. `text` contains information as to why.
|
||||
|
||||
#### Controller wants the device to upgrade its firmware
|
||||
Controller sends this command when it believes the device should upgrade its firmware.
|
||||
```json
|
||||
|
||||
21
buildaws
Executable file
21
buildaws
Executable file
@@ -0,0 +1,21 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
[ -z "$AWS_PROFILE" ] && echo "Please set AWS_PROFILE" && exit 1
|
||||
registry="471112855615.dkr.ecr.us-east-1.amazonaws.com"
|
||||
repo="owgw"
|
||||
aws ecr get-login-password --region us-east-1 | docker login --username AWS --password-stdin "$registry"
|
||||
img="$registry/$repo"
|
||||
if [ -n "$1" ] ; then
|
||||
version="$1"
|
||||
else
|
||||
version="latest"
|
||||
fi
|
||||
#date > about.txt
|
||||
#id=$(git rev-parse HEAD)
|
||||
#br=$(git branch --show-current)
|
||||
#echo "$br" >> about.txt
|
||||
#echo "$id" >> about.txt
|
||||
#echo "Built manually via $0" >> about.txt
|
||||
#docker build --no-cache -t $img:$version .
|
||||
docker build -t $img:$version .
|
||||
docker push $img:$version
|
||||
20
buildit
Executable file
20
buildit
Executable file
@@ -0,0 +1,20 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
repo="owgw"
|
||||
[ -z "$REMOTE_DOCKER_HOST" ] && echo "Please set DOCKER_HOST" && exit 1
|
||||
[ -z "$REMOTE_DOCKER_PASSWORD" ] && echo "Please set DOCKER_PASSWORD" && exit 1
|
||||
img="$REMOTE_DOCKER_HOST/kinara/$repo"
|
||||
if [ -n "$1" ] ; then
|
||||
version="$1"
|
||||
else
|
||||
version="latest"
|
||||
fi
|
||||
#date > about.txt
|
||||
#id=$(git rev-parse HEAD)
|
||||
#br=$(git branch --show-current)
|
||||
#echo "$br" >> about.txt
|
||||
#echo "$id" >> about.txt
|
||||
#echo "Built manually via $0" >> about.txt
|
||||
#docker build --no-cache -t $img:$version .
|
||||
docker build -t $img:$version .
|
||||
docker push $img:$version
|
||||
@@ -1,18 +1,18 @@
|
||||
apiVersion: v2
|
||||
appVersion: "1.0"
|
||||
appVersion: "3.0.8"
|
||||
description: A Helm chart for Kubernetes
|
||||
name: owgw
|
||||
version: 0.1.0
|
||||
dependencies:
|
||||
- name: postgresql
|
||||
repository: https://tip.jfrog.io/artifactory/tip-wlan-cloud-ucentral-helm/
|
||||
version: 10.9.2
|
||||
condition: postgresql.enabled
|
||||
- name: mysql
|
||||
repository: https://tip.jfrog.io/artifactory/tip-wlan-cloud-ucentral-helm/
|
||||
version: 8.8.3
|
||||
condition: mysql.enabled
|
||||
- name: mariadb
|
||||
repository: https://tip.jfrog.io/artifactory/tip-wlan-cloud-ucentral-helm/
|
||||
version: 9.4.2
|
||||
condition: mariadb.enabled
|
||||
- name: postgresql
|
||||
repository: https://tip.jfrog.io/artifactory/tip-wlan-cloud-ucentral-helm/
|
||||
version: 10.9.2
|
||||
condition: postgresql.enabled
|
||||
- name: mysql
|
||||
repository: https://tip.jfrog.io/artifactory/tip-wlan-cloud-ucentral-helm/
|
||||
version: 8.8.3
|
||||
condition: mysql.enabled
|
||||
- name: mariadb
|
||||
repository: https://tip.jfrog.io/artifactory/tip-wlan-cloud-ucentral-helm/
|
||||
version: 9.4.2
|
||||
condition: mariadb.enabled
|
||||
|
||||
@@ -2,24 +2,21 @@
|
||||
replicaCount: 1
|
||||
strategyType: Recreate
|
||||
revisionHistoryLimit: 2
|
||||
|
||||
nameOverride: ""
|
||||
fullnameOverride: ""
|
||||
|
||||
images:
|
||||
owgw:
|
||||
repository: tip-tip-wlan-cloud-ucentral.jfrog.io/owgw
|
||||
tag: master
|
||||
repository: 471112855615.dkr.ecr.us-east-1.amazonaws.com/owgw
|
||||
tag: kv3.0.8
|
||||
pullPolicy: Always
|
||||
# regcred:
|
||||
# registry: tip-tip-wlan-cloud-ucentral.jfrog.io
|
||||
# username: username
|
||||
# password: password
|
||||
# regcred:
|
||||
# registry: tip-tip-wlan-cloud-ucentral.jfrog.io
|
||||
# username: username
|
||||
# password: password
|
||||
dockerize:
|
||||
repository: tip-tip-wlan-cloud-ucentral.jfrog.io/dockerize
|
||||
tag: 0.16.0
|
||||
repository: 471112855615.dkr.ecr.us-east-1.amazonaws.com/wait-ready
|
||||
tag: latest
|
||||
pullPolicy: IfNotPresent
|
||||
|
||||
services:
|
||||
owgw:
|
||||
type: ClusterIP
|
||||
@@ -62,7 +59,6 @@ services:
|
||||
servicePort: 3799
|
||||
targetPort: 3799
|
||||
protocol: UDP
|
||||
|
||||
checks:
|
||||
owgw:
|
||||
liveness:
|
||||
@@ -73,33 +69,31 @@ checks:
|
||||
exec:
|
||||
command:
|
||||
- /readiness_check
|
||||
|
||||
ingresses:
|
||||
restapi:
|
||||
enabled: false
|
||||
annotations: {}
|
||||
# kubernetes.io/ingress.class: nginx
|
||||
# kubernetes.io/tls-acme: "true"
|
||||
# kubernetes.io/ingress.class: nginx
|
||||
# kubernetes.io/tls-acme: "true"
|
||||
hosts:
|
||||
- restapi.chart-example.local
|
||||
- restapi.chart-example.local
|
||||
paths:
|
||||
- path: /
|
||||
pathType: ImplementationSpecific
|
||||
serviceName: owgw
|
||||
servicePort: restapi
|
||||
- path: /
|
||||
pathType: ImplementationSpecific
|
||||
serviceName: owgw
|
||||
servicePort: restapi
|
||||
fileuploader:
|
||||
enabled: false
|
||||
annotations: {}
|
||||
# kubernetes.io/ingress.class: nginx
|
||||
# kubernetes.io/tls-acme: "true"
|
||||
# kubernetes.io/ingress.class: nginx
|
||||
# kubernetes.io/tls-acme: "true"
|
||||
hosts:
|
||||
- fileuploader.chart-example.local
|
||||
- fileuploader.chart-example.local
|
||||
paths:
|
||||
- path: /
|
||||
pathType: ImplementationSpecific
|
||||
serviceName: owgw
|
||||
servicePort: fileuploader
|
||||
|
||||
- path: /
|
||||
pathType: ImplementationSpecific
|
||||
serviceName: owgw
|
||||
servicePort: fileuploader
|
||||
volumes:
|
||||
owgw:
|
||||
- name: config
|
||||
@@ -125,18 +119,17 @@ volumes:
|
||||
volumeDefinition: |
|
||||
persistentVolumeClaim:
|
||||
claimName: {{ template "owgw.fullname" . }}-pvc
|
||||
|
||||
resources: {}
|
||||
# We usually recommend not to specify default resources and to leave this as a conscious
|
||||
# choice for the user. This also increases chances charts run on environments with little
|
||||
# resources, such as Minikube. If you do want to specify resources, uncomment the following
|
||||
# lines, adjust them as necessary, and remove the curly braces after 'resources:'.
|
||||
# requests:
|
||||
# cpu: 100m
|
||||
# memory: 128Mi
|
||||
# limits:
|
||||
# cpu: 100m
|
||||
# memory: 128Mi
|
||||
# We usually recommend not to specify default resources and to leave this as a conscious
|
||||
# choice for the user. This also increases chances charts run on environments with little
|
||||
# resources, such as Minikube. If you do want to specify resources, uncomment the following
|
||||
# lines, adjust them as necessary, and remove the curly braces after 'resources:'.
|
||||
# requests:
|
||||
# cpu: 100m
|
||||
# memory: 128Mi
|
||||
# limits:
|
||||
# cpu: 100m
|
||||
# memory: 128Mi
|
||||
|
||||
securityContext:
|
||||
fsGroup: 1000
|
||||
@@ -151,18 +144,12 @@ securityContext:
|
||||
# value: "2"
|
||||
#- name: net.ipv4.tcp_keepalive_time
|
||||
# value: "45"
|
||||
|
||||
nodeSelector: {}
|
||||
|
||||
tolerations: []
|
||||
|
||||
affinity: {}
|
||||
|
||||
podAnnotations: {}
|
||||
|
||||
podSecurityPolicy:
|
||||
enabled: false
|
||||
|
||||
persistence:
|
||||
enabled: true
|
||||
# storageClassName: "-"
|
||||
@@ -170,7 +157,6 @@ persistence:
|
||||
- ReadWriteOnce
|
||||
size: 10Gi
|
||||
annotations: {}
|
||||
|
||||
# Application
|
||||
public_env_variables:
|
||||
OWGW_ROOT: /owgw-data
|
||||
@@ -180,12 +166,10 @@ public_env_variables:
|
||||
# NOTE in order for readiness check to use system info you need to set READINESS_METHOD to "systeminfo" and set OWSEC to the OWSEC's REST API endpoint
|
||||
#READINESS_METHOD: systeminfo
|
||||
#OWSEC: gw-qa01.cicd.lab.wlan.tip.build:16001
|
||||
|
||||
secret_env_variables:
|
||||
# NOTE in order for readiness check to use system info method you need to override these values to the real OWSEC credentials
|
||||
OWSEC_USERNAME: tip@ucentral.com
|
||||
OWSEC_PASSWORD: openwifi
|
||||
|
||||
configProperties:
|
||||
# -> Public part
|
||||
# Websocket
|
||||
@@ -310,7 +294,6 @@ configProperties:
|
||||
archiver.db.2.keep: 7
|
||||
archiver.db.3.name: commandlist
|
||||
archiver.db.3.keep: 7
|
||||
|
||||
# -> Secret part
|
||||
# Websocket
|
||||
ucentral.websocket.host.0.key.password: mypassword
|
||||
@@ -332,10 +315,8 @@ configProperties:
|
||||
## MySQL
|
||||
storage.type.mysql.username: stephb
|
||||
storage.type.mysql.password: snoopy99
|
||||
|
||||
# NOTE: List of required certificates may be found in "certs" key. Alternative way to pass required certificates is to create external secret with all required certificates and set secret name in "existingCertsSecret" key. Details may be found in https://github.com/Telecominfraproject/wlan-cloud-ucentral-deploy/tree/main/chart#tldr
|
||||
existingCertsSecret: ""
|
||||
|
||||
certs:
|
||||
clientcas.pem: ""
|
||||
issuer.pem: ""
|
||||
@@ -345,66 +326,53 @@ certs:
|
||||
root.pem: ""
|
||||
websocket-cert.pem: ""
|
||||
websocket-key.pem: ""
|
||||
|
||||
certsCAs:
|
||||
issuer.pem: ""
|
||||
root.pem: ""
|
||||
|
||||
# PostgreSQL (https://github.com/bitnami/charts/tree/master/bitnami/postgresql)
|
||||
postgresql:
|
||||
enabled: false
|
||||
|
||||
image:
|
||||
registry: docker.io
|
||||
repository: bitnami/postgresql
|
||||
tag: 11.13.0-debian-10-r0
|
||||
|
||||
postgresqlPostgresPassword: "rootPassword"
|
||||
postgresqlUsername: stephb
|
||||
postgresqlPassword: snoopy99
|
||||
postgresqlDatabase: owgw
|
||||
|
||||
persistence:
|
||||
enabled: true
|
||||
storageClass: ""
|
||||
size: 8Gi
|
||||
|
||||
# MySQL (https://github.com/bitnami/charts/tree/master/bitnami/mysql)
|
||||
mysql:
|
||||
enabled: false
|
||||
|
||||
image:
|
||||
registry: docker.io
|
||||
repository: bitnami/mysql
|
||||
tag: 8.0.26-debian-10-r10
|
||||
|
||||
auth:
|
||||
rootPassword: rootPassword
|
||||
database: owgw
|
||||
username: stephb
|
||||
password: snoopy99
|
||||
|
||||
primary:
|
||||
persistence:
|
||||
enabled: true
|
||||
storageClass: ""
|
||||
size: 8Gi
|
||||
|
||||
# MariaDB (https://github.com/bitnami/charts/tree/master/bitnami/mariadb)
|
||||
mariadb:
|
||||
enabled: false
|
||||
|
||||
image:
|
||||
registry: docker.io
|
||||
repository: bitnami/mariadb
|
||||
tag: 10.5.12-debian-10-r0
|
||||
|
||||
auth:
|
||||
rootPassword: rootPassword
|
||||
database: owgw
|
||||
username: stephb
|
||||
password: snoopy99
|
||||
|
||||
primary:
|
||||
persistence:
|
||||
enabled: true
|
||||
|
||||
85
ols_samples/sample1.json
Normal file
85
ols_samples/sample1.json
Normal file
@@ -0,0 +1,85 @@
|
||||
{
|
||||
"ethernet": [
|
||||
{
|
||||
"select-ports": [
|
||||
"Ethernet0",
|
||||
"Ethernet1",
|
||||
"Ethernet2",
|
||||
"Ethernet3",
|
||||
"Ethernet4",
|
||||
"Ethernet5",
|
||||
"Ethernet6",
|
||||
"Ethernet7"
|
||||
],
|
||||
"speed": 2500,
|
||||
"duplex": "full",
|
||||
"enabled": true,
|
||||
"poe": {
|
||||
"admin-mode": true,
|
||||
"power-limit": 60000
|
||||
}
|
||||
},
|
||||
{
|
||||
"select-ports": [
|
||||
"Ethernet8",
|
||||
"Ethernet9"
|
||||
],
|
||||
"speed": 10000,
|
||||
"duplex": "full",
|
||||
"media": "sfp-forced-1000sfp"
|
||||
}
|
||||
],
|
||||
"interfaces": [
|
||||
{
|
||||
"name": "VLAN1",
|
||||
"vlan": {
|
||||
"id": 1
|
||||
},
|
||||
"ipv4": {
|
||||
"addressing": "dynamic"
|
||||
},
|
||||
"ethernet": [
|
||||
{
|
||||
"select-ports": [
|
||||
"Ethernet0",
|
||||
"Ethernet1",
|
||||
"Ethernet2",
|
||||
"Ethernet3",
|
||||
"Ethernet4",
|
||||
"Ethernet5",
|
||||
"Ethernet6",
|
||||
"Ethernet7",
|
||||
"Ethernet8",
|
||||
"Ethernet9"
|
||||
],
|
||||
"vlan-tag": "un-tagged"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"metrics": {
|
||||
"dhcp-snooping": {
|
||||
"filters": [
|
||||
"ack",
|
||||
"discover",
|
||||
"offer",
|
||||
"request",
|
||||
"solicit",
|
||||
"reply",
|
||||
"renew"
|
||||
]
|
||||
},
|
||||
"health": {
|
||||
"interval": 60
|
||||
},
|
||||
"statistics": {
|
||||
"interval": 120,
|
||||
"types": []
|
||||
}
|
||||
},
|
||||
"unit": {
|
||||
"leds-active": true,
|
||||
"usage-threshold": 95
|
||||
},
|
||||
"uuid": 1678263900
|
||||
}
|
||||
@@ -42,12 +42,10 @@ components:
|
||||
schemas:
|
||||
DeviceType:
|
||||
type: string
|
||||
default: AP
|
||||
default: ap
|
||||
enum:
|
||||
- AP
|
||||
- SWITCH
|
||||
- IOT
|
||||
- MESH
|
||||
- ap
|
||||
- switch
|
||||
|
||||
DeviceRestrictionsKeyInfo:
|
||||
type: object
|
||||
@@ -157,6 +155,9 @@ components:
|
||||
lastRecordedContact:
|
||||
type: integer
|
||||
format: int64
|
||||
blackListed:
|
||||
type: boolean
|
||||
readOnly: true
|
||||
|
||||
DeviceWithStatus:
|
||||
type: object
|
||||
@@ -281,6 +282,9 @@ components:
|
||||
format: float
|
||||
connectReason:
|
||||
type: string
|
||||
blackListed:
|
||||
type: boolean
|
||||
readOnly: true
|
||||
|
||||
DeviceList:
|
||||
type: object
|
||||
@@ -545,6 +549,12 @@ components:
|
||||
lastModified:
|
||||
type: integer
|
||||
format: int64
|
||||
platform:
|
||||
type: string
|
||||
enum:
|
||||
- ap
|
||||
- switch
|
||||
default: ap
|
||||
|
||||
DefaultConfigurationList:
|
||||
properties:
|
||||
@@ -1566,6 +1576,30 @@ components:
|
||||
format: base64
|
||||
description: This is a base64 encoded string of the certificate bundle (the current bundle .tar.gz file from the PKI portal)
|
||||
|
||||
PowerCycleRequest:
|
||||
type: object
|
||||
properties:
|
||||
serial:
|
||||
type: string
|
||||
when:
|
||||
type: integer
|
||||
format: int64
|
||||
ports:
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
properties:
|
||||
name:
|
||||
type: string
|
||||
example:
|
||||
- Ethernet0
|
||||
cycle:
|
||||
type: integer
|
||||
default: 10000
|
||||
minimum: 1
|
||||
maximum: 60000
|
||||
description: off time in milliseconds
|
||||
|
||||
paths:
|
||||
/devices:
|
||||
get:
|
||||
@@ -1657,6 +1691,22 @@ paths:
|
||||
type: integer
|
||||
default: 70
|
||||
required: false
|
||||
- in: query
|
||||
description: return only devices matching a certain platform of AP or SWITCH
|
||||
name: platform
|
||||
schema:
|
||||
type: string
|
||||
default: ALL
|
||||
enum:
|
||||
- all
|
||||
- ap
|
||||
- switch
|
||||
required: false
|
||||
- in: query
|
||||
description: only devices which are not provisioned
|
||||
name: includeProvisioned
|
||||
schema:
|
||||
type: boolean
|
||||
responses:
|
||||
200:
|
||||
description: List devices
|
||||
@@ -3006,6 +3056,34 @@ paths:
|
||||
404:
|
||||
$ref: '#/components/responses/NotFound'
|
||||
|
||||
/device/{serialNumber}/powercycle:
|
||||
post:
|
||||
tags:
|
||||
- Commands
|
||||
summary: Perform PoE power cycle for some PoE ports.
|
||||
operationId: performPowerCycle
|
||||
parameters:
|
||||
- in: path
|
||||
name: serialNumber
|
||||
schema:
|
||||
type: string
|
||||
required: true
|
||||
requestBody:
|
||||
description: Certificate update details
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/PowerCycleRequest'
|
||||
responses:
|
||||
200:
|
||||
$ref: '#/components/responses/Success'
|
||||
403:
|
||||
$ref: '#/components/responses/Unauthorized'
|
||||
404:
|
||||
$ref: '#/components/responses/NotFound'
|
||||
|
||||
/ouis:
|
||||
get:
|
||||
tags:
|
||||
|
||||
15
package.json
Normal file
15
package.json
Normal file
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"name": "owgw",
|
||||
"version": "3.0.8",
|
||||
"description": "This is the Kinara version of OpenWifi OWGW",
|
||||
"author": "Kinara Systems",
|
||||
"homepage": "https://kinarasystems.com",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/kinarasystems/wlan-cloud-ucentralgw"
|
||||
},
|
||||
"keywords": [
|
||||
"owgw",
|
||||
"gateway"
|
||||
]
|
||||
}
|
||||
@@ -9,14 +9,14 @@
|
||||
|
||||
namespace OpenWifi {
|
||||
|
||||
int AP_WS_ConfigAutoUpgrader::Start() {
|
||||
int AP_WS_ConfigAutoUpgradeAgent::Start() {
|
||||
poco_notice(Logger(), "Starting...");
|
||||
QueueManager_.start(*this);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void AP_WS_ConfigAutoUpgrader::Stop() {
|
||||
void AP_WS_ConfigAutoUpgradeAgent::Stop() {
|
||||
poco_notice(Logger(), "Stopping...");
|
||||
Running_ = false;
|
||||
Queue_.wakeUpAll();
|
||||
@@ -24,7 +24,7 @@ namespace OpenWifi {
|
||||
poco_notice(Logger(), "Stopped...");
|
||||
}
|
||||
|
||||
void AP_WS_ConfigAutoUpgrader::run() {
|
||||
void AP_WS_ConfigAutoUpgradeAgent::run() {
|
||||
Utils::SetThreadName("auto:cfgmgr");
|
||||
Running_ = true;
|
||||
|
||||
|
||||
@@ -28,14 +28,14 @@ namespace OpenWifi {
|
||||
std::uint64_t pending_config_=0;
|
||||
};
|
||||
|
||||
class AP_WS_ConfigAutoUpgrader : public SubSystemServer, Poco::Runnable {
|
||||
class AP_WS_ConfigAutoUpgradeAgent : public SubSystemServer, Poco::Runnable {
|
||||
public:
|
||||
int Start() final;
|
||||
void Stop() final;
|
||||
void run() final;
|
||||
|
||||
static auto instance() {
|
||||
static auto instance = new AP_WS_ConfigAutoUpgrader;
|
||||
static auto instance = new AP_WS_ConfigAutoUpgradeAgent;
|
||||
return instance;
|
||||
}
|
||||
|
||||
@@ -126,12 +126,12 @@ namespace OpenWifi {
|
||||
mutable std::mutex CacheMutex_;
|
||||
std::map<std::uint64_t, ConfigurationCacheEntry> Cache_;
|
||||
|
||||
AP_WS_ConfigAutoUpgrader() noexcept
|
||||
AP_WS_ConfigAutoUpgradeAgent() noexcept
|
||||
: SubSystemServer("AutoConfigUpgrade", "AUTO-CFG-MGR", "auto.config.updater") {
|
||||
}
|
||||
};
|
||||
|
||||
inline auto AP_WS_ConfigAutoUpgrader() { return AP_WS_ConfigAutoUpgrader::instance(); }
|
||||
inline auto AP_WS_ConfigAutoUpgradeAgent() { return AP_WS_ConfigAutoUpgradeAgent::instance(); }
|
||||
|
||||
} // namespace OpenWifi
|
||||
|
||||
|
||||
@@ -2,37 +2,32 @@
|
||||
// Created by stephane bourque on 2022-02-03.
|
||||
//
|
||||
|
||||
#include "AP_WS_Connection.h"
|
||||
|
||||
#include "Poco/Base64Decoder.h"
|
||||
#include "Poco/Net/Context.h"
|
||||
#include "Poco/Net/HTTPServerRequestImpl.h"
|
||||
#include "Poco/Net/HTTPServerResponseImpl.h"
|
||||
#include "Poco/Net/NetException.h"
|
||||
#include "Poco/Net/SSLException.h"
|
||||
#include "Poco/Net/SecureStreamSocketImpl.h"
|
||||
#include "Poco/Net/WebSocketImpl.h"
|
||||
#include "Poco/zlib.h"
|
||||
#include <Poco/Base64Decoder.h>
|
||||
#include <Poco/Net/Context.h>
|
||||
#include <Poco/Net/HTTPServerRequestImpl.h>
|
||||
#include <Poco/Net/HTTPServerResponseImpl.h>
|
||||
#include <Poco/Net/NetException.h>
|
||||
#include <Poco/Net/SSLException.h>
|
||||
#include <Poco/Net/SecureStreamSocketImpl.h>
|
||||
#include <Poco/Net/WebSocketImpl.h>
|
||||
|
||||
#include "AP_WS_Server.h"
|
||||
#include "CentralConfig.h"
|
||||
#include "CommandManager.h"
|
||||
#include "ConfigurationCache.h"
|
||||
#include "StorageService.h"
|
||||
#include "TelemetryStream.h"
|
||||
#include <framework/KafkaManager.h>
|
||||
#include <framework/MicroServiceFuncs.h>
|
||||
#include <framework/utils.h>
|
||||
#include <framework/ow_constants.h>
|
||||
|
||||
#include "GWKafkaEvents.h"
|
||||
#include "UI_GW_WebSocketNotifications.h"
|
||||
#include "framework/KafkaManager.h"
|
||||
#include "framework/MicroServiceFuncs.h"
|
||||
#include "framework/utils.h"
|
||||
#include <fmt/format.h>
|
||||
|
||||
#include "fmt/format.h"
|
||||
|
||||
#include "framework/ow_constants.h"
|
||||
|
||||
#include "RADIUSSessionTracker.h"
|
||||
#include "RADIUS_proxy_server.h"
|
||||
#include <AP_WS_Connection.h>
|
||||
#include <AP_WS_Server.h>
|
||||
#include <CentralConfig.h>
|
||||
#include <CommandManager.h>
|
||||
#include <StorageService.h>
|
||||
#include <RADIUSSessionTracker.h>
|
||||
#include <RADIUS_proxy_server.h>
|
||||
#include <GWKafkaEvents.h>
|
||||
#include <UI_GW_WebSocketNotifications.h>
|
||||
|
||||
namespace OpenWifi {
|
||||
|
||||
@@ -60,6 +55,8 @@ namespace OpenWifi {
|
||||
WS_->setKeepAlive(true);
|
||||
WS_->setBlocking(false);
|
||||
uuid_ = MicroServiceRandom(std::numeric_limits<std::uint64_t>::max()-1);
|
||||
|
||||
AP_WS_Server()->IncrementConnectionCount();
|
||||
}
|
||||
|
||||
void AP_WS_Connection::Start() {
|
||||
@@ -79,14 +76,11 @@ namespace OpenWifi {
|
||||
}
|
||||
|
||||
AP_WS_Connection::~AP_WS_Connection() {
|
||||
// poco_information(Logger_, fmt::format("DESTRUCTOR({}): 0 - Session={} Connection closed.", SerialNumber_,
|
||||
// State_.sessionId));
|
||||
std::lock_guard G(ConnectionMutex_);
|
||||
// poco_information(Logger_, fmt::format("DESTRUCTOR({}): 1 - Session={} Connection closed.", SerialNumber_,
|
||||
// State_.sessionId));
|
||||
EndConnection(false);
|
||||
AP_WS_Server()->DecrementConnectionCount();
|
||||
EndConnection();
|
||||
poco_debug(Logger_, fmt::format("TERMINATION({}): Session={}, Connection removed.", SerialNumber_,
|
||||
State_.sessionId));
|
||||
State_.sessionId));
|
||||
}
|
||||
|
||||
static void NotifyKafkaDisconnect(const std::string &SerialNumber, std::uint64_t uuid) {
|
||||
@@ -102,7 +96,7 @@ namespace OpenWifi {
|
||||
}
|
||||
}
|
||||
|
||||
void AP_WS_Connection::EndConnection(bool Clean) {
|
||||
void AP_WS_Connection::EndConnection() {
|
||||
bool expectedValue=false;
|
||||
if (Dead_.compare_exchange_strong(expectedValue,true,std::memory_order_release,std::memory_order_relaxed)) {
|
||||
|
||||
@@ -128,9 +122,7 @@ namespace OpenWifi {
|
||||
if(!SerialNumber_.empty()) {
|
||||
DeviceDisconnectionCleanup(SerialNumber_, uuid_);
|
||||
}
|
||||
|
||||
if(Clean)
|
||||
AP_WS_Server()->EndSession(State_.sessionId, SerialNumberInt_);
|
||||
AP_WS_Server()->AddCleanupSession(State_.sessionId, SerialNumberInt_);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -569,14 +561,14 @@ namespace OpenWifi {
|
||||
void AP_WS_Connection::OnSocketShutdown(
|
||||
[[maybe_unused]] const Poco::AutoPtr<Poco::Net::ShutdownNotification> &pNf) {
|
||||
poco_trace(Logger_, fmt::format("SOCKET-SHUTDOWN({}): Closing.", CId_));
|
||||
std::lock_guard G(ConnectionMutex_);
|
||||
// std::lock_guard G(ConnectionMutex_);
|
||||
return EndConnection();
|
||||
}
|
||||
|
||||
void AP_WS_Connection::OnSocketError(
|
||||
[[maybe_unused]] const Poco::AutoPtr<Poco::Net::ErrorNotification> &pNf) {
|
||||
poco_trace(Logger_, fmt::format("SOCKET-ERROR({}): Closing.", CId_));
|
||||
std::lock_guard G(ConnectionMutex_);
|
||||
// std::lock_guard G(ConnectionMutex_);
|
||||
return EndConnection();
|
||||
}
|
||||
|
||||
@@ -586,7 +578,7 @@ namespace OpenWifi {
|
||||
if (Dead_) // we are dead, so we do not process anything.
|
||||
return;
|
||||
|
||||
std::lock_guard DeviceLock(ConnectionMutex_);
|
||||
std::lock_guard G(ConnectionMutex_);
|
||||
|
||||
State_.LastContact = LastContact_ = Utils::Now();
|
||||
if (AP_WS_Server()->Running() && (DeviceValidated_ || ValidatedDevice())) {
|
||||
@@ -902,25 +894,25 @@ namespace OpenWifi {
|
||||
try {
|
||||
Poco::JSON::Parser P;
|
||||
auto Stats = P.parse(LastStats).extract<Poco::JSON::Object::Ptr>();
|
||||
hasGPS_ = Stats->isObject("gps");
|
||||
State_.hasGPS = Stats->isObject("gps");
|
||||
auto Unit = Stats->getObject("unit");
|
||||
auto Memory = Unit->getObject("memory");
|
||||
std::uint64_t TotalMemory = Memory->get("total");
|
||||
std::uint64_t FreeMemory = Memory->get("free");
|
||||
if (TotalMemory > 0) {
|
||||
memory_used_ =
|
||||
State_.memoryUsed =
|
||||
(100.0 * ((double)TotalMemory - (double)FreeMemory)) / (double)TotalMemory;
|
||||
}
|
||||
if (Unit->isArray("load")) {
|
||||
Poco::JSON::Array::Ptr Load = Unit->getArray("load");
|
||||
if (Load->size() > 1) {
|
||||
cpu_load_ = Load->get(1);
|
||||
State_.load = Load->get(1);
|
||||
}
|
||||
}
|
||||
if (Unit->isArray("temperature")) {
|
||||
Poco::JSON::Array::Ptr Temperature = Unit->getArray("temperature");
|
||||
if (Temperature->size() > 1) {
|
||||
temperature_ = Temperature->get(0);
|
||||
State_.temperature = Temperature->get(0);
|
||||
}
|
||||
}
|
||||
} catch (const Poco::Exception &E) {
|
||||
|
||||
@@ -30,7 +30,7 @@ namespace OpenWifi {
|
||||
Poco::Logger &L, std::pair<std::shared_ptr<Poco::Net::SocketReactor>, std::shared_ptr<LockedDbSession>> R);
|
||||
~AP_WS_Connection();
|
||||
|
||||
void EndConnection(bool Clean = true);
|
||||
void EndConnection();
|
||||
void ProcessJSONRPCEvent(Poco::JSON::Object::Ptr &Doc);
|
||||
void ProcessJSONRPCResult(Poco::JSON::Object::Ptr Doc);
|
||||
void ProcessIncomingFrame();
|
||||
@@ -79,14 +79,14 @@ namespace OpenWifi {
|
||||
}
|
||||
}
|
||||
|
||||
inline GWObjects::DeviceRestrictions GetRestrictions() {
|
||||
std::lock_guard G(ConnectionMutex_);
|
||||
return Restrictions_;
|
||||
}
|
||||
|
||||
[[nodiscard]] inline bool HasGPS() const { return hasGPS_; }
|
||||
[[nodiscard]] bool ValidatedDevice();
|
||||
|
||||
inline void GetRestrictions(GWObjects::DeviceRestrictions &R) {
|
||||
std::lock_guard G(ConnectionMutex_);
|
||||
R = Restrictions_;
|
||||
}
|
||||
|
||||
inline bool GetTelemetryParameters(bool &Reporting, uint64_t &Interval,
|
||||
uint64_t &WebSocketTimer, uint64_t &KafkaTimer,
|
||||
uint64_t &WebSocketCount, uint64_t &KafkaCount,
|
||||
@@ -105,14 +105,10 @@ namespace OpenWifi {
|
||||
|
||||
friend class AP_WS_Server;
|
||||
|
||||
inline GWObjects::DeviceRestrictions Restrictions() {
|
||||
std::lock_guard G(ConnectionMutex_);
|
||||
return Restrictions_;
|
||||
}
|
||||
void Start();
|
||||
|
||||
private:
|
||||
std::recursive_mutex ConnectionMutex_;
|
||||
mutable std::recursive_mutex ConnectionMutex_;
|
||||
std::mutex TelemetryMutex_;
|
||||
Poco::Logger &Logger_;
|
||||
std::shared_ptr<Poco::Net::SocketReactor> Reactor_;
|
||||
@@ -148,7 +144,7 @@ namespace OpenWifi {
|
||||
std::double_t memory_used_=0.0, cpu_load_ = 0.0, temperature_ = 0.0;
|
||||
std::uint64_t uuid_=0;
|
||||
bool Simulated_=false;
|
||||
std::uint64_t LastContact_=0;
|
||||
std::atomic_uint64_t LastContact_=0;
|
||||
|
||||
static inline std::atomic_uint64_t ConcurrentStartingDevices_ = 0;
|
||||
|
||||
|
||||
@@ -11,78 +11,101 @@ namespace OpenWifi {
|
||||
if (UUID == 0)
|
||||
return false;
|
||||
|
||||
uint64_t GoodConfig = ConfigurationCache().CurrentConfig(SerialNumberInt_);
|
||||
uint64_t GoodConfig = GetCurrentConfigurationID(SerialNumberInt_);
|
||||
if (GoodConfig && (GoodConfig == UUID || GoodConfig == State_.PendingUUID)) {
|
||||
UpgradedUUID = UUID;
|
||||
State_.PendingUUID = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
GWObjects::Device D;
|
||||
if (StorageService()->GetDevice(Session,SerialNumber_, D)) {
|
||||
if(D.pendingUUID!=0 && UUID==D.pendingUUID) {
|
||||
// so we sent an upgrade to a device, and now it is completing now...
|
||||
UpgradedUUID = D.pendingUUID;
|
||||
StorageService()->CompleteDeviceConfigurationChange(Session, SerialNumber_);
|
||||
return true;
|
||||
}
|
||||
|
||||
// This is the case where the cache is empty after a restart. So GoodConfig will 0. If
|
||||
// the device already has the right UUID, we just return.
|
||||
if (D.UUID == UUID) {
|
||||
UpgradedUUID = UUID;
|
||||
ConfigurationCache().Add(SerialNumberInt_, UUID);
|
||||
return false;
|
||||
}
|
||||
|
||||
Config::Config Cfg(D.Configuration);
|
||||
if (UUID > D.UUID) {
|
||||
// so we have a problem, the device has a newer config than we have. So we need to
|
||||
// make sure our config is newer.
|
||||
D.UUID = UUID + 2;
|
||||
UpgradedUUID = D.UUID;
|
||||
}
|
||||
|
||||
Cfg.SetUUID(D.UUID);
|
||||
D.Configuration = Cfg.get();
|
||||
State_.PendingUUID = UpgradedUUID = D.UUID;
|
||||
|
||||
GWObjects::CommandDetails Cmd;
|
||||
Cmd.SerialNumber = SerialNumber_;
|
||||
Cmd.UUID = MicroServiceCreateUUID();
|
||||
Cmd.SubmittedBy = uCentralProtocol::SUBMITTED_BY_SYSTEM;
|
||||
Cmd.Status = uCentralProtocol::PENDING;
|
||||
Cmd.Command = uCentralProtocol::CONFIGURE;
|
||||
Poco::JSON::Parser P;
|
||||
auto ParsedConfig = P.parse(D.Configuration).extract<Poco::JSON::Object::Ptr>();
|
||||
Poco::JSON::Object Params;
|
||||
Params.set(uCentralProtocol::SERIAL, SerialNumber_);
|
||||
Params.set(uCentralProtocol::UUID, D.UUID);
|
||||
Params.set(uCentralProtocol::WHEN, 0);
|
||||
Params.set(uCentralProtocol::CONFIG, ParsedConfig);
|
||||
|
||||
std::ostringstream O;
|
||||
Poco::JSON::Stringifier::stringify(Params, O);
|
||||
Cmd.Details = O.str();
|
||||
poco_information(Logger_,
|
||||
fmt::format("CFG-UPGRADE({}): Current ID: {}, newer configuration {}.",
|
||||
CId_, UUID, D.UUID));
|
||||
bool Sent;
|
||||
|
||||
StorageService()->AddCommand(SerialNumber_, Cmd,
|
||||
Storage::CommandExecutionType::COMMAND_EXECUTED);
|
||||
CommandManager()->PostCommand(
|
||||
CommandManager()->Next_RPC_ID(), APCommands::to_apcommand(Cmd.Command.c_str()),
|
||||
SerialNumber_, Cmd.Command, Params, Cmd.UUID, Sent, false, false);
|
||||
|
||||
GWWebSocketNotifications::SingleDeviceConfigurationChange_t Notification;
|
||||
Notification.content.serialNumber = D.SerialNumber;
|
||||
Notification.content.oldUUID = UUID;
|
||||
Notification.content.newUUID = UpgradedUUID;
|
||||
GWWebSocketNotifications::DeviceConfigurationChange(Notification);
|
||||
if (!StorageService()->GetDevice(Session,SerialNumber_, D)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if(State_.PendingUUID!=0 && UUID==State_.PendingUUID) {
|
||||
// so we sent an upgrade to a device, and now it is completing now...
|
||||
UpgradedUUID = UUID;
|
||||
StorageService()->CompleteDeviceConfigurationChange(Session, SerialNumber_);
|
||||
State_.PendingUUID = 0;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
||||
// dont upgrade a switch if it does not have a real config. Config will always be more than 20 characters
|
||||
if (D.DeviceType==Platforms::SWITCH && D.Configuration.size()<20) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Config::Config Cfg(D.Configuration);
|
||||
// if this is a broken device (UUID==0) just fix it
|
||||
auto StoredConfigurationUUID = Cfg.UUID();
|
||||
if(D.UUID==0) {
|
||||
D.UUID = StoredConfigurationUUID;
|
||||
}
|
||||
|
||||
|
||||
if (D.UUID == UUID) {
|
||||
D.UUID = UpgradedUUID = UUID;
|
||||
State_.PendingUUID = D.pendingUUID = 0;
|
||||
D.pendingConfiguration.clear();
|
||||
D.pendingConfigurationCmd.clear();
|
||||
StorageService()->UpdateDevice(Session, D);
|
||||
SetCurrentConfigurationID(SerialNumberInt_, UUID);
|
||||
// std::cout << __LINE__ << ": " << SerialNumber_ << " GoodConfig: " << GoodConfig << " UUID:" << UUID << " Pending:" << State_.PendingUUID << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (UUID > D.UUID) {
|
||||
// so we have a problem, the device has a newer config than we have. So we need to
|
||||
// make sure our config is newer.
|
||||
D.UUID = UUID + 2;
|
||||
UpgradedUUID = D.UUID;
|
||||
// std::cout << __LINE__ << ": " << SerialNumber_ << " GoodConfig: " << GoodConfig << " UUID:" << UUID << " Pending:" << State_.PendingUUID << std::endl;
|
||||
}
|
||||
|
||||
Cfg.SetUUID(D.UUID);
|
||||
D.Configuration = Cfg.get();
|
||||
D.pendingUUID = State_.PendingUUID = UpgradedUUID = D.UUID;
|
||||
StorageService()->UpdateDevice(Session, D);
|
||||
|
||||
GWObjects::CommandDetails Cmd;
|
||||
Cmd.SerialNumber = SerialNumber_;
|
||||
Cmd.UUID = MicroServiceCreateUUID();
|
||||
Cmd.SubmittedBy = uCentralProtocol::SUBMITTED_BY_SYSTEM;
|
||||
Cmd.Status = uCentralProtocol::PENDING;
|
||||
Cmd.Command = uCentralProtocol::CONFIGURE;
|
||||
Poco::JSON::Parser P;
|
||||
auto ParsedConfig = P.parse(D.Configuration).extract<Poco::JSON::Object::Ptr>();
|
||||
Poco::JSON::Object Params;
|
||||
Params.set(uCentralProtocol::SERIAL, SerialNumber_);
|
||||
Params.set(uCentralProtocol::UUID, D.UUID);
|
||||
Params.set(uCentralProtocol::WHEN, 0);
|
||||
Params.set(uCentralProtocol::CONFIG, ParsedConfig);
|
||||
|
||||
std::ostringstream O;
|
||||
Poco::JSON::Stringifier::stringify(Params, O);
|
||||
Cmd.Details = O.str();
|
||||
poco_information(Logger_,
|
||||
fmt::format("CFG-UPGRADE({}): Current ID: {}, newer configuration {}.",
|
||||
CId_, UUID, D.UUID));
|
||||
bool Sent;
|
||||
|
||||
StorageService()->AddCommand(SerialNumber_, Cmd,
|
||||
Storage::CommandExecutionType::COMMAND_EXECUTED);
|
||||
CommandManager()->PostCommand(
|
||||
CommandManager()->Next_RPC_ID(), APCommands::to_apcommand(Cmd.Command.c_str()),
|
||||
SerialNumber_, Cmd.Command, Params, Cmd.UUID, Sent, false, false);
|
||||
|
||||
GWWebSocketNotifications::SingleDeviceConfigurationChange_t Notification;
|
||||
Notification.content.serialNumber = D.SerialNumber;
|
||||
Notification.content.oldUUID = UUID;
|
||||
Notification.content.newUUID = UpgradedUUID;
|
||||
GWWebSocketNotifications::DeviceConfigurationChange(Notification);
|
||||
|
||||
// std::cout << __LINE__ << ": " << SerialNumber_ << " GoodConfig: " << GoodConfig << " UUID:" << UUID <<
|
||||
// " Pending:" << State_.PendingUUID << " Upgraded:" << UpgradedUUID << std::endl;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -83,6 +83,8 @@ namespace OpenWifi {
|
||||
State_.Address = Utils::FormatIPv6(WS_->peerAddress().toString());
|
||||
CId_ = SerialNumber_ + "@" + CId_;
|
||||
|
||||
auto Platform = Poco::toLower(Caps.Platform());
|
||||
|
||||
if(ParamsObj->has("reason")) {
|
||||
State_.connectReason = ParamsObj->get("reason").toString();
|
||||
}
|
||||
@@ -204,8 +206,13 @@ namespace OpenWifi {
|
||||
++Updated;
|
||||
}
|
||||
|
||||
if (Compatible_ != DeviceInfo.DeviceType) {
|
||||
DeviceInfo.DeviceType = Compatible_;
|
||||
if (Compatible_ != DeviceInfo.Compatible) {
|
||||
DeviceInfo.Compatible = Compatible_;
|
||||
++Updated;
|
||||
}
|
||||
|
||||
if (Platform != DeviceInfo.DeviceType) {
|
||||
DeviceInfo.DeviceType = Platform;
|
||||
++Updated;
|
||||
}
|
||||
|
||||
@@ -227,10 +234,11 @@ namespace OpenWifi {
|
||||
if (Updated) {
|
||||
StorageService()->UpdateDevice(DbSession_->Session(), DeviceInfo);
|
||||
}
|
||||
}
|
||||
|
||||
if(!Simulated_) {
|
||||
uint64_t UpgradedUUID = 0;
|
||||
LookForUpgrade(DbSession_->Session(), UUID, UpgradedUUID);
|
||||
if(!Simulated_) {
|
||||
uint64_t UpgradedUUID = 0;
|
||||
if (LookForUpgrade(DbSession_->Session(), UUID, UpgradedUUID)) {
|
||||
State_.UUID = UpgradedUUID;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,6 +26,7 @@ namespace OpenWifi {
|
||||
|
||||
uint64_t UUID = ParamsObj->get(uCentralProtocol::UUID);
|
||||
auto Sanity = ParamsObj->get(uCentralProtocol::SANITY);
|
||||
State_.sanity = Sanity;
|
||||
auto CheckData = ParamsObj->get(uCentralProtocol::DATA).toString();
|
||||
if (CheckData.empty())
|
||||
CheckData = uCentralProtocol::EMPTY_JSON_DOC;
|
||||
|
||||
@@ -58,7 +58,7 @@ namespace OpenWifi {
|
||||
}
|
||||
|
||||
StateUtils::ComputeAssociations(StateObj, State_.Associations_2G,
|
||||
State_.Associations_5G, State_.Associations_6G);
|
||||
State_.Associations_5G, State_.Associations_6G, State_.uptime);
|
||||
|
||||
if (KafkaManager()->Enabled() && !AP_WS_Server()->KafkaDisableState()) {
|
||||
KafkaManager()->PostMessage(KafkaTopics::STATE, SerialNumber_, *ParamsObj);
|
||||
|
||||
@@ -7,10 +7,12 @@
|
||||
#include <mutex>
|
||||
#include <string>
|
||||
|
||||
#include "Poco/Environment.h"
|
||||
#include "Poco/Net/SocketAcceptor.h"
|
||||
#include <framework/utils.h>
|
||||
|
||||
#include <Poco/Environment.h>
|
||||
#include <Poco/Net/SocketAcceptor.h>
|
||||
#include <Poco/Data/SessionPool.h>
|
||||
#include "framework/utils.h"
|
||||
|
||||
#include <StorageService.h>
|
||||
|
||||
namespace OpenWifi {
|
||||
@@ -55,7 +57,7 @@ namespace OpenWifi {
|
||||
DbSessions_.clear();
|
||||
}
|
||||
|
||||
std::pair<std::shared_ptr<Poco::Net::SocketReactor>, std::shared_ptr<LockedDbSession> > NextReactor() {
|
||||
auto NextReactor() {
|
||||
std::lock_guard Lock(Mutex_);
|
||||
NextReactor_++;
|
||||
NextReactor_ %= NumberOfThreads_;
|
||||
|
||||
@@ -6,21 +6,23 @@
|
||||
// Arilia Wireless Inc.
|
||||
//
|
||||
|
||||
#include "Poco/Net/Context.h"
|
||||
#include "Poco/Net/HTTPHeaderStream.h"
|
||||
#include "Poco/Net/HTTPServerRequest.h"
|
||||
#include <Poco/Net/Context.h>
|
||||
#include <Poco/Net/HTTPHeaderStream.h>
|
||||
#include <Poco/Net/HTTPServerRequest.h>
|
||||
|
||||
#include "AP_WS_Connection.h"
|
||||
#include "AP_WS_Server.h"
|
||||
#include "ConfigurationCache.h"
|
||||
#include "TelemetryStream.h"
|
||||
#include <AP_WS_Connection.h>
|
||||
#include <AP_WS_Server.h>
|
||||
#include <ConfigurationCache.h>
|
||||
#include <TelemetryStream.h>
|
||||
|
||||
#include "UI_GW_WebSocketNotifications.h"
|
||||
#include "fmt/format.h"
|
||||
#include "framework/MicroServiceFuncs.h"
|
||||
#include "framework/utils.h"
|
||||
#include <fmt/format.h>
|
||||
|
||||
#include <framework/MicroServiceFuncs.h>
|
||||
#include <framework/utils.h>
|
||||
#include <framework/KafkaManager.h>
|
||||
|
||||
#include <UI_GW_WebSocketNotifications.h>
|
||||
|
||||
namespace OpenWifi {
|
||||
|
||||
class AP_WS_RequestHandler : public Poco::Net::HTTPRequestHandler {
|
||||
@@ -198,9 +200,53 @@ namespace OpenWifi {
|
||||
Running_ = true;
|
||||
GarbageCollector_.setName("ws:garbage");
|
||||
GarbageCollector_.start(*this);
|
||||
|
||||
std::thread CleanupThread([this](){ CleanupSessions(); });
|
||||
CleanupThread.detach();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool AP_WS_Server::Disconnect(uint64_t SerialNumber) {
|
||||
std::shared_ptr<AP_WS_Connection> Connection;
|
||||
{
|
||||
auto hashIndex = MACHash::Hash(SerialNumber);
|
||||
std::lock_guard DeviceLock(SerialNumbersMutex_[hashIndex]);
|
||||
auto DeviceHint = SerialNumbers_[hashIndex].find(SerialNumber);
|
||||
if (DeviceHint == SerialNumbers_[hashIndex].end() || DeviceHint->second == nullptr) {
|
||||
return false;
|
||||
}
|
||||
Connection = DeviceHint->second;
|
||||
SerialNumbers_[hashIndex].erase(DeviceHint);
|
||||
}
|
||||
|
||||
{
|
||||
auto H = SessionHash::Hash(Connection->State_.sessionId);
|
||||
std::lock_guard SessionLock(SessionMutex_[H]);
|
||||
Sessions_[H].erase(Connection->State_.sessionId);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void AP_WS_Server::CleanupSessions() {
|
||||
|
||||
while(Running_) {
|
||||
std::this_thread::sleep_for(std::chrono::seconds(10));
|
||||
|
||||
while(Running_ && !CleanupSessions_.empty()) {
|
||||
std::pair<uint64_t, uint64_t> Session;
|
||||
{
|
||||
std::lock_guard G(CleanupMutex_);
|
||||
Session = CleanupSessions_.front();
|
||||
CleanupSessions_.pop_front();
|
||||
}
|
||||
poco_trace(this->Logger(),fmt::format("Cleaning up session: {} for device: {}", Session.first, Utils::IntToSerialNumber(Session.second)));
|
||||
EndSession(Session.first, Session.second);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AP_WS_Server::run() {
|
||||
uint64_t last_log = Utils::Now(),
|
||||
last_zombie_run = 0,
|
||||
@@ -223,7 +269,6 @@ namespace OpenWifi {
|
||||
try {
|
||||
poco_information(LocalLogger,
|
||||
fmt::format("Garbage collecting zombies... (step 1)"));
|
||||
NumberOfConnectedDevices_ = 0;
|
||||
NumberOfConnectingDevices_ = 0;
|
||||
AverageDeviceConnectionTime_ = 0;
|
||||
int waits = 0;
|
||||
@@ -235,55 +280,49 @@ namespace OpenWifi {
|
||||
waits = 0;
|
||||
auto hint = SerialNumbers_[hashIndex].begin();
|
||||
while (hint != end(SerialNumbers_[hashIndex])) {
|
||||
|
||||
if (hint->second == nullptr) {
|
||||
poco_information(
|
||||
LocalLogger,
|
||||
fmt::format("Dead device found in hash index {}", hashIndex));
|
||||
// hint = SerialNumbers_[hashIndex].erase(hint);
|
||||
hint++;
|
||||
continue;
|
||||
}
|
||||
auto Device = hint->second;
|
||||
if(Device->ConnectionMutex_.try_lock()) {
|
||||
hint = SerialNumbers_[hashIndex].erase(hint);
|
||||
} else {
|
||||
auto Device = hint->second;
|
||||
auto RightNow = Utils::Now();
|
||||
if (RightNow > Device->LastContact_ &&
|
||||
(RightNow - Device->LastContact_) > SessionTimeOut_) {
|
||||
if (Device->Dead_) {
|
||||
AddCleanupSession(Device->State_.sessionId, Device->SerialNumberInt_);
|
||||
++hint;
|
||||
// hint = SerialNumbers_[hashIndex].erase(hint);
|
||||
} else if (RightNow > Device->LastContact_ &&
|
||||
(RightNow - Device->LastContact_) > SessionTimeOut_) {
|
||||
poco_information(
|
||||
LocalLogger,
|
||||
fmt::format("{}: Session seems idle. Controller disconnecting device.",
|
||||
Device->SerialNumber_));
|
||||
hint = SerialNumbers_[hashIndex].erase(hint);
|
||||
} else if (Device->State_.Connected) {
|
||||
NumberOfConnectedDevices_++;
|
||||
total_connected_time +=
|
||||
(RightNow - Device->State_.started);
|
||||
fmt::format(
|
||||
"{}: Session seems idle. Controller disconnecting device.",
|
||||
Device->SerialNumber_));
|
||||
// hint = SerialNumbers_[hashIndex].erase(hint);
|
||||
AddCleanupSession(Device->State_.sessionId, Device->SerialNumberInt_);
|
||||
++hint;
|
||||
} else {
|
||||
if (Device->State_.Connected) {
|
||||
total_connected_time +=
|
||||
(RightNow - Device->State_.started);
|
||||
}
|
||||
++hint;
|
||||
}
|
||||
Device->ConnectionMutex_.unlock();
|
||||
continue;
|
||||
} else {
|
||||
poco_warning(LocalLogger, fmt::format("Could not lock device mutex for {}",
|
||||
Device->SerialNumber_));
|
||||
}
|
||||
++NumberOfConnectingDevices_;
|
||||
++hint;
|
||||
}
|
||||
SerialNumbersMutex_[hashIndex].unlock();
|
||||
break;
|
||||
} else if (waits < 5) {
|
||||
waits++;
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(10));
|
||||
Poco::Thread::trySleep(10);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
poco_information(LocalLogger,
|
||||
fmt::format("Garbage collecting zombies... (step 2)"));
|
||||
poco_information(LocalLogger, fmt::format("Garbage collecting zombies... (step 2)"));
|
||||
LeftOverSessions_ = 0;
|
||||
for (int i = 0; i < SessionHash::HashMax(); i++) {
|
||||
waits = 0;
|
||||
@@ -295,6 +334,10 @@ namespace OpenWifi {
|
||||
while (hint != end(Sessions_[i])) {
|
||||
if (hint->second == nullptr) {
|
||||
hint = Sessions_[i].erase(hint);
|
||||
} else if (hint->second->Dead_) {
|
||||
// hint = Sessions_[i].erase(hint);
|
||||
AddCleanupSession(hint->second->State_.sessionId, hint->second->SerialNumberInt_);
|
||||
++hint;
|
||||
} else if (RightNow > hint->second->LastContact_ &&
|
||||
(RightNow - hint->second->LastContact_) >
|
||||
SessionTimeOut_) {
|
||||
@@ -302,7 +345,9 @@ namespace OpenWifi {
|
||||
LocalLogger,
|
||||
fmt::format("{}: Session seems idle. Controller disconnecting device.",
|
||||
hint->second->SerialNumber_));
|
||||
hint = Sessions_[i].erase(hint);
|
||||
AddCleanupSession(hint->second->State_.sessionId, hint->second->SerialNumberInt_);
|
||||
++hint;
|
||||
// hint = Sessions_[i].erase(hint);
|
||||
} else {
|
||||
++LeftOverSessions_;
|
||||
++hint;
|
||||
@@ -311,7 +356,7 @@ namespace OpenWifi {
|
||||
SessionMutex_[i].unlock();
|
||||
break;
|
||||
} else if (waits < 5) {
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(10));
|
||||
Poco::Thread::trySleep(10);
|
||||
waits++;
|
||||
} else {
|
||||
break;
|
||||
@@ -319,10 +364,9 @@ namespace OpenWifi {
|
||||
}
|
||||
}
|
||||
|
||||
AverageDeviceConnectionTime_ =
|
||||
NumberOfConnectedDevices_ > 0
|
||||
? total_connected_time / NumberOfConnectedDevices_
|
||||
: 0;
|
||||
AverageDeviceConnectionTime_ = NumberOfConnectedDevices_ > 0
|
||||
? total_connected_time / NumberOfConnectedDevices_
|
||||
: 0;
|
||||
poco_information(LocalLogger, fmt::format("Garbage collecting zombies done..."));
|
||||
} catch (const Poco::Exception &E) {
|
||||
poco_error(LocalLogger, fmt::format("Poco::Exception: Garbage collecting zombies failed: {}", E.displayText()));
|
||||
@@ -332,47 +376,49 @@ namespace OpenWifi {
|
||||
poco_error(LocalLogger, fmt::format("exception:Garbage collecting zombies failed: {}", "unknown"));
|
||||
}
|
||||
|
||||
} else {
|
||||
NumberOfConnectedDevices_=0;
|
||||
for(int i=0;i<MACHash::HashMax();i++) {
|
||||
std::lock_guard Lock(SerialNumbersMutex_[i]);
|
||||
NumberOfConnectedDevices_ += SerialNumbers_[i].size();
|
||||
}
|
||||
if(NumberOfConnectedDevices_) {
|
||||
if (last_garbage_run > 0) {
|
||||
AverageDeviceConnectionTime_ += (now - last_garbage_run);
|
||||
}
|
||||
} else {
|
||||
AverageDeviceConnectionTime_ = 0;
|
||||
}
|
||||
|
||||
if(NumberOfConnectedDevices_) {
|
||||
if (last_garbage_run > 0) {
|
||||
AverageDeviceConnectionTime_ += (now - last_garbage_run);
|
||||
}
|
||||
}
|
||||
|
||||
if ((now - last_log) > 60) {
|
||||
last_log = now;
|
||||
poco_information(LocalLogger,
|
||||
fmt::format("Active AP connections: {} Connecting: {} Average connection time: {} seconds. Left Over Sessions: {}",
|
||||
NumberOfConnectedDevices_, NumberOfConnectingDevices_,
|
||||
AverageDeviceConnectionTime_, LeftOverSessions_));
|
||||
try {
|
||||
if ((now - last_log) > 60) {
|
||||
last_log = now;
|
||||
poco_information(
|
||||
LocalLogger,
|
||||
fmt::format("Active AP connections: {} Connecting: {} Average connection time: {} seconds. Left Over Sessions: {}",
|
||||
NumberOfConnectedDevices_, NumberOfConnectingDevices_,
|
||||
AverageDeviceConnectionTime_, LeftOverSessions_));
|
||||
}
|
||||
|
||||
GWWebSocketNotifications::NumberOfConnection_t Notification;
|
||||
Notification.content.numberOfConnectingDevices = NumberOfConnectingDevices_;
|
||||
Notification.content.numberOfDevices = NumberOfConnectedDevices_;
|
||||
Notification.content.averageConnectedTime = AverageDeviceConnectionTime_;
|
||||
GetTotalDataStatistics(Notification.content.tx, Notification.content.rx);
|
||||
GWWebSocketNotifications::NumberOfConnections(Notification);
|
||||
|
||||
Poco::JSON::Object KafkaNotification;
|
||||
Notification.to_json(KafkaNotification);
|
||||
|
||||
Poco::JSON::Object FullEvent;
|
||||
FullEvent.set("type", "load-update");
|
||||
FullEvent.set("timestamp", now);
|
||||
FullEvent.set("payload", KafkaNotification);
|
||||
|
||||
KafkaManager()->PostMessage(KafkaTopics::DEVICE_EVENT_QUEUE, "system", FullEvent);
|
||||
LocalLogger.information(fmt::format("Garbage collection finished run."));
|
||||
last_garbage_run = now;
|
||||
} catch (const Poco::Exception &E) {
|
||||
LocalLogger.error(fmt::format("Poco::Exception: Garbage collecting failed: {}", E.displayText()));
|
||||
} catch (const std::exception &E) {
|
||||
LocalLogger.error(fmt::format("std::exception: Garbage collecting failed: {}", E.what()));
|
||||
} catch (...) {
|
||||
LocalLogger.error(fmt::format("exception:Garbage collecting failed: {}", "unknown"));
|
||||
}
|
||||
|
||||
GWWebSocketNotifications::NumberOfConnection_t Notification;
|
||||
Notification.content.numberOfConnectingDevices = NumberOfConnectingDevices_;
|
||||
Notification.content.numberOfDevices = NumberOfConnectedDevices_;
|
||||
Notification.content.averageConnectedTime = AverageDeviceConnectionTime_;
|
||||
GetTotalDataStatistics(Notification.content.tx,Notification.content.rx);
|
||||
GWWebSocketNotifications::NumberOfConnections(Notification);
|
||||
|
||||
Poco::JSON::Object KafkaNotification;
|
||||
Notification.to_json(KafkaNotification);
|
||||
|
||||
Poco::JSON::Object FullEvent;
|
||||
FullEvent.set("type", "load-update");
|
||||
FullEvent.set("timestamp", now);
|
||||
FullEvent.set("payload", KafkaNotification);
|
||||
|
||||
KafkaManager()->PostMessage(KafkaTopics::DEVICE_EVENT_QUEUE, "system", FullEvent);
|
||||
LocalLogger.information(fmt::format("Garbage collection finished run." ));
|
||||
last_garbage_run = now;
|
||||
}
|
||||
LocalLogger.information(fmt::format("Garbage collector done for the day." ));
|
||||
}
|
||||
@@ -409,15 +455,17 @@ namespace OpenWifi {
|
||||
}
|
||||
|
||||
bool AP_WS_Server::GetStatistics(uint64_t SerialNumber, std::string &Statistics) const {
|
||||
|
||||
auto hashIndex = MACHash::Hash(SerialNumber);
|
||||
std::lock_guard Lock(SerialNumbersMutex_[hashIndex]);
|
||||
auto Device = SerialNumbers_[hashIndex].find(SerialNumber);
|
||||
if (Device == SerialNumbers_[hashIndex].end() || Device->second == nullptr) {
|
||||
return false;
|
||||
std::shared_ptr<AP_WS_Connection> Connection;
|
||||
{
|
||||
auto hashIndex = MACHash::Hash(SerialNumber);
|
||||
std::lock_guard DeviceLock(SerialNumbersMutex_[hashIndex]);
|
||||
auto DeviceHint = SerialNumbers_[hashIndex].find(SerialNumber);
|
||||
if (DeviceHint == SerialNumbers_[hashIndex].end() || DeviceHint->second == nullptr) {
|
||||
return false;
|
||||
}
|
||||
Connection = DeviceHint->second;
|
||||
}
|
||||
Device->second->GetLastStats(Statistics);
|
||||
|
||||
Connection->GetLastStats(Statistics);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -439,49 +487,63 @@ namespace OpenWifi {
|
||||
|
||||
bool AP_WS_Server::GetHealthcheck(uint64_t SerialNumber,
|
||||
GWObjects::HealthCheck &CheckData) const {
|
||||
|
||||
auto hashIndex = MACHash::Hash(SerialNumber);
|
||||
std::lock_guard Lock(SerialNumbersMutex_[hashIndex]);
|
||||
auto Device = SerialNumbers_[hashIndex].find(SerialNumber);
|
||||
if (Device == SerialNumbers_[hashIndex].end() || Device->second == nullptr) {
|
||||
return false;
|
||||
std::shared_ptr<AP_WS_Connection> Connection;
|
||||
{
|
||||
auto hashIndex = MACHash::Hash(SerialNumber);
|
||||
std::lock_guard DeviceLock(SerialNumbersMutex_[hashIndex]);
|
||||
auto Device = SerialNumbers_[hashIndex].find(SerialNumber);
|
||||
if (Device == SerialNumbers_[hashIndex].end() || Device->second == nullptr) {
|
||||
return false;
|
||||
}
|
||||
Connection = Device->second;
|
||||
}
|
||||
Device->second->GetLastHealthCheck(CheckData);
|
||||
Connection->GetLastHealthCheck(CheckData);
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
void AP_WS_Server::StartSession(uint64_t session_id, uint64_t SerialNumber) {
|
||||
auto deviceHash = MACHash::Hash(SerialNumber);
|
||||
auto sessionHash = SessionHash::Hash(session_id);
|
||||
std::lock_guard SessionLock(SessionMutex_[sessionHash]);
|
||||
auto SessionHint = Sessions_[sessionHash].find(session_id);
|
||||
if (SessionHint != end(Sessions_[sessionHash])) {
|
||||
std::lock_guard Lock(SerialNumbersMutex_[deviceHash]);
|
||||
SerialNumbers_[deviceHash][SerialNumber] = SessionHint->second;
|
||||
std::shared_ptr<AP_WS_Connection> Connection;
|
||||
{
|
||||
std::lock_guard SessionLock(SessionMutex_[sessionHash]);
|
||||
auto SessionHint = Sessions_[sessionHash].find(session_id);
|
||||
if (SessionHint == end(Sessions_[sessionHash])) {
|
||||
return;
|
||||
}
|
||||
Connection = SessionHint->second;
|
||||
Sessions_[sessionHash].erase(SessionHint);
|
||||
} else {
|
||||
poco_error(Logger(), fmt::format("StartSession: Could not find session '{}'", session_id));
|
||||
}
|
||||
|
||||
auto deviceHash = MACHash::Hash(SerialNumber);
|
||||
std::lock_guard DeviceLock(SerialNumbersMutex_[deviceHash]);
|
||||
SerialNumbers_[deviceHash][SerialNumber] = Connection;
|
||||
}
|
||||
|
||||
bool AP_WS_Server::EndSession(uint64_t session_id, uint64_t SerialNumber) {
|
||||
{
|
||||
poco_trace(Logger(), fmt::format("Ending session 1: {} for device: {}", session_id, Utils::IntToSerialNumber(SerialNumber)));
|
||||
auto sessionHash = SessionHash::Hash(session_id);
|
||||
std::lock_guard SessionLock(SessionMutex_[sessionHash]);
|
||||
Sessions_[sessionHash].erase(session_id);
|
||||
poco_trace(Logger(), fmt::format("Ended session 1: {} for device: {}", session_id, Utils::IntToSerialNumber(SerialNumber)));
|
||||
}
|
||||
|
||||
{
|
||||
auto hashIndex = MACHash::Hash(SerialNumber);
|
||||
poco_trace(Logger(), fmt::format("Ending session 2.0: {} for device: {} hi:{}", session_id, Utils::IntToSerialNumber(SerialNumber), hashIndex));
|
||||
std::lock_guard DeviceLock(SerialNumbersMutex_[hashIndex]);
|
||||
poco_trace(Logger(), fmt::format("Ending session 2.1: {} for device: {} hi:{}", session_id, Utils::IntToSerialNumber(SerialNumber), hashIndex));
|
||||
auto DeviceHint = SerialNumbers_[hashIndex].find(SerialNumber);
|
||||
poco_trace(Logger(), fmt::format("Ending session 2.2: {} for device: {} hi:{}", session_id, Utils::IntToSerialNumber(SerialNumber), hashIndex));
|
||||
if (DeviceHint == SerialNumbers_[hashIndex].end()
|
||||
|| DeviceHint->second == nullptr
|
||||
|| DeviceHint->second->State_.sessionId != session_id) {
|
||||
poco_trace(Logger(), fmt::format("Did not end session 2: {} for device: {}", session_id, Utils::IntToSerialNumber(SerialNumber)));
|
||||
return false;
|
||||
}
|
||||
SerialNumbers_[hashIndex].erase(DeviceHint);
|
||||
poco_trace(Logger(), fmt::format("Ended session 2: {} for device: {}", session_id, Utils::IntToSerialNumber(SerialNumber)));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -489,47 +551,62 @@ namespace OpenWifi {
|
||||
|
||||
bool AP_WS_Server::Connected(uint64_t SerialNumber,
|
||||
GWObjects::DeviceRestrictions &Restrictions) const {
|
||||
auto hashIndex = MACHash::Hash(SerialNumber);
|
||||
std::lock_guard DeviceLock(SerialNumbersMutex_[hashIndex]);
|
||||
auto DeviceHint = SerialNumbers_[hashIndex].find(SerialNumber);
|
||||
if (DeviceHint == end(SerialNumbers_[hashIndex]) || DeviceHint->second == nullptr) {
|
||||
std::shared_ptr<AP_WS_Connection> Connection;
|
||||
{
|
||||
auto hashIndex = MACHash::Hash(SerialNumber);
|
||||
std::lock_guard DeviceLock(SerialNumbersMutex_[hashIndex]);
|
||||
auto DeviceHint = SerialNumbers_[hashIndex].find(SerialNumber);
|
||||
if (DeviceHint == end(SerialNumbers_[hashIndex]) || DeviceHint->second == nullptr) {
|
||||
return false;
|
||||
}
|
||||
Connection = DeviceHint->second;
|
||||
}
|
||||
|
||||
if(Connection->Dead_) {
|
||||
return false;
|
||||
}
|
||||
if(!DeviceHint->second->Dead_) {
|
||||
DeviceHint->second->GetRestrictions(Restrictions);
|
||||
return DeviceHint->second->State_.Connected;
|
||||
}
|
||||
return false;
|
||||
Restrictions = Connection->GetRestrictions();
|
||||
return Connection->State_.Connected;
|
||||
}
|
||||
|
||||
|
||||
bool AP_WS_Server::Connected(uint64_t SerialNumber) const {
|
||||
auto hashIndex = MACHash::Hash(SerialNumber);
|
||||
std::lock_guard Lock(SerialNumbersMutex_[hashIndex]);
|
||||
auto DeviceHint = SerialNumbers_[hashIndex].find(SerialNumber);
|
||||
if (DeviceHint == end(SerialNumbers_[hashIndex]) || DeviceHint->second == nullptr) {
|
||||
std::shared_ptr<AP_WS_Connection> Connection;
|
||||
{
|
||||
auto hashIndex = MACHash::Hash(SerialNumber);
|
||||
std::lock_guard DeviceLock(SerialNumbersMutex_[hashIndex]);
|
||||
auto DeviceHint = SerialNumbers_[hashIndex].find(SerialNumber);
|
||||
if (DeviceHint == end(SerialNumbers_[hashIndex]) || DeviceHint->second == nullptr) {
|
||||
return false;
|
||||
}
|
||||
Connection = DeviceHint->second;
|
||||
}
|
||||
|
||||
if(Connection->Dead_) {
|
||||
return false;
|
||||
}
|
||||
if(!DeviceHint->second->Dead_) {
|
||||
return DeviceHint->second->State_.Connected;
|
||||
}
|
||||
return false;
|
||||
return Connection->State_.Connected;
|
||||
}
|
||||
|
||||
bool AP_WS_Server::SendFrame(uint64_t SerialNumber, const std::string &Payload) const {
|
||||
auto hashIndex = MACHash::Hash(SerialNumber);
|
||||
std::lock_guard Lock(SerialNumbersMutex_[hashIndex]);
|
||||
auto DeviceHint = SerialNumbers_[hashIndex].find(SerialNumber);
|
||||
if (DeviceHint == end(SerialNumbers_[hashIndex]) || DeviceHint->second == nullptr) {
|
||||
return false;
|
||||
|
||||
std::shared_ptr<AP_WS_Connection> Connection;
|
||||
{
|
||||
std::lock_guard DeviceLock(SerialNumbersMutex_[hashIndex]);
|
||||
auto DeviceHint = SerialNumbers_[hashIndex].find(SerialNumber);
|
||||
if (DeviceHint == end(SerialNumbers_[hashIndex]) || DeviceHint->second == nullptr) {
|
||||
return false;
|
||||
}
|
||||
Connection = DeviceHint->second;
|
||||
}
|
||||
|
||||
if(DeviceHint->second->Dead_) {
|
||||
if(Connection->Dead_) {
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
return DeviceHint->second->Send(Payload);
|
||||
return Connection->Send(Payload);
|
||||
} catch (...) {
|
||||
poco_debug(Logger(), fmt::format(": SendFrame: Could not send data to device '{}'",
|
||||
Utils::IntToSerialNumber(SerialNumber)));
|
||||
@@ -538,48 +615,64 @@ namespace OpenWifi {
|
||||
}
|
||||
|
||||
void AP_WS_Server::StopWebSocketTelemetry(uint64_t RPCID, uint64_t SerialNumber) {
|
||||
auto hashIndex = MACHash::Hash(SerialNumber);
|
||||
std::lock_guard Lock(SerialNumbersMutex_[hashIndex]);
|
||||
auto Device = SerialNumbers_[hashIndex].find(SerialNumber);
|
||||
if (Device == end(SerialNumbers_[hashIndex]) || Device->second == nullptr) {
|
||||
return;
|
||||
std::shared_ptr<AP_WS_Connection> Connection;
|
||||
{
|
||||
auto hashIndex = MACHash::Hash(SerialNumber);
|
||||
std::lock_guard DeviceLock(SerialNumbersMutex_[hashIndex]);
|
||||
auto Device = SerialNumbers_[hashIndex].find(SerialNumber);
|
||||
if (Device == end(SerialNumbers_[hashIndex]) || Device->second == nullptr) {
|
||||
return;
|
||||
}
|
||||
Connection = Device->second;
|
||||
}
|
||||
Device->second->StopWebSocketTelemetry(RPCID);
|
||||
Connection->StopWebSocketTelemetry(RPCID);
|
||||
}
|
||||
|
||||
void
|
||||
AP_WS_Server::SetWebSocketTelemetryReporting(uint64_t RPCID, uint64_t SerialNumber,
|
||||
uint64_t Interval, uint64_t Lifetime,
|
||||
const std::vector<std::string> &TelemetryTypes) {
|
||||
auto hashIndex = MACHash::Hash(SerialNumber);
|
||||
std::lock_guard DeviceLock(SerialNumbersMutex_[hashIndex]);
|
||||
auto DeviceHint = SerialNumbers_[hashIndex].find(SerialNumber);
|
||||
if (DeviceHint == end(SerialNumbers_[hashIndex]) || DeviceHint->second == nullptr) {
|
||||
return;
|
||||
std::shared_ptr<AP_WS_Connection> Connection;
|
||||
{
|
||||
auto hashIndex = MACHash::Hash(SerialNumber);
|
||||
std::lock_guard DeviceLock(SerialNumbersMutex_[hashIndex]);
|
||||
auto DeviceHint = SerialNumbers_[hashIndex].find(SerialNumber);
|
||||
if (DeviceHint == end(SerialNumbers_[hashIndex]) || DeviceHint->second == nullptr) {
|
||||
return;
|
||||
}
|
||||
Connection = DeviceHint->second;
|
||||
}
|
||||
DeviceHint->second->SetWebSocketTelemetryReporting(RPCID, Interval, Lifetime, TelemetryTypes);
|
||||
Connection->SetWebSocketTelemetryReporting(RPCID, Interval, Lifetime, TelemetryTypes);
|
||||
}
|
||||
|
||||
void AP_WS_Server::SetKafkaTelemetryReporting(uint64_t RPCID, uint64_t SerialNumber,
|
||||
uint64_t Interval, uint64_t Lifetime,
|
||||
const std::vector<std::string> &TelemetryTypes) {
|
||||
auto hashIndex = MACHash::Hash(SerialNumber);
|
||||
std::lock_guard Lock(SerialNumbersMutex_[hashIndex]);
|
||||
auto DeviceHint = SerialNumbers_[hashIndex].find(SerialNumber);
|
||||
if (DeviceHint == end(SerialNumbers_[hashIndex]) || DeviceHint->second == nullptr) {
|
||||
return;
|
||||
std::shared_ptr<AP_WS_Connection> Connection;
|
||||
{
|
||||
auto hashIndex = MACHash::Hash(SerialNumber);
|
||||
std::lock_guard DeviceLock(SerialNumbersMutex_[hashIndex]);
|
||||
auto DeviceHint = SerialNumbers_[hashIndex].find(SerialNumber);
|
||||
if (DeviceHint == end(SerialNumbers_[hashIndex]) || DeviceHint->second == nullptr) {
|
||||
return;
|
||||
}
|
||||
Connection = DeviceHint->second;
|
||||
}
|
||||
DeviceHint->second->SetKafkaTelemetryReporting(RPCID, Interval, Lifetime, TelemetryTypes);
|
||||
Connection->SetKafkaTelemetryReporting(RPCID, Interval, Lifetime, TelemetryTypes);
|
||||
}
|
||||
|
||||
void AP_WS_Server::StopKafkaTelemetry(uint64_t RPCID, uint64_t SerialNumber) {
|
||||
auto hashIndex = MACHash::Hash(SerialNumber);
|
||||
std::lock_guard DevicesLock(SerialNumbersMutex_[hashIndex]);
|
||||
auto DeviceHint = SerialNumbers_[hashIndex].find(SerialNumber);
|
||||
if (DeviceHint == end(SerialNumbers_[hashIndex]) || DeviceHint->second == nullptr) {
|
||||
return;
|
||||
std::shared_ptr<AP_WS_Connection> Connection;
|
||||
{
|
||||
auto hashIndex = MACHash::Hash(SerialNumber);
|
||||
std::lock_guard DevicesLock(SerialNumbersMutex_[hashIndex]);
|
||||
auto DeviceHint = SerialNumbers_[hashIndex].find(SerialNumber);
|
||||
if (DeviceHint == end(SerialNumbers_[hashIndex]) || DeviceHint->second == nullptr) {
|
||||
return;
|
||||
}
|
||||
Connection = DeviceHint->second;
|
||||
}
|
||||
DeviceHint->second->StopKafkaTelemetry(RPCID);
|
||||
Connection->StopKafkaTelemetry(RPCID);
|
||||
}
|
||||
|
||||
void AP_WS_Server::GetTelemetryParameters(
|
||||
@@ -588,14 +681,18 @@ namespace OpenWifi {
|
||||
uint64_t &TelemetryWebSocketCount, uint64_t &TelemetryKafkaCount,
|
||||
uint64_t &TelemetryWebSocketPackets, uint64_t &TelemetryKafkaPackets) {
|
||||
|
||||
auto hashIndex = MACHash::Hash(SerialNumber);
|
||||
std::lock_guard DevicesLock(SerialNumbersMutex_[hashIndex]);
|
||||
auto DeviceHint = SerialNumbers_[hashIndex].find(SerialNumber);
|
||||
if (DeviceHint == end(SerialNumbers_[hashIndex]) || DeviceHint->second == nullptr) {
|
||||
return;
|
||||
std::shared_ptr<AP_WS_Connection> Connection;
|
||||
{
|
||||
auto hashIndex = MACHash::Hash(SerialNumber);
|
||||
std::lock_guard DevicesLock(SerialNumbersMutex_[hashIndex]);
|
||||
auto DeviceHint = SerialNumbers_[hashIndex].find(SerialNumber);
|
||||
if (DeviceHint == end(SerialNumbers_[hashIndex]) || DeviceHint->second == nullptr) {
|
||||
return;
|
||||
}
|
||||
Connection = DeviceHint->second;
|
||||
}
|
||||
|
||||
DeviceHint->second->GetTelemetryParameters(TelemetryRunning, TelemetryInterval,
|
||||
Connection->GetTelemetryParameters(TelemetryRunning, TelemetryInterval,
|
||||
TelemetryWebSocketTimer, TelemetryKafkaTimer,
|
||||
TelemetryWebSocketCount, TelemetryKafkaCount,
|
||||
TelemetryWebSocketPackets, TelemetryKafkaPackets);
|
||||
@@ -604,20 +701,24 @@ namespace OpenWifi {
|
||||
bool AP_WS_Server::SendRadiusAccountingData(const std::string &SerialNumber,
|
||||
const unsigned char *buffer, std::size_t size) {
|
||||
|
||||
auto IntSerialNumber = Utils::SerialNumberToInt(SerialNumber);
|
||||
auto hashIndex = MACHash::Hash(IntSerialNumber);
|
||||
std::lock_guard DevicesLock(SerialNumbersMutex_[hashIndex]);
|
||||
auto DeviceHint = SerialNumbers_[hashIndex].find(IntSerialNumber);
|
||||
if (DeviceHint == end(SerialNumbers_[hashIndex]) || DeviceHint->second == nullptr) {
|
||||
return false;
|
||||
std::shared_ptr<AP_WS_Connection> Connection;
|
||||
{
|
||||
auto IntSerialNumber = Utils::SerialNumberToInt(SerialNumber);
|
||||
auto hashIndex = MACHash::Hash(IntSerialNumber);
|
||||
std::lock_guard DevicesLock(SerialNumbersMutex_[hashIndex]);
|
||||
auto DeviceHint = SerialNumbers_[hashIndex].find(IntSerialNumber);
|
||||
if (DeviceHint == end(SerialNumbers_[hashIndex]) || DeviceHint->second == nullptr) {
|
||||
return false;
|
||||
}
|
||||
Connection = DeviceHint->second;
|
||||
}
|
||||
|
||||
if(DeviceHint->second->Dead_) {
|
||||
if(Connection->Dead_) {
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
return DeviceHint->second->SendRadiusAccountingData(buffer, size);
|
||||
return Connection->SendRadiusAccountingData(buffer, size);
|
||||
} catch (...) {
|
||||
poco_debug(
|
||||
Logger(),
|
||||
@@ -629,20 +730,24 @@ namespace OpenWifi {
|
||||
|
||||
bool AP_WS_Server::SendRadiusAuthenticationData(const std::string &SerialNumber,
|
||||
const unsigned char *buffer, std::size_t size) {
|
||||
auto IntSerialNumber = Utils::SerialNumberToInt(SerialNumber);
|
||||
auto hashIndex = MACHash::Hash(IntSerialNumber);
|
||||
std::lock_guard DevicesLock(SerialNumbersMutex_[hashIndex]);
|
||||
auto DeviceHint = SerialNumbers_[hashIndex].find(IntSerialNumber);
|
||||
if (DeviceHint == end(SerialNumbers_[hashIndex]) || DeviceHint->second == nullptr) {
|
||||
return false;
|
||||
std::shared_ptr<AP_WS_Connection> Connection;
|
||||
{
|
||||
auto IntSerialNumber = Utils::SerialNumberToInt(SerialNumber);
|
||||
auto hashIndex = MACHash::Hash(IntSerialNumber);
|
||||
std::lock_guard DevicesLock(SerialNumbersMutex_[hashIndex]);
|
||||
auto DeviceHint = SerialNumbers_[hashIndex].find(IntSerialNumber);
|
||||
if (DeviceHint == end(SerialNumbers_[hashIndex]) || DeviceHint->second == nullptr) {
|
||||
return false;
|
||||
}
|
||||
Connection = DeviceHint->second;
|
||||
}
|
||||
|
||||
if(DeviceHint->second->Dead_) {
|
||||
if(Connection->Dead_) {
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
return DeviceHint->second->SendRadiusAuthenticationData(buffer, size);
|
||||
return Connection->SendRadiusAuthenticationData(buffer, size);
|
||||
} catch (...) {
|
||||
poco_debug(
|
||||
Logger(),
|
||||
@@ -654,19 +759,23 @@ namespace OpenWifi {
|
||||
|
||||
bool AP_WS_Server::SendRadiusCoAData(const std::string &SerialNumber,
|
||||
const unsigned char *buffer, std::size_t size) {
|
||||
auto IntSerialNumber = Utils::SerialNumberToInt(SerialNumber);
|
||||
auto hashIndex = MACHash::Hash(IntSerialNumber);
|
||||
std::lock_guard DevicesGuard(SerialNumbersMutex_[hashIndex]);
|
||||
auto DeviceHint = SerialNumbers_[hashIndex].find(IntSerialNumber);
|
||||
if (DeviceHint == end(SerialNumbers_[hashIndex]) || DeviceHint->second == nullptr) {
|
||||
return false;
|
||||
std::shared_ptr<AP_WS_Connection> Connection;
|
||||
{
|
||||
auto IntSerialNumber = Utils::SerialNumberToInt(SerialNumber);
|
||||
auto hashIndex = MACHash::Hash(IntSerialNumber);
|
||||
std::lock_guard DeviceLock(SerialNumbersMutex_[hashIndex]);
|
||||
auto DeviceHint = SerialNumbers_[hashIndex].find(IntSerialNumber);
|
||||
if (DeviceHint == end(SerialNumbers_[hashIndex]) || DeviceHint->second == nullptr) {
|
||||
return false;
|
||||
}
|
||||
Connection = DeviceHint->second;
|
||||
}
|
||||
|
||||
if(DeviceHint->second->Dead_) {
|
||||
if(Connection->Dead_) {
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
return DeviceHint->second->SendRadiusCoAData(buffer, size);
|
||||
return Connection->SendRadiusCoAData(buffer, size);
|
||||
} catch (...) {
|
||||
poco_debug(Logger(),
|
||||
fmt::format(": SendRadiusCoAData: Could not send data to device '{}'",
|
||||
@@ -675,32 +784,4 @@ namespace OpenWifi {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool AP_WS_Server::ExtendedAttributes(const std::string &serialNumber,
|
||||
bool & hasGPS,
|
||||
std::uint64_t &Sanity,
|
||||
std::double_t &MemoryUsed,
|
||||
std::double_t &Load,
|
||||
std::double_t &Temperature
|
||||
) {
|
||||
|
||||
auto serialNumberInt = Utils::SerialNumberToInt(serialNumber);
|
||||
auto hashIndex = MACHash::Hash(serialNumberInt);
|
||||
std::lock_guard DevicesGuard(SerialNumbersMutex_[hashIndex]);
|
||||
auto DeviceHint = SerialNumbers_[hashIndex].find(Utils::SerialNumberToInt(serialNumber));
|
||||
if(DeviceHint==end(SerialNumbers_[hashIndex])) {
|
||||
return false;
|
||||
}
|
||||
if(DeviceHint->second->Dead_) {
|
||||
return false;
|
||||
}
|
||||
std::lock_guard DeviceGuard(DeviceHint->second->ConnectionMutex_);
|
||||
hasGPS = DeviceHint->second->hasGPS_;
|
||||
Sanity = DeviceHint->second->RawLastHealthcheck_.Sanity;
|
||||
MemoryUsed = DeviceHint->second->memory_used_;
|
||||
Load = DeviceHint->second->cpu_load_;
|
||||
Temperature = DeviceHint->second->temperature_;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
} // namespace OpenWifi
|
||||
@@ -103,20 +103,23 @@ namespace OpenWifi {
|
||||
|
||||
inline void AddConnection(std::shared_ptr<AP_WS_Connection> Connection) {
|
||||
std::uint64_t sessionHash = SessionHash::Hash(Connection->State_.sessionId);
|
||||
std::lock_guard Lock(SessionMutex_[sessionHash]);
|
||||
std::lock_guard SessionLock(SessionMutex_[sessionHash]);
|
||||
if(Sessions_[sessionHash].find(Connection->State_.sessionId)==end(Sessions_[sessionHash])) {
|
||||
Sessions_[sessionHash][Connection->State_.sessionId] = std::move(Connection);
|
||||
}
|
||||
}
|
||||
|
||||
[[nodiscard]] inline bool DeviceRequiresSecureRTTY(uint64_t serialNumber) const {
|
||||
auto hashIndex = MACHash::Hash(serialNumber);
|
||||
std::lock_guard G(SerialNumbersMutex_[hashIndex]);
|
||||
|
||||
auto Connection = SerialNumbers_[hashIndex].find(serialNumber);
|
||||
if (Connection==end(SerialNumbers_[hashIndex]) || Connection->second==nullptr)
|
||||
return false;
|
||||
return Connection->second->RTTYMustBeSecure_;
|
||||
std::shared_ptr<AP_WS_Connection> Connection;
|
||||
{
|
||||
auto hashIndex = MACHash::Hash(serialNumber);
|
||||
std::lock_guard DeviceLock(SerialNumbersMutex_[hashIndex]);
|
||||
auto DeviceHint = SerialNumbers_[hashIndex].find(serialNumber);
|
||||
if (DeviceHint == end(SerialNumbers_[hashIndex]) || DeviceHint->second == nullptr)
|
||||
return false;
|
||||
Connection = DeviceHint->second;
|
||||
}
|
||||
return Connection->RTTYMustBeSecure_;
|
||||
}
|
||||
|
||||
inline bool GetStatistics(const std::string &SerialNumber, std::string &Statistics) const {
|
||||
@@ -138,6 +141,7 @@ namespace OpenWifi {
|
||||
|
||||
bool Connected(uint64_t SerialNumber, GWObjects::DeviceRestrictions &Restrictions) const;
|
||||
bool Connected(uint64_t SerialNumber) const;
|
||||
bool Disconnect(uint64_t SerialNumber);
|
||||
bool SendFrame(uint64_t SerialNumber, const std::string &Payload) const;
|
||||
bool SendRadiusAuthenticationData(const std::string &SerialNumber,
|
||||
const unsigned char *buffer, std::size_t size);
|
||||
@@ -165,8 +169,8 @@ namespace OpenWifi {
|
||||
uint64_t &TelemetryKafkaPackets);
|
||||
|
||||
bool GetHealthDevices(std::uint64_t lowLimit, std::uint64_t highLimit, std::vector<std::string> & SerialNumbers);
|
||||
bool ExtendedAttributes(const std::string &serialNumber, bool & hasGPS, std::uint64_t &Sanity,
|
||||
std::double_t &MemoryUsed, std::double_t &Load, std::double_t &Temperature);
|
||||
// bool ExtendedAttributes(const std::string &serialNumber, bool & hasGPS, std::uint64_t &Sanity,
|
||||
// std::double_t &MemoryUsed, std::double_t &Load, std::double_t &Temperature);
|
||||
|
||||
inline void AverageDeviceStatistics(uint64_t &Connections, uint64_t &AverageConnectionTime,
|
||||
uint64_t &NumberOfConnectingDevices) const {
|
||||
@@ -195,13 +199,28 @@ namespace OpenWifi {
|
||||
bool KafkaDisableState() const { return KafkaDisableState_; }
|
||||
bool KafkaDisableHealthChecks() const { return KafkaDisableHealthChecks_; }
|
||||
|
||||
inline void IncrementConnectionCount() {
|
||||
++NumberOfConnectedDevices_;
|
||||
}
|
||||
|
||||
inline void DecrementConnectionCount() {
|
||||
--NumberOfConnectedDevices_;
|
||||
}
|
||||
|
||||
inline void AddCleanupSession(uint64_t session_id, uint64_t SerialNumber) {
|
||||
std::lock_guard G(CleanupMutex_);
|
||||
CleanupSessions_.emplace_back(session_id, SerialNumber);
|
||||
}
|
||||
|
||||
void CleanupSessions();
|
||||
|
||||
private:
|
||||
std::array<std::mutex,SessionHashMax> SessionMutex_;
|
||||
std::array<std::map<std::uint64_t, std::shared_ptr<AP_WS_Connection>>,SessionHashMax> Sessions_;
|
||||
using SerialNumberMap = std::map<uint64_t /* serial number */,
|
||||
std::shared_ptr<AP_WS_Connection>>;
|
||||
std::array<SerialNumberMap,MACHashMax> SerialNumbers_;
|
||||
mutable std::array<std::recursive_mutex,MACHashMax> SerialNumbersMutex_;
|
||||
mutable std::array<std::mutex,MACHashMax> SerialNumbersMutex_;
|
||||
|
||||
std::unique_ptr<Poco::Crypto::X509Certificate> IssuerCert_;
|
||||
std::list<std::unique_ptr<Poco::Net::HTTPServer>> WebServers_;
|
||||
@@ -214,12 +233,17 @@ namespace OpenWifi {
|
||||
bool SimulatorEnabled_ = false;
|
||||
bool AllowSerialNumberMismatch_ = true;
|
||||
|
||||
Poco::Thread CleanupThread_;
|
||||
std::mutex CleanupMutex_;
|
||||
std::deque<std::pair<uint64_t, uint64_t>> CleanupSessions_;
|
||||
|
||||
std::unique_ptr<AP_WS_ReactorThreadPool> Reactor_pool_;
|
||||
std::atomic_bool Running_ = false;
|
||||
|
||||
std::uint64_t MismatchDepth_ = 2;
|
||||
std::uint64_t NumberOfConnectedDevices_ = 0;
|
||||
std::uint64_t AverageDeviceConnectionTime_ = 0;
|
||||
|
||||
std::atomic_uint64_t NumberOfConnectedDevices_ = 0;
|
||||
std::atomic_uint64_t AverageDeviceConnectionTime_ = 0;
|
||||
std::uint64_t NumberOfConnectingDevices_ = 0;
|
||||
std::uint64_t SessionTimeOut_ = 10*60;
|
||||
std::uint64_t LeftOverSessions_ = 0;
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include <string>
|
||||
|
||||
#include "framework/MicroServiceFuncs.h"
|
||||
#include "framework/ow_constants.h"
|
||||
|
||||
#include "CentralConfig.h"
|
||||
#include "nlohmann/json.hpp"
|
||||
@@ -34,7 +35,7 @@ namespace OpenWifi {
|
||||
std::lock_guard G(Mutex_);
|
||||
if (!PlatformsLoaded_)
|
||||
LoadPlatforms();
|
||||
auto P = Poco::toUpper(Caps.Platform());
|
||||
auto P = Poco::toLower(Caps.Platform());
|
||||
auto Hint = Platforms_.find(Caps.Compatible());
|
||||
if (Hint == Platforms_.end()) {
|
||||
Platforms_.insert(std::make_pair(Caps.Compatible(), P));
|
||||
@@ -68,7 +69,7 @@ namespace OpenWifi {
|
||||
|
||||
auto Hint = Platforms_.find(DeviceType);
|
||||
if (Hint == Platforms_.end())
|
||||
return "AP";
|
||||
return Platforms::AP;
|
||||
return Hint->second;
|
||||
}
|
||||
|
||||
@@ -110,7 +111,7 @@ namespace OpenWifi {
|
||||
i >> cache;
|
||||
|
||||
for (const auto &[Type, Platform] : cache.items()) {
|
||||
Platforms_[Type] = Platform;
|
||||
Platforms_[Type] = Poco::toLower(to_string(Platform));
|
||||
}
|
||||
} catch (...) {
|
||||
}
|
||||
|
||||
@@ -204,6 +204,17 @@ namespace OpenWifi::Config {
|
||||
return false;
|
||||
}
|
||||
|
||||
std::uint64_t Config::UUID() {
|
||||
try {
|
||||
Poco::JSON::Parser Parser;
|
||||
auto object = Parser.parse(Config_).extract<Poco::JSON::Object::Ptr>();
|
||||
if (object->has("uuid"))
|
||||
return object->get("uuid");
|
||||
} catch (...) {
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool Config::Valid() {
|
||||
try {
|
||||
Poco::JSON::Parser Parser;
|
||||
@@ -254,7 +265,11 @@ namespace OpenWifi::Config {
|
||||
Model_ = Caps->get("model").toString();
|
||||
|
||||
if (Caps->has("platform"))
|
||||
Platform_ = Caps->get("platform").toString();
|
||||
Platform_ = Poco::toLower(Caps->get("platform").toString());
|
||||
|
||||
if(Compatible_.empty()) {
|
||||
Compatible_ = Model_;
|
||||
}
|
||||
|
||||
std::ostringstream OS;
|
||||
Caps->stringify(OS);
|
||||
|
||||
@@ -23,6 +23,7 @@ namespace OpenWifi::Config {
|
||||
[[nodiscard]] std::string get() { return Config_; };
|
||||
[[nodiscard]] std::string Default();
|
||||
[[nodiscard]] Poco::JSON::Object::Ptr to_json();
|
||||
[[nodiscard]] std::uint64_t UUID();
|
||||
|
||||
private:
|
||||
void Init();
|
||||
|
||||
@@ -11,12 +11,12 @@
|
||||
namespace OpenWifi {
|
||||
class ConfigurationCache {
|
||||
public:
|
||||
static ConfigurationCache &instance() {
|
||||
static ConfigurationCache instance;
|
||||
static auto instance() {
|
||||
static auto instance = new ConfigurationCache;
|
||||
return instance;
|
||||
}
|
||||
|
||||
inline uint64_t CurrentConfig(uint64_t SerialNumber) {
|
||||
inline uint64_t GetCurrentConfig(std::uint64_t SerialNumber) {
|
||||
std::lock_guard G(Mutex_);
|
||||
const auto Hint = Cache_.find(SerialNumber);
|
||||
if (Hint == end(Cache_))
|
||||
@@ -24,25 +24,25 @@ namespace OpenWifi {
|
||||
return Hint->second;
|
||||
}
|
||||
|
||||
inline void Add(uint64_t SerialNumber, uint64_t Id) {
|
||||
inline void SetCurrentConfig(std::uint64_t SerialNumber, uint64_t Id) {
|
||||
std::lock_guard G(Mutex_);
|
||||
Cache_[SerialNumber] = Id;
|
||||
}
|
||||
|
||||
private:
|
||||
std::recursive_mutex Mutex_;
|
||||
std::mutex Mutex_;
|
||||
std::map<uint64_t, uint64_t> Cache_;
|
||||
};
|
||||
|
||||
inline uint64_t GetCurrentConfigurationID(uint64_t SerialNumber) {
|
||||
return ConfigurationCache::instance().CurrentConfig(SerialNumber);
|
||||
inline auto GetCurrentConfigurationID(std::uint64_t SerialNumber) {
|
||||
return ConfigurationCache::instance()->GetCurrentConfig(SerialNumber);
|
||||
}
|
||||
|
||||
inline void SetCurrentConfigurationID(const std::string &SerialNumber, uint64_t ID) {
|
||||
return ConfigurationCache::instance().Add(Utils::SerialNumberToInt(SerialNumber), ID);
|
||||
inline void SetCurrentConfigurationID(const std::string &SerialNumber, std::uint64_t ID) {
|
||||
return ConfigurationCache::instance()->SetCurrentConfig(Utils::SerialNumberToInt(SerialNumber), ID);
|
||||
}
|
||||
|
||||
inline void SetCurrentConfigurationID(uint64_t SerialNumber, uint64_t ID) {
|
||||
return ConfigurationCache::instance().Add(SerialNumber, ID);
|
||||
inline void SetCurrentConfigurationID(uint64_t SerialNumber, std::uint64_t ID) {
|
||||
return ConfigurationCache::instance()->SetCurrentConfig(SerialNumber, ID);
|
||||
}
|
||||
} // namespace OpenWifi
|
||||
|
||||
@@ -49,7 +49,7 @@ namespace OpenWifi {
|
||||
SignatureManager(), AP_WS_Server(),
|
||||
RegulatoryInfo(),
|
||||
RADIUSSessionTracker(),
|
||||
AP_WS_ConfigAutoUpgrader(),
|
||||
AP_WS_ConfigAutoUpgradeAgent(),
|
||||
FirmwareRevisionCache()
|
||||
});
|
||||
return &instance;
|
||||
@@ -78,7 +78,7 @@ namespace OpenWifi {
|
||||
if (Id == DeviceType)
|
||||
return Type;
|
||||
}
|
||||
return "AP";
|
||||
return Platforms::AP;
|
||||
}
|
||||
|
||||
void DaemonPostInitialization(Poco::Util::Application &self) {
|
||||
|
||||
@@ -8,12 +8,12 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Poco/Net/HTTPRequestHandler.h"
|
||||
#include "Poco/Net/HTTPRequestHandlerFactory.h"
|
||||
#include "Poco/Net/HTTPServer.h"
|
||||
#include "Poco/Net/HTTPServerRequest.h"
|
||||
#include <Poco/Net/HTTPRequestHandler.h>
|
||||
#include <Poco/Net/HTTPRequestHandlerFactory.h>
|
||||
#include <Poco/Net/HTTPServer.h>
|
||||
#include <Poco/Net/HTTPServerRequest.h>
|
||||
|
||||
#include "framework/SubSystemServer.h"
|
||||
#include <framework/SubSystemServer.h>
|
||||
|
||||
namespace OpenWifi {
|
||||
|
||||
|
||||
@@ -50,12 +50,22 @@ namespace OpenWifi {
|
||||
class DeviceConfigurationChangeKafkaEvent : public GWKafkaEvents {
|
||||
public:
|
||||
DeviceConfigurationChangeKafkaEvent(std::uint64_t serialNumber,
|
||||
std::uint64_t timestamp, const Poco::JSON::Object::Ptr config)
|
||||
std::uint64_t timestamp,
|
||||
const Poco::JSON::Object::Ptr config)
|
||||
: GWKafkaEvents(serialNumber, "unit.configuration_change", timestamp), config_(config) {
|
||||
}
|
||||
|
||||
~DeviceConfigurationChangeKafkaEvent() {
|
||||
payload_->set("configuration", *config_);
|
||||
if(config_!= nullptr) {
|
||||
std::ostringstream os;
|
||||
config_->stringify(os);
|
||||
if(os.str().size()> KafkaManager()->KafkaManagerMaximumPayloadSize()) {
|
||||
payload_->set("configuration", "{}");
|
||||
payload_->set("configurationTooBig", true);
|
||||
} else {
|
||||
payload_->set("configuration", *config_);
|
||||
}
|
||||
}
|
||||
Send();
|
||||
}
|
||||
|
||||
|
||||
@@ -75,8 +75,10 @@ namespace OpenWifi {
|
||||
} else if ((Utils::Now() - LastKeepAlive) > Pool_.radsecKeepAlive) {
|
||||
RADIUS::RadiusOutputPacket P(Pool_.authConfig.servers[ServerIndex_].radsecSecret);
|
||||
P.MakeStatusMessage(Pool_.authConfig.servers[ServerIndex_].name);
|
||||
poco_trace(Logger_, fmt::format("{}: Keep-Alive message.", Pool_.authConfig.servers[ServerIndex_].name));
|
||||
Socket_->sendBytes(P.Data(), P.Len());
|
||||
if(Type_!=GWObjects::RadiusEndpointType::generic) {
|
||||
poco_trace(Logger_, fmt::format("{}: Keep-Alive message.", Pool_.authConfig.servers[ServerIndex_].name));
|
||||
Socket_->sendBytes(P.Data(), P.Len());
|
||||
}
|
||||
LastKeepAlive = Utils::Now();
|
||||
}
|
||||
Poco::Thread::trySleep(2000);
|
||||
@@ -163,17 +165,16 @@ namespace OpenWifi {
|
||||
fmt::format("Unknown packet: Type: {} (type={}) Length={}",
|
||||
P.PacketType(), P.PacketTypeInt(), P.BufferLen()));
|
||||
}
|
||||
return;
|
||||
} else {
|
||||
poco_warning(Logger_, "Invalid packet received. Resetting the connection.");
|
||||
Disconnect();
|
||||
}
|
||||
} catch (const Poco::Exception &E) {
|
||||
Logger_.log(E);
|
||||
Disconnect();
|
||||
} catch (...) {
|
||||
Disconnect();
|
||||
poco_warning(Logger_, "Exception occurred. Resetting the connection.");
|
||||
}
|
||||
Disconnect();
|
||||
}
|
||||
|
||||
inline void
|
||||
@@ -324,7 +325,7 @@ namespace OpenWifi {
|
||||
ofs << OpenRoamingRootCert;
|
||||
ofs.close();
|
||||
|
||||
Poco::Net::Context::Ptr SecureContext = Poco::AutoPtr<Poco::Net::Context>(
|
||||
auto SecureContext = Poco::AutoPtr<Poco::Net::Context>(
|
||||
new Poco::Net::Context(Poco::Net::Context::TLS_CLIENT_USE, ""));
|
||||
|
||||
if (Pool_.acctConfig.servers[ServerIndex_].allowSelfSigned) {
|
||||
@@ -430,7 +431,7 @@ namespace OpenWifi {
|
||||
DecodeFile(CaCertFiles_[CaCertFiles_.size() - 1]->path(), cert);
|
||||
}
|
||||
|
||||
Poco::Net::Context::Ptr SecureContext =
|
||||
auto SecureContext =
|
||||
Poco::AutoPtr<Poco::Net::Context>(new Poco::Net::Context(
|
||||
Poco::Net::Context::TLS_CLIENT_USE, KeyFile_.path(), CertFile_.path(), ""));
|
||||
if (Pool_.acctConfig.servers[ServerIndex_].allowSelfSigned) {
|
||||
@@ -498,7 +499,9 @@ namespace OpenWifi {
|
||||
}
|
||||
|
||||
inline bool Connect_Generic() {
|
||||
if (TryAgain_) {
|
||||
poco_information(Logger_, fmt::format("Connecting {}", Pool_.name));
|
||||
if (TryAgain_ && !Connected_) {
|
||||
|
||||
std::lock_guard G(LocalMutex_);
|
||||
|
||||
Poco::Net::SocketAddress AuthSockAddrV4(
|
||||
@@ -520,26 +523,6 @@ namespace OpenWifi {
|
||||
MicroServiceConfigGetInt("radius.proxy.coa.port", DEFAULT_RADIUS_CoA_PORT));
|
||||
CoASocketV4_ = std::make_unique<Poco::Net::DatagramSocket>(CoASockAddrV4, true, true);
|
||||
|
||||
/*
|
||||
AuthenticationSocketV6_ =
|
||||
std::make_unique<Poco::Net::DatagramSocket>(AuthSockAddrV6, true, true);
|
||||
Poco::Net::SocketAddress AuthSockAddrV6(
|
||||
Poco::Net::AddressFamily::IPv6,
|
||||
MicroServiceConfigGetInt("radius.proxy.authentication.port",
|
||||
DEFAULT_RADIUS_AUTHENTICATION_PORT));
|
||||
|
||||
Poco::Net::SocketAddress AcctSockAddrV6(
|
||||
Poco::Net::AddressFamily::IPv6,
|
||||
MicroServiceConfigGetInt("radius.proxy.accounting.port",
|
||||
DEFAULT_RADIUS_ACCOUNTING_PORT));
|
||||
AccountingSocketV6_ =
|
||||
std::make_unique<Poco::Net::DatagramSocket>(AcctSockAddrV6, true, true);
|
||||
|
||||
Poco::Net::SocketAddress CoASockAddrV6(
|
||||
Poco::Net::AddressFamily::IPv6,
|
||||
MicroServiceConfigGetInt("radius.proxy.coa.port", DEFAULT_RADIUS_CoA_PORT));
|
||||
CoASocketV6_ = std::make_unique<Poco::Net::DatagramSocket>(CoASockAddrV6, true, true);
|
||||
*/
|
||||
Reactor_.addEventHandler(
|
||||
*AuthenticationSocketV4_,
|
||||
Poco::NObserver<RADIUS_Destination, Poco::Net::ReadableNotification>(
|
||||
@@ -551,7 +534,27 @@ namespace OpenWifi {
|
||||
Reactor_.addEventHandler(
|
||||
*CoASocketV4_, Poco::NObserver<RADIUS_Destination, Poco::Net::ReadableNotification>(
|
||||
*this, &RADIUS_Destination::OnCoASocketReadable));
|
||||
|
||||
/*
|
||||
Poco::Net::SocketAddress AuthSockAddrV6(
|
||||
Poco::Net::AddressFamily::IPv6,
|
||||
MicroServiceConfigGetInt("radius.proxy.authentication.port",
|
||||
DEFAULT_RADIUS_AUTHENTICATION_PORT));
|
||||
AuthenticationSocketV6_ =
|
||||
std::make_unique<Poco::Net::DatagramSocket>(AuthSockAddrV6, true, true);
|
||||
|
||||
Poco::Net::SocketAddress AcctSockAddrV6(
|
||||
Poco::Net::AddressFamily::IPv6,
|
||||
MicroServiceConfigGetInt("radius.proxy.accounting.port",
|
||||
DEFAULT_RADIUS_AUTHENTICATION_PORT));
|
||||
AccountingSocketV6_ =
|
||||
std::make_unique<Poco::Net::DatagramSocket>(AcctSockAddrV6, true, true);
|
||||
|
||||
Poco::Net::SocketAddress CoASockAddrV6(
|
||||
Poco::Net::AddressFamily::IPv6,
|
||||
MicroServiceConfigGetInt("radius.proxy.coa.port", DEFAULT_RADIUS_CoA_PORT));
|
||||
CoASocketV6_ = std::make_unique<Poco::Net::DatagramSocket>(CoASockAddrV6, true, true);
|
||||
|
||||
Reactor_.addEventHandler(
|
||||
*AuthenticationSocketV6_,
|
||||
Poco::NObserver<RADIUS_Destination, Poco::Net::ReadableNotification>(
|
||||
@@ -565,6 +568,7 @@ namespace OpenWifi {
|
||||
*CoASocketV6_, Poco::NObserver<RADIUS_Destination, Poco::Net::ReadableNotification>(
|
||||
*this, &RADIUS_Destination::OnCoASocketReadable));
|
||||
*/
|
||||
Connected_ = true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -590,6 +594,8 @@ namespace OpenWifi {
|
||||
if (Connected_) {
|
||||
std::lock_guard G(LocalMutex_);
|
||||
if(Type_==GWObjects::RadiusEndpointType::generic) {
|
||||
poco_information(Logger_, fmt::format("Disconnecting {} generic server. Releasing all UDP resources.", Pool_.name));
|
||||
|
||||
if(AuthenticationSocketV4_) {
|
||||
Reactor_.removeEventHandler(
|
||||
*AuthenticationSocketV4_,
|
||||
@@ -617,7 +623,8 @@ namespace OpenWifi {
|
||||
CoASocketV4_.reset();
|
||||
}
|
||||
|
||||
/* if(AuthenticationSocketV6_) {
|
||||
/*
|
||||
if(AuthenticationSocketV6_) {
|
||||
Reactor_.removeEventHandler(
|
||||
*AuthenticationSocketV6_,
|
||||
Poco::NObserver<RADIUS_Destination, Poco::Net::ReadableNotification>(
|
||||
@@ -646,7 +653,6 @@ namespace OpenWifi {
|
||||
*/
|
||||
} else {
|
||||
if(Socket_!=nullptr) {
|
||||
std::lock_guard G(LocalMutex_);
|
||||
Reactor_.removeEventHandler(
|
||||
*Socket_, Poco::NObserver<RADIUS_Destination, Poco::Net::ReadableNotification>(
|
||||
*this, &RADIUS_Destination::onData));
|
||||
@@ -660,9 +666,9 @@ namespace OpenWifi {
|
||||
Socket_->close();
|
||||
}
|
||||
}
|
||||
Connected_ = false;
|
||||
}
|
||||
Connected_ = false;
|
||||
poco_information(Logger_, "Disconnecting.");
|
||||
poco_information(Logger_, fmt::format("Disconnecting {}", Pool_.name));
|
||||
}
|
||||
|
||||
static void DecodeFile(const std::string &filename, const std::string &s) {
|
||||
@@ -724,7 +730,8 @@ namespace OpenWifi {
|
||||
std::unique_ptr<Poco::Net::DatagramSocket> AuthenticationSocketV4_;
|
||||
std::unique_ptr<Poco::Net::DatagramSocket> CoASocketV4_;
|
||||
|
||||
/* std::unique_ptr<Poco::Net::DatagramSocket> CoASocketV6_;
|
||||
/*
|
||||
std::unique_ptr<Poco::Net::DatagramSocket> CoASocketV6_;
|
||||
std::unique_ptr<Poco::Net::DatagramSocket> AccountingSocketV6_;
|
||||
std::unique_ptr<Poco::Net::DatagramSocket> AuthenticationSocketV6_;
|
||||
*/
|
||||
|
||||
@@ -25,9 +25,23 @@ namespace OpenWifi::RESTAPI_RPC {
|
||||
if (StorageService()->AddCommand(Cmd.SerialNumber, Cmd, Status)) {
|
||||
Poco::JSON::Object RetObj;
|
||||
Cmd.to_json(RetObj);
|
||||
if (Handler != nullptr)
|
||||
return Handler->ReturnObject(RetObj);
|
||||
return;
|
||||
if (Handler == nullptr) {
|
||||
// nothing to process/return
|
||||
return;
|
||||
}
|
||||
Poco::Net::HTTPResponse::HTTPStatus cmd_status = Poco::Net::HTTPResponse::HTTP_OK;
|
||||
if (Cmd.ErrorCode > 0) {
|
||||
// command returned error
|
||||
cmd_status = Poco::Net::HTTPResponse::HTTP_BAD_REQUEST;
|
||||
if (Cmd.Command == uCentralProtocol::CONFIGURE) {
|
||||
// special handling for configure command
|
||||
if (!Handler->GetBoolParameter("strict", false)) {
|
||||
// in non-strict mode return success for failed configure command
|
||||
cmd_status = Poco::Net::HTTPResponse::HTTP_OK;
|
||||
}
|
||||
}
|
||||
}
|
||||
return Handler->ReturnObject(RetObj, cmd_status);
|
||||
}
|
||||
if (Handler != nullptr)
|
||||
return Handler->ReturnStatus(Poco::Net::HTTPResponse::HTTP_INTERNAL_SERVER_ERROR);
|
||||
@@ -167,6 +181,20 @@ namespace OpenWifi::RESTAPI_RPC {
|
||||
Cmd.AttachType = "";
|
||||
}
|
||||
|
||||
// If the command fails on the device we should show it as failed and not return 200 OK
|
||||
// exception is configure command which only reported failed in strict validation mode
|
||||
if (Cmd.ErrorCode &&
|
||||
(Cmd.Command != uCentralProtocol::CONFIGURE ||
|
||||
(Cmd.Command == uCentralProtocol::CONFIGURE && Handler->GetBoolParameter("strict", false))
|
||||
))
|
||||
{
|
||||
Logger.information(fmt::format(
|
||||
"Command failed with error on device: {} Reason: {}.",
|
||||
Cmd.ErrorCode, Cmd.ErrorText));
|
||||
return SetCommandStatus(Cmd, Request, Response, Handler,
|
||||
Storage::CommandExecutionType::COMMAND_FAILED, Logger);
|
||||
}
|
||||
|
||||
if (Cmd.ErrorCode == 0 && Cmd.Command == uCentralProtocol::CONFIGURE) {
|
||||
// we need to post a kafka event for this.
|
||||
if (Params.has(uCentralProtocol::CONFIG) && Params.isObject(uCentralProtocol::CONFIG)) {
|
||||
@@ -175,6 +203,7 @@ namespace OpenWifi::RESTAPI_RPC {
|
||||
DeviceConfigurationChangeKafkaEvent KEvent(
|
||||
Utils::SerialNumberToInt(Cmd.SerialNumber), Utils::Now(),
|
||||
Config);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -56,17 +56,27 @@ namespace OpenWifi {
|
||||
return BadRequest(RESTAPI::Errors::InvalidJSONDocument);
|
||||
}
|
||||
|
||||
if (DefConfig.Models.empty()) {
|
||||
if (DefConfig.models.empty()) {
|
||||
return BadRequest(RESTAPI::Errors::ModelIDListCannotBeEmpty);
|
||||
}
|
||||
|
||||
std::vector<std::string> Error;
|
||||
if (!ValidateUCentralConfiguration(DefConfig.Configuration, Error,
|
||||
GetBoolParameter("strict", false))) {
|
||||
return BadRequest(RESTAPI::Errors::ConfigBlockInvalid);
|
||||
DefConfig.platform = DefConfig.platform.empty() ? Platforms::AP : DefConfig.platform;
|
||||
if(DefConfig.platform != Platforms::AP && DefConfig.platform != Platforms::SWITCH) {
|
||||
return BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
|
||||
}
|
||||
|
||||
DefConfig.Created = DefConfig.LastModified = Utils::Now();
|
||||
if(DefConfig.configuration.empty()) {
|
||||
return BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
|
||||
}
|
||||
|
||||
std::string Error;
|
||||
if (!ValidateUCentralConfiguration(ConfigurationValidator::GetType(DefConfig.platform),
|
||||
DefConfig.configuration, Error,
|
||||
GetBoolParameter("strict", false))) {
|
||||
return BadRequest(RESTAPI::Errors::ConfigBlockInvalid, Error);
|
||||
}
|
||||
|
||||
DefConfig.created = DefConfig.lastModified = Utils::Now();
|
||||
if (StorageService()->CreateDefaultConfiguration(Name, DefConfig)) {
|
||||
return OK();
|
||||
}
|
||||
@@ -88,19 +98,31 @@ namespace OpenWifi {
|
||||
return NotFound();
|
||||
}
|
||||
|
||||
if (!NewConfig.Configuration.empty()) {
|
||||
std::vector<std::string> Error;
|
||||
if (!ValidateUCentralConfiguration(NewConfig.Configuration, Error,
|
||||
GetBoolParameter("strict", false))) {
|
||||
return BadRequest(RESTAPI::Errors::ConfigBlockInvalid);
|
||||
}
|
||||
Existing.Configuration = NewConfig.Configuration;
|
||||
if(Existing.platform.empty()) {
|
||||
Existing.platform = Platforms::AP;
|
||||
}
|
||||
|
||||
Existing.LastModified = Utils::Now();
|
||||
AssignIfPresent(Obj, "description", Existing.Description);
|
||||
if(ParsedBody_->has("platform")) {
|
||||
if(NewConfig.platform.empty() || (NewConfig.platform != Platforms::AP && NewConfig.platform != Platforms::SWITCH)) {
|
||||
return BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
|
||||
}
|
||||
Existing.platform = NewConfig.platform;
|
||||
}
|
||||
|
||||
if (!NewConfig.configuration.empty()) {
|
||||
std::string Error;
|
||||
if (!ValidateUCentralConfiguration(ConfigurationValidator::GetType(Existing.platform),
|
||||
NewConfig.configuration, Error,
|
||||
GetBoolParameter("strict", false))) {
|
||||
return BadRequest(RESTAPI::Errors::ConfigBlockInvalid, Error);
|
||||
}
|
||||
Existing.configuration = NewConfig.configuration;
|
||||
}
|
||||
|
||||
Existing.lastModified = Utils::Now();
|
||||
AssignIfPresent(Obj, "description", Existing.description);
|
||||
if (Obj->has("modelIds"))
|
||||
Existing.Models = NewConfig.Models;
|
||||
Existing.models = NewConfig.models;
|
||||
|
||||
if (StorageService()->UpdateDefaultConfiguration(Name, Existing)) {
|
||||
GWObjects::DefaultConfiguration ModifiedConfig;
|
||||
|
||||
@@ -166,7 +166,8 @@ namespace OpenWifi {
|
||||
{APCommands::Commands::rrm, false, true, &RESTAPI_device_commandHandler::RRM, 60000ms},
|
||||
{APCommands::Commands::certupdate, false, true, &RESTAPI_device_commandHandler::CertUpdate, 60000ms},
|
||||
{APCommands::Commands::transfer, false, true, &RESTAPI_device_commandHandler::Transfer, 60000ms},
|
||||
{APCommands::Commands::script, false, true, &RESTAPI_device_commandHandler::Script, 60000ms}
|
||||
{APCommands::Commands::script, false, true, &RESTAPI_device_commandHandler::Script, 60000ms},
|
||||
{APCommands::Commands::powercycle, false, true, &RESTAPI_device_commandHandler::PowerCycle, 60000ms}
|
||||
};
|
||||
|
||||
void RESTAPI_device_commandHandler::DoPost() {
|
||||
@@ -653,13 +654,18 @@ namespace OpenWifi {
|
||||
return BadRequest(RESTAPI::Errors::SerialNumberMismatch);
|
||||
}
|
||||
|
||||
GWObjects::Device DeviceInfo;
|
||||
if (!StorageService()->GetDevice(SerialNumber_, DeviceInfo)) {
|
||||
return NotFound();
|
||||
}
|
||||
auto Configuration =
|
||||
GetS(RESTAPI::Protocol::CONFIGURATION, Obj, uCentralProtocol::EMPTY_JSON_DOC);
|
||||
std::vector<std::string> Error;
|
||||
if (!ValidateUCentralConfiguration(Configuration, Error,
|
||||
std::string Error;
|
||||
if (!ValidateUCentralConfiguration(ConfigurationValidator::GetType(DeviceInfo.DeviceType),
|
||||
Configuration, Error,
|
||||
GetBoolParameter("strict", false))) {
|
||||
CallCanceled("CONFIGURE", CMD_UUID, CMD_RPC, RESTAPI::Errors::ConfigBlockInvalid);
|
||||
return BadRequest(RESTAPI::Errors::ConfigBlockInvalid);
|
||||
return BadRequest(RESTAPI::Errors::ConfigBlockInvalid, Error);
|
||||
}
|
||||
|
||||
auto When = GetWhen(Obj);
|
||||
@@ -1401,9 +1407,9 @@ namespace OpenWifi {
|
||||
Cmd.WaitingForFile = 0;
|
||||
Cmd.Status= "completed";
|
||||
if(CommandManager()->FireAndForget(SerialNumber_, uCentralProtocol::RRM, Params)) {
|
||||
Cmd.Status= "completed";
|
||||
StorageService()->AddCommand(SerialNumber_, Cmd,
|
||||
Storage::CommandExecutionType::COMMAND_COMPLETED);
|
||||
Cmd.Status= "completed";
|
||||
return OK();
|
||||
}
|
||||
Cmd.Status= "failed"; // should never happen
|
||||
@@ -1501,4 +1507,45 @@ namespace OpenWifi {
|
||||
|
||||
}
|
||||
|
||||
void RESTAPI_device_commandHandler::PowerCycle(
|
||||
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("RRM", CMD_UUID, CMD_RPC, RESTAPI::Errors::ACCESS_DENIED);
|
||||
return UnAuthorized(RESTAPI::Errors::ACCESS_DENIED);
|
||||
}
|
||||
|
||||
poco_debug(Logger_, fmt::format("POWERCYCLE({},{}): TID={} user={} serial={}", CMD_UUID,
|
||||
CMD_RPC, TransactionId_, Requester(), SerialNumber_));
|
||||
|
||||
if(IsDeviceSimulated(SerialNumber_)) {
|
||||
CallCanceled("RRM", CMD_UUID, CMD_RPC, RESTAPI::Errors::SimulatedDeviceNotSupported);
|
||||
return BadRequest(RESTAPI::Errors::SimulatedDeviceNotSupported);
|
||||
}
|
||||
|
||||
GWObjects::PowerCycleRequest 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::POWERCYCLE;
|
||||
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::powercycle, false, Cmd,
|
||||
*ParsedBody_, *Request, *Response, timeout, nullptr, this,
|
||||
Logger_);
|
||||
}
|
||||
|
||||
} // namespace OpenWifi
|
||||
|
||||
@@ -68,6 +68,8 @@ namespace OpenWifi {
|
||||
const GWObjects::DeviceRestrictions &R);
|
||||
void Transfer(const std::string &UUID, uint64_t RPC, std::chrono::milliseconds timeout,
|
||||
const GWObjects::DeviceRestrictions &R);
|
||||
void PowerCycle(const std::string &UUID, uint64_t RPC, std::chrono::milliseconds timeout,
|
||||
const GWObjects::DeviceRestrictions &R);
|
||||
|
||||
static auto PathName() {
|
||||
return std::list<std::string>{"/api/v1/device/{serialNumber}/{command}"};
|
||||
|
||||
@@ -17,6 +17,8 @@
|
||||
|
||||
#include "RESTAPI_device_helper.h"
|
||||
|
||||
#include "AP_WS_Server.h"
|
||||
|
||||
namespace OpenWifi {
|
||||
void RESTAPI_device_handler::DoGet() {
|
||||
std::string SerialNumber = GetBinding(RESTAPI::Protocol::SERIALNUMBER, "");
|
||||
@@ -80,6 +82,9 @@ namespace OpenWifi {
|
||||
return OK();
|
||||
|
||||
} else if (StorageService()->DeleteDevice(SerialNumber)) {
|
||||
if(AP_WS_Server()->Connected(Utils::SerialNumberToInt(SerialNumber))) {
|
||||
AP_WS_Server()->Disconnect(Utils::SerialNumberToInt(SerialNumber));
|
||||
}
|
||||
return OK();
|
||||
}
|
||||
|
||||
@@ -101,9 +106,10 @@ namespace OpenWifi {
|
||||
}
|
||||
auto Config = Obj->get("configuration").toString();
|
||||
Poco::JSON::Object Answer;
|
||||
std::vector<std::string> Error;
|
||||
std::string Error;
|
||||
auto DeviceType = Poco::toLower(GetParameter("deviceType", Platforms::AP));
|
||||
auto Res =
|
||||
ValidateUCentralConfiguration(Config, Error, GetBoolParameter("strict", false));
|
||||
ValidateUCentralConfiguration(ConfigurationValidator::GetType(DeviceType),Config, Error, GetBoolParameter("strict", false));
|
||||
Answer.set("valid", Res);
|
||||
if (!Error.empty())
|
||||
Answer.set("error", Error);
|
||||
@@ -123,12 +129,13 @@ namespace OpenWifi {
|
||||
return BadRequest(RESTAPI::Errors::SerialNumberMismatch);
|
||||
}
|
||||
|
||||
std::vector<std::string> Error;
|
||||
std::string Error;
|
||||
if (Device.Configuration.empty() ||
|
||||
(!Device.Configuration.empty() &&
|
||||
!ValidateUCentralConfiguration(Device.Configuration, Error,
|
||||
!ValidateUCentralConfiguration(ConfigurationValidator::GetType(Device.DeviceType),
|
||||
Device.Configuration, Error,
|
||||
GetBoolParameter("strict", false)))) {
|
||||
return BadRequest(RESTAPI::Errors::ConfigBlockInvalid);
|
||||
return BadRequest(RESTAPI::Errors::ConfigBlockInvalid, Error);
|
||||
}
|
||||
|
||||
for (auto &i : Device.Notes) {
|
||||
@@ -169,10 +176,11 @@ namespace OpenWifi {
|
||||
}
|
||||
|
||||
if (!NewDevice.Configuration.empty()) {
|
||||
std::vector<std::string> Error;
|
||||
if (!ValidateUCentralConfiguration(NewDevice.Configuration, Error,
|
||||
std::string Error;
|
||||
if (!ValidateUCentralConfiguration(ConfigurationValidator::GetType(Existing.DeviceType),
|
||||
NewDevice.Configuration, Error,
|
||||
GetBoolParameter("strict", false))) {
|
||||
return BadRequest(RESTAPI::Errors::ConfigBlockInvalid);
|
||||
return BadRequest(RESTAPI::Errors::ConfigBlockInvalid, Error);
|
||||
}
|
||||
Config::Config NewConfig(NewDevice.Configuration);
|
||||
uint64_t NewConfigUUID = Utils::Now();
|
||||
|
||||
@@ -82,15 +82,24 @@ namespace OpenWifi {
|
||||
}
|
||||
}
|
||||
|
||||
auto platform = Poco::toLower(GetParameter("platform", ""));
|
||||
auto serialOnly = GetBoolParameter(RESTAPI::Protocol::SERIALONLY, false);
|
||||
auto deviceWithStatus = GetBoolParameter(RESTAPI::Protocol::DEVICEWITHSTATUS, false);
|
||||
auto completeInfo = GetBoolParameter("completeInfo", false);
|
||||
auto includeProvisioned = GetBoolParameter("includeProvisioned", true);
|
||||
|
||||
if(!platform.empty() && (platform!=Platforms::AP && platform!=Platforms::SWITCH && platform!="all")) {
|
||||
return BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
|
||||
}
|
||||
|
||||
if(platform=="all")
|
||||
platform="";
|
||||
|
||||
Poco::JSON::Object RetObj;
|
||||
if (!QB_.Select.empty()) {
|
||||
Poco::JSON::Array Objects;
|
||||
for (auto &i : SelectedRecords()) {
|
||||
auto SerialNumber = i;
|
||||
auto &SerialNumber = i;
|
||||
if (!Utils::ValidSerialNumber(i))
|
||||
continue;
|
||||
GWObjects::Device D;
|
||||
@@ -116,14 +125,14 @@ namespace OpenWifi {
|
||||
else
|
||||
RetObj.set(RESTAPI::Protocol::DEVICES, Objects);
|
||||
|
||||
} else if (QB_.CountOnly == true) {
|
||||
} else if (QB_.CountOnly) {
|
||||
uint64_t Count = 0;
|
||||
if (StorageService()->GetDeviceCount(Count)) {
|
||||
if (StorageService()->GetDeviceCount(Count, platform, includeProvisioned)) {
|
||||
return ReturnCountOnly(Count);
|
||||
}
|
||||
} else if (serialOnly) {
|
||||
std::vector<std::string> SerialNumbers;
|
||||
StorageService()->GetDeviceSerialNumbers(QB_.Offset, QB_.Limit, SerialNumbers, OrderBy);
|
||||
StorageService()->GetDeviceSerialNumbers(QB_.Offset, QB_.Limit, SerialNumbers, OrderBy, platform, includeProvisioned);
|
||||
Poco::JSON::Array Objects;
|
||||
for (const auto &i : SerialNumbers) {
|
||||
Objects.add(i);
|
||||
@@ -141,7 +150,7 @@ namespace OpenWifi {
|
||||
RetObj.set("serialNumbers", Objects);
|
||||
} else {
|
||||
std::vector<GWObjects::Device> Devices;
|
||||
StorageService()->GetDevices(QB_.Offset, QB_.Limit, Devices, OrderBy);
|
||||
StorageService()->GetDevices(QB_.Offset, QB_.Limit, Devices, OrderBy, platform, includeProvisioned);
|
||||
Poco::JSON::Array Objects;
|
||||
for (const auto &i : Devices) {
|
||||
Poco::JSON::Object Obj;
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "framework/RESTAPI_Handler.h"
|
||||
#include <framework/RESTAPI_Handler.h>
|
||||
|
||||
namespace OpenWifi {
|
||||
class RESTAPI_file : public RESTAPIHandler {
|
||||
|
||||
@@ -23,8 +23,8 @@ namespace OpenWifi {
|
||||
void RESTAPI_script_handler::DoDelete() {
|
||||
std::string UUID = GetBinding("uuid", "");
|
||||
|
||||
if (UserInfo_.userinfo.userRole != SecurityObjects::ROOT) {
|
||||
return BadRequest(RESTAPI::Errors::ACCESS_DENIED);
|
||||
if (!UserInfo_.userinfo.userPermissions[SecurityObjects::PM_SCRIPTS_GW][SecurityObjects::PT_DELETE]) {
|
||||
return UnAuthorized(RESTAPI::Errors::ACCESS_DENIED);
|
||||
}
|
||||
|
||||
if (UUID.empty()) {
|
||||
@@ -40,8 +40,8 @@ namespace OpenWifi {
|
||||
void RESTAPI_script_handler::DoPost() {
|
||||
std::string UUID = GetBinding("uuid", "");
|
||||
|
||||
if (UserInfo_.userinfo.userRole != SecurityObjects::ROOT) {
|
||||
return BadRequest(RESTAPI::Errors::ACCESS_DENIED);
|
||||
if (!UserInfo_.userinfo.userPermissions[SecurityObjects::PM_SCRIPTS_GW][SecurityObjects::PT_CREATE]) {
|
||||
return UnAuthorized(RESTAPI::Errors::ACCESS_DENIED);
|
||||
}
|
||||
|
||||
if (UUID.empty()) {
|
||||
@@ -86,8 +86,8 @@ namespace OpenWifi {
|
||||
void RESTAPI_script_handler::DoPut() {
|
||||
std::string UUID = GetBinding("uuid", "");
|
||||
|
||||
if (UserInfo_.userinfo.userRole != SecurityObjects::ROOT) {
|
||||
return BadRequest(RESTAPI::Errors::ACCESS_DENIED);
|
||||
if (!UserInfo_.userinfo.userPermissions[SecurityObjects::PM_SCRIPTS_GW][SecurityObjects::PT_UPDATE]) {
|
||||
return UnAuthorized(RESTAPI::Errors::ACCESS_DENIED);
|
||||
}
|
||||
|
||||
if (UUID.empty()) {
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include "RESTAPI_ProvObjects.h"
|
||||
#include "framework/utils.h"
|
||||
#include <vector>
|
||||
#include "framework/ow_constants.h"
|
||||
|
||||
namespace OpenWifi {
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#include "Daemon.h"
|
||||
#ifdef TIP_GATEWAY_SERVICE
|
||||
#include "AP_WS_Server.h"
|
||||
#include "StorageService.h"
|
||||
#include "CapabilitiesCache.h"
|
||||
#include "RADIUSSessionTracker.h"
|
||||
#endif
|
||||
@@ -29,8 +30,8 @@ namespace OpenWifi::GWObjects {
|
||||
void Device::to_json(Poco::JSON::Object &Obj) const {
|
||||
field_to_json(Obj, "serialNumber", SerialNumber);
|
||||
#ifdef TIP_GATEWAY_SERVICE
|
||||
field_to_json(Obj, "deviceType", CapabilitiesCache::instance()->GetPlatform(Compatible));
|
||||
field_to_json(Obj, "hasRADIUSSessions", RADIUSSessionTracker()->HasSessions(SerialNumber));
|
||||
field_to_json(Obj, "deviceType", StorageService()->GetPlatform(SerialNumber));
|
||||
field_to_json(Obj, "blackListed", StorageService()->IsBlackListed(Utils::MACToInt(SerialNumber)));
|
||||
#endif
|
||||
field_to_json(Obj, "macAddress", MACAddress);
|
||||
field_to_json(Obj, "manufacturer", Manufacturer);
|
||||
@@ -68,9 +69,14 @@ namespace OpenWifi::GWObjects {
|
||||
|
||||
#ifdef TIP_GATEWAY_SERVICE
|
||||
ConnectionState ConState;
|
||||
|
||||
if (AP_WS_Server()->GetState(SerialNumber, ConState)) {
|
||||
#ifdef USE_MEDUSA_CLIENT
|
||||
auto Res = GS()->GetState(SerialNumber);
|
||||
if (Res.has_value()) {
|
||||
Res.value().to_json(SerialNumber,Obj);
|
||||
#else
|
||||
if (AP_WS_Server()->GetState(SerialNumber, ConState)) {
|
||||
ConState.to_json(SerialNumber,Obj);
|
||||
#endif
|
||||
} else {
|
||||
field_to_json(Obj, "ipAddress", "");
|
||||
field_to_json(Obj, "txBytes", (uint64_t)0);
|
||||
@@ -166,14 +172,17 @@ namespace OpenWifi::GWObjects {
|
||||
field_to_json(Obj, "recorded", Recorded);
|
||||
}
|
||||
|
||||
void DefaultConfiguration::to_json(Poco::JSON::Object &Obj) const {
|
||||
EmbedDocument("configuration", Obj, Configuration);
|
||||
field_to_json(Obj, "name", Name);
|
||||
field_to_json(Obj, "modelIds", Models);
|
||||
field_to_json(Obj, "description", Description);
|
||||
field_to_json(Obj, "created", Created);
|
||||
field_to_json(Obj, "lastModified", LastModified);
|
||||
}
|
||||
bool HealthCheck::from_json(const Poco::JSON::Object::Ptr &Obj) {
|
||||
try {
|
||||
field_from_json(Obj, "UUID", UUID);
|
||||
field_from_json(Obj, "sanity", Sanity);
|
||||
field_from_json(Obj, "recorded", Recorded);
|
||||
return true;
|
||||
} catch(...) {
|
||||
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void DefaultFirmware::to_json(Poco::JSON::Object &Obj) const {
|
||||
field_to_json(Obj, "deviceType", deviceType);
|
||||
@@ -222,12 +231,25 @@ namespace OpenWifi::GWObjects {
|
||||
field_to_json(Obj, "deferred", deferred);
|
||||
}
|
||||
|
||||
void DefaultConfiguration::to_json(Poco::JSON::Object &Obj) const {
|
||||
EmbedDocument("configuration", Obj, configuration);
|
||||
field_to_json(Obj, "name", name);
|
||||
field_to_json(Obj, "modelIds", models);
|
||||
field_to_json(Obj, "description", description);
|
||||
field_to_json(Obj, "created", created);
|
||||
field_to_json(Obj, "lastModified", lastModified);
|
||||
field_to_json(Obj, "platform", platform);
|
||||
}
|
||||
|
||||
bool DefaultConfiguration::from_json(const Poco::JSON::Object::Ptr &Obj) {
|
||||
try {
|
||||
field_from_json(Obj, "name", Name);
|
||||
field_from_json(Obj, "configuration", Configuration);
|
||||
field_from_json(Obj, "modelIds", Models);
|
||||
field_from_json(Obj, "description", Description);
|
||||
field_from_json(Obj, "configuration", configuration);
|
||||
field_from_json(Obj, "name", name);
|
||||
field_from_json(Obj, "modelIds", models);
|
||||
field_from_json(Obj, "description", description);
|
||||
field_from_json(Obj, "created", created);
|
||||
field_from_json(Obj, "lastModified", lastModified);
|
||||
field_from_json(Obj, "platform", platform);
|
||||
return true;
|
||||
} catch (const Poco::Exception &E) {
|
||||
}
|
||||
@@ -273,16 +295,14 @@ namespace OpenWifi::GWObjects {
|
||||
field_to_json(Obj, "started", started);
|
||||
field_to_json(Obj, "sessionId", sessionId);
|
||||
field_to_json(Obj, "connectionCompletionTime", connectionCompletionTime);
|
||||
field_to_json(Obj, "totalConnectionTime", Utils::Now() - started);
|
||||
field_to_json(Obj, "totalConnectionTime", started ? Utils::Now() - started : 0);
|
||||
field_to_json(Obj, "certificateExpiryDate", certificateExpiryDate);
|
||||
field_to_json(Obj, "connectReason", connectReason);
|
||||
field_to_json(Obj, "uptime", uptime);
|
||||
field_to_json(Obj, "compatible", Compatible);
|
||||
|
||||
#ifdef TIP_GATEWAY_SERVICE
|
||||
hasRADIUSSessions = RADIUSSessionTracker()->HasSessions(SerialNumber);
|
||||
AP_WS_Server()->ExtendedAttributes(SerialNumber, hasGPS, sanity,
|
||||
memoryUsed,
|
||||
load,
|
||||
temperature);
|
||||
#endif
|
||||
field_to_json(Obj, "hasRADIUSSessions", hasRADIUSSessions );
|
||||
field_to_json(Obj, "hasGPS", hasGPS);
|
||||
@@ -314,6 +334,45 @@ namespace OpenWifi::GWObjects {
|
||||
}
|
||||
}
|
||||
|
||||
bool ConnectionState::from_json(const Poco::JSON::Object::Ptr &Obj) {
|
||||
try {
|
||||
field_from_json(Obj, "compatible", Compatible);
|
||||
field_from_json(Obj, "ipAddress", Address);
|
||||
field_from_json(Obj, "txBytes", TX);
|
||||
field_from_json(Obj, "rxBytes", RX);
|
||||
field_from_json(Obj, "messageCount", MessageCount);
|
||||
field_from_json(Obj, "UUID", UUID);
|
||||
field_from_json(Obj, "connected", Connected);
|
||||
field_from_json(Obj, "firmware", Firmware);
|
||||
field_from_json(Obj, "lastContact", LastContact);
|
||||
field_from_json(Obj, "associations_2G", Associations_2G);
|
||||
field_from_json(Obj, "associations_5G", Associations_5G);
|
||||
field_from_json(Obj, "associations_6G", Associations_6G);
|
||||
field_from_json(Obj, "webSocketClients", webSocketClients);
|
||||
field_from_json(Obj, "websocketPackets", websocketPackets);
|
||||
field_from_json(Obj, "kafkaClients", kafkaClients);
|
||||
field_from_json(Obj, "kafkaPackets", kafkaPackets);
|
||||
field_from_json(Obj, "locale", locale);
|
||||
field_from_json(Obj, "started", started);
|
||||
field_from_json(Obj, "sessionId", sessionId);
|
||||
field_from_json(Obj, "connectionCompletionTime", connectionCompletionTime);
|
||||
field_from_json(Obj, "totalConnectionTime", totalConnectionTime);
|
||||
field_from_json(Obj, "certificateExpiryDate", certificateExpiryDate);
|
||||
field_from_json(Obj, "connectReason", connectReason);
|
||||
field_from_json(Obj, "uptime", uptime);
|
||||
field_from_json(Obj, "hasRADIUSSessions", hasRADIUSSessions );
|
||||
field_from_json(Obj, "hasGPS", hasGPS);
|
||||
field_from_json(Obj, "sanity", sanity);
|
||||
field_from_json(Obj, "memoryUsed", memoryUsed);
|
||||
field_from_json(Obj, "sanity", sanity);
|
||||
field_from_json(Obj, "load", load);
|
||||
field_from_json(Obj, "temperature", temperature);
|
||||
return true;
|
||||
} catch(const Poco::Exception &E) {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void DeviceConnectionStatistics::to_json(Poco::JSON::Object &Obj) const {
|
||||
field_to_json(Obj, "averageConnectionTime", averageConnectionTime);
|
||||
field_to_json(Obj, "connectedDevices", connectedDevices);
|
||||
@@ -711,7 +770,7 @@ namespace OpenWifi::GWObjects {
|
||||
|
||||
bool DeviceCertificateUpdateRequest::from_json(const Poco::JSON::Object::Ptr &Obj) {
|
||||
try {
|
||||
field_from_json(Obj, "serialNumber", serialNumber);
|
||||
field_from_json(Obj, "serial", serialNumber);
|
||||
field_from_json(Obj, "encodedCertificate", encodedCertificate);
|
||||
return true;
|
||||
} catch (const Poco::Exception &E) {
|
||||
@@ -719,4 +778,25 @@ namespace OpenWifi::GWObjects {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool PowerCyclePort::from_json(const Poco::JSON::Object::Ptr &Obj) {
|
||||
try {
|
||||
field_from_json(Obj, "name", name);
|
||||
field_from_json(Obj, "cycle", cycle);
|
||||
return true;
|
||||
} catch (const Poco::Exception &E) {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool PowerCycleRequest::from_json(const Poco::JSON::Object::Ptr &Obj) {
|
||||
try {
|
||||
field_from_json(Obj, "serial", serialNumber);
|
||||
field_from_json(Obj, "when", when);
|
||||
field_from_json(Obj, "ports", ports);
|
||||
return true;
|
||||
} catch (const Poco::Exception &E) {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace OpenWifi::GWObjects
|
||||
|
||||
@@ -49,8 +49,11 @@ namespace OpenWifi::GWObjects {
|
||||
std::double_t load=0.0;
|
||||
std::double_t temperature=0.0;
|
||||
std::string connectReason;
|
||||
std::uint64_t uptime=0;
|
||||
std::uint64_t totalConnectionTime=0;
|
||||
|
||||
void to_json(const std::string &SerialNumber, Poco::JSON::Object &Obj) ;
|
||||
bool from_json(const Poco::JSON::Object::Ptr &Obj);
|
||||
};
|
||||
|
||||
struct DeviceRestrictionsKeyInfo {
|
||||
@@ -112,6 +115,7 @@ namespace OpenWifi::GWObjects {
|
||||
std::uint64_t lastRecordedContact=0;
|
||||
std::uint64_t certificateExpiryDate = 0;
|
||||
std::string connectReason;
|
||||
bool blackListed=false;
|
||||
|
||||
void to_json(Poco::JSON::Object &Obj) const;
|
||||
void to_json_with_status(Poco::JSON::Object &Obj) const;
|
||||
@@ -137,13 +141,15 @@ namespace OpenWifi::GWObjects {
|
||||
};
|
||||
|
||||
struct HealthCheck {
|
||||
std::string SerialNumber;
|
||||
uint64_t UUID = 0;
|
||||
std::string Data;
|
||||
uint64_t Recorded = 0;
|
||||
uint64_t Sanity = 0;
|
||||
void to_json(Poco::JSON::Object &Obj) const;
|
||||
};
|
||||
std::string SerialNumber;
|
||||
uint64_t UUID = 0;
|
||||
std::string Data;
|
||||
uint64_t Recorded = 0;
|
||||
uint64_t Sanity = 0;
|
||||
|
||||
void to_json(Poco::JSON::Object &Obj) const;
|
||||
bool from_json(const Poco::JSON::Object::Ptr &Obj);
|
||||
};
|
||||
|
||||
struct Capabilities {
|
||||
std::string Capabilities;
|
||||
@@ -174,12 +180,13 @@ namespace OpenWifi::GWObjects {
|
||||
};
|
||||
|
||||
struct DefaultConfiguration {
|
||||
std::string Name;
|
||||
std::string Configuration;
|
||||
Types::StringVec Models;
|
||||
std::string Description;
|
||||
uint64_t Created;
|
||||
uint64_t LastModified;
|
||||
std::string name;
|
||||
std::string configuration;
|
||||
Types::StringVec models;
|
||||
std::string description;
|
||||
uint64_t created;
|
||||
uint64_t lastModified;
|
||||
std::string platform;
|
||||
void to_json(Poco::JSON::Object &Obj) const;
|
||||
bool from_json(const Poco::JSON::Object::Ptr &Obj);
|
||||
};
|
||||
@@ -513,4 +520,18 @@ namespace OpenWifi::GWObjects {
|
||||
bool from_json(const Poco::JSON::Object::Ptr &Obj);
|
||||
};
|
||||
|
||||
struct PowerCyclePort {
|
||||
std::string name;
|
||||
std::uint64_t cycle=10000;
|
||||
|
||||
bool from_json(const Poco::JSON::Object::Ptr &Obj);
|
||||
};
|
||||
|
||||
struct PowerCycleRequest {
|
||||
std::string serialNumber;
|
||||
std::uint64_t when;
|
||||
std::vector<PowerCyclePort> ports;
|
||||
|
||||
bool from_json(const Poco::JSON::Object::Ptr &Obj);
|
||||
};
|
||||
} // namespace OpenWifi::GWObjects
|
||||
|
||||
@@ -587,6 +587,9 @@ namespace OpenWifi::ProvObjects {
|
||||
field_to_json(Obj, "locale", locale);
|
||||
field_to_json(Obj, "realMacAddress", realMacAddress);
|
||||
field_to_json(Obj, "doNotAllowOverrides", doNotAllowOverrides);
|
||||
field_to_json(Obj, "imported", imported);
|
||||
field_to_json(Obj, "connected", connected);
|
||||
field_to_json(Obj, "platform", platform);
|
||||
}
|
||||
|
||||
bool InventoryTag::from_json(const Poco::JSON::Object::Ptr &Obj) {
|
||||
@@ -609,6 +612,9 @@ namespace OpenWifi::ProvObjects {
|
||||
field_from_json(Obj, "locale", locale);
|
||||
field_from_json(Obj, "realMacAddress", realMacAddress);
|
||||
field_from_json(Obj, "doNotAllowOverrides", doNotAllowOverrides);
|
||||
field_from_json(Obj, "imported", imported);
|
||||
field_from_json(Obj, "connected", connected);
|
||||
field_from_json(Obj, "platform", platform);
|
||||
return true;
|
||||
} catch (...) {
|
||||
}
|
||||
|
||||
@@ -490,9 +490,11 @@ namespace OpenWifi::ProvObjects {
|
||||
std::string locale;
|
||||
std::string realMacAddress;
|
||||
bool doNotAllowOverrides = false;
|
||||
std::uint64_t imported=0;
|
||||
std::uint64_t connected=0;
|
||||
std::string platform{Platforms::AP};
|
||||
|
||||
void to_json(Poco::JSON::Object &Obj) const;
|
||||
|
||||
bool from_json(const Poco::JSON::Object::Ptr &Obj);
|
||||
};
|
||||
|
||||
|
||||
@@ -12,6 +12,8 @@
|
||||
#include "RESTAPI_SecurityObjects.h"
|
||||
#include "framework/RESTAPI_utils.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
using OpenWifi::RESTAPI_utils::field_from_json;
|
||||
using OpenWifi::RESTAPI_utils::field_to_json;
|
||||
|
||||
@@ -282,6 +284,7 @@ namespace OpenWifi::SecurityObjects {
|
||||
field_to_json(Obj, "oauthUserInfo", oauthUserInfo);
|
||||
field_to_json(Obj, "modified", modified);
|
||||
field_to_json(Obj, "signingUp", signingUp);
|
||||
Obj.set("userPermissions", permissions_to_json(userPermissions));
|
||||
};
|
||||
|
||||
bool UserInfo::from_json(const Poco::JSON::Object::Ptr &Obj) {
|
||||
@@ -318,6 +321,7 @@ namespace OpenWifi::SecurityObjects {
|
||||
field_from_json(Obj, "oauthUserInfo", oauthUserInfo);
|
||||
field_from_json(Obj, "modified", modified);
|
||||
field_from_json(Obj, "signingUp", signingUp);
|
||||
userPermissions = permissions_from_json(Obj->getObject("userPermissions"));
|
||||
return true;
|
||||
} catch (const Poco::Exception &E) {
|
||||
std::cout << "Cannot parse: UserInfo" << std::endl;
|
||||
@@ -737,4 +741,218 @@ namespace OpenWifi::SecurityObjects {
|
||||
return false;
|
||||
}
|
||||
|
||||
PERMISSION_TYPE PermTypeFromString(const std::string &U) {
|
||||
if (!Poco::icompare(U, "create"))
|
||||
return PT_CREATE;
|
||||
else if (!Poco::icompare(U, "update"))
|
||||
return PT_UPDATE;
|
||||
else if (!Poco::icompare(U, "delete"))
|
||||
return PT_DELETE;
|
||||
else if (!Poco::icompare(U, "readonly"))
|
||||
return PT_READ_ONLY;
|
||||
return PT_UNKNOWN;
|
||||
}
|
||||
|
||||
std::string PermTypeToString(PERMISSION_TYPE U) {
|
||||
switch (U) {
|
||||
case PT_CREATE:
|
||||
return "create";
|
||||
case PT_UPDATE:
|
||||
return "update";
|
||||
case PT_DELETE:
|
||||
return "delete";
|
||||
case PT_READ_ONLY:
|
||||
return "readonly";
|
||||
case PT_UNKNOWN:
|
||||
default:
|
||||
return "unknown";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
PERMISSION_MODEL PermModelFromString(const std::string &U) {
|
||||
if (!Poco::icompare(U, "permissions"))
|
||||
return PM_PERMISSIONS;
|
||||
else if (!Poco::icompare(U, "venues"))
|
||||
return PM_VENUES_PROV;
|
||||
else if (!Poco::icompare(U, "venues_list"))
|
||||
return PM_VENUES_LIST_PROV;
|
||||
else if (!Poco::icompare(U, "entities"))
|
||||
return PM_ENTITIES_PROV;
|
||||
else if (!Poco::icompare(U, "entities_list"))
|
||||
return PM_ENTITIES_LIST_PROV;
|
||||
else if (!Poco::icompare(U, "inventory"))
|
||||
return PM_INVENTORY_PROV;
|
||||
else if (!Poco::icompare(U, "inventory_list"))
|
||||
return PM_INVENTORY_LIST_PROV;
|
||||
else if (!Poco::icompare(U, "managementpolicy"))
|
||||
return PM_MANAGEMENTPOLICY_PROV;
|
||||
else if (!Poco::icompare(U, "managementpolicy_list"))
|
||||
return PM_MANAGEMENTPOLICY_LIST_PROV;
|
||||
else if (!Poco::icompare(U, "managementrole"))
|
||||
return PM_MANAGEMENTROLE_PROV;
|
||||
else if (!Poco::icompare(U, "managementrole_list"))
|
||||
return PM_MANAGEMENTROLE_LIST_PROV;
|
||||
//GW
|
||||
else if (!Poco::icompare(U, "scripts"))
|
||||
return PM_SCRIPTS_GW;
|
||||
else if (!Poco::icompare(U, "configure"))
|
||||
return PM_DEVICE_CONFIGURE_GW;
|
||||
else if (!Poco::icompare(U, "upgrade"))
|
||||
return PM_DEVICE_UPGRADE_GW;
|
||||
else if (!Poco::icompare(U, "factoryreset"))
|
||||
return PM_DEVICE_FACTORY_GW;
|
||||
else if (!Poco::icompare(U, "leds"))
|
||||
return PM_DEVICE_LEDS_GW;
|
||||
else if (!Poco::icompare(U, "trace"))
|
||||
return PM_DEVICE_TRACE_GW;
|
||||
else if (!Poco::icompare(U, "request"))
|
||||
return PM_DEVICE_REQUEST_GW;
|
||||
else if (!Poco::icompare(U, "wifiscan"))
|
||||
return PM_DEVICE_WIFISCAN_GW;
|
||||
else if (!Poco::icompare(U, "eventqueue"))
|
||||
return PM_DEVICE_EVENTQUEUE_GW;
|
||||
else if (!Poco::icompare(U, "telemetry"))
|
||||
return PM_DEVICE_TELEMETRY_GW;
|
||||
else if (!Poco::icompare(U, "ping"))
|
||||
return PM_DEVICE_PING_GW;
|
||||
else if (!Poco::icompare(U, "ap_script"))
|
||||
return PM_DEVICE_SCRIPT_GW;
|
||||
else if (!Poco::icompare(U, "rrm"))
|
||||
return PM_DEVICE_RRM_GW;
|
||||
else if (!Poco::icompare(U, "transfer"))
|
||||
return PM_DEVICE_TRANSFER_GW;
|
||||
else if (!Poco::icompare(U, "certupdate"))
|
||||
return PM_DEVICE_CERTUPDATE_GW;
|
||||
else if (!Poco::icompare(U, "powercycle"))
|
||||
return PM_DEVICE_POWERCYCLE_GW;
|
||||
else if (!Poco::icompare(U, "ap_logs"))
|
||||
return PM_DEVICE_LOGS_GW;
|
||||
else if (!Poco::icompare(U, "healthchecks"))
|
||||
return PM_DEVICE_HEALTHCHECKS_GW;
|
||||
else if (!Poco::icompare(U, "ap_capabilities"))
|
||||
return PM_DEVICE_CAPABILITIES_GW;
|
||||
else if (!Poco::icompare(U, "ap_statistics"))
|
||||
return PM_DEVICE_STATISTICS_GW;
|
||||
else if (!Poco::icompare(U, "ap_status"))
|
||||
return PM_DEVICE_STATUS_GW;
|
||||
else if (!Poco::icompare(U, "ap_rtty"))
|
||||
return PM_DEVICE_RTTY_GW;
|
||||
|
||||
return PM_UNKNOWN;
|
||||
}
|
||||
|
||||
std::string PermModelToString(PERMISSION_MODEL U) {
|
||||
switch (U) {
|
||||
case PM_PERMISSIONS:
|
||||
return "permissions";
|
||||
case PM_VENUES_PROV:
|
||||
return "venues";
|
||||
case PM_VENUES_LIST_PROV:
|
||||
return "venues_list";
|
||||
case PM_ENTITIES_PROV:
|
||||
return "entities";
|
||||
case PM_ENTITIES_LIST_PROV:
|
||||
return "entities_list";
|
||||
case PM_INVENTORY_PROV:
|
||||
return "inventory";
|
||||
case PM_INVENTORY_LIST_PROV:
|
||||
return "inventory_list";
|
||||
case PM_MANAGEMENTPOLICY_PROV:
|
||||
return "managementpolicy";
|
||||
case PM_MANAGEMENTPOLICY_LIST_PROV:
|
||||
return "managementpolicy_list";
|
||||
case PM_MANAGEMENTROLE_PROV:
|
||||
return "managementrole";
|
||||
case PM_MANAGEMENTROLE_LIST_PROV:
|
||||
return "managementrole_list";
|
||||
|
||||
//Gateway
|
||||
case PM_SCRIPTS_GW:
|
||||
return "scripts";
|
||||
case PM_DEVICE_CONFIGURE_GW:
|
||||
return "configure";
|
||||
case PM_DEVICE_UPGRADE_GW:
|
||||
return "upgrade";
|
||||
case PM_DEVICE_FACTORY_GW:
|
||||
return "factoryreset";
|
||||
case PM_DEVICE_LEDS_GW:
|
||||
return "leds";
|
||||
case PM_DEVICE_TRACE_GW:
|
||||
return "trace";
|
||||
case PM_DEVICE_REQUEST_GW:
|
||||
return "request";
|
||||
case PM_DEVICE_WIFISCAN_GW:
|
||||
return "wifiscan";
|
||||
case PM_DEVICE_EVENTQUEUE_GW:
|
||||
return "eventqueue";
|
||||
case PM_DEVICE_TELEMETRY_GW:
|
||||
return "telemetry";
|
||||
case PM_DEVICE_PING_GW:
|
||||
return "ping";
|
||||
case PM_DEVICE_SCRIPT_GW:
|
||||
return "ap_script";
|
||||
case PM_DEVICE_RRM_GW:
|
||||
return "rrm";
|
||||
case PM_DEVICE_TRANSFER_GW:
|
||||
return "transfer";
|
||||
case PM_DEVICE_CERTUPDATE_GW:
|
||||
return "certupdate";
|
||||
case PM_DEVICE_POWERCYCLE_GW:
|
||||
return "powercycle";
|
||||
case PM_DEVICE_LOGS_GW:
|
||||
return "ap_logs";
|
||||
case PM_DEVICE_HEALTHCHECKS_GW:
|
||||
return "healthchecks";
|
||||
case PM_DEVICE_CAPABILITIES_GW:
|
||||
return "ap_capabilities";
|
||||
case PM_DEVICE_STATISTICS_GW:
|
||||
return "ap_statistics";
|
||||
case PM_DEVICE_STATUS_GW:
|
||||
return "ap_status";
|
||||
case PM_DEVICE_RTTY_GW:
|
||||
return "ap_rtty";
|
||||
case PM_UNKNOWN:
|
||||
default:
|
||||
return "unknown";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert PermissionMap into a JSON object and return it
|
||||
*/
|
||||
Poco::JSON::Object permissions_to_json(const PermissionMap &Map) {
|
||||
Poco::JSON::Object MapObj;
|
||||
for (auto &[Model, Permissions] : Map) {
|
||||
Poco::JSON::Object ModelObject;
|
||||
for (auto &[Permission, Allowed] : Permissions) {
|
||||
ModelObject.set(PermTypeToString(Permission), Allowed);
|
||||
}
|
||||
MapObj.set(PermModelToString(Model), ModelObject);
|
||||
}
|
||||
return MapObj;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert JSON object into a PermissionMap and return it
|
||||
*/
|
||||
PermissionMap permissions_from_json(const Poco::JSON::Object::Ptr &Obj) {
|
||||
PermissionMap permissions;
|
||||
if (Obj == nullptr) {
|
||||
return permissions;
|
||||
}
|
||||
Poco::JSON::Object::ConstIterator it1;
|
||||
for(it1 = Obj->begin(); it1 != Obj->end(); it1++) {
|
||||
std::string model = it1->first;
|
||||
Poco::JSON::Object::Ptr modelObj = it1->second.extract<Poco::JSON::Object::Ptr>();
|
||||
Poco::JSON::Object::ConstIterator it2;
|
||||
for(it2 = modelObj->begin(); it2 != modelObj->end(); it2++) {
|
||||
std::string permission = it2->first;
|
||||
bool allowed = it2->second;
|
||||
permissions[PermModelFromString(model)]
|
||||
[PermTypeFromString(permission)] = allowed;
|
||||
}
|
||||
}
|
||||
return permissions;
|
||||
}
|
||||
} // namespace OpenWifi::SecurityObjects
|
||||
|
||||
@@ -11,10 +11,15 @@
|
||||
#include "Poco/Data/LOB.h"
|
||||
#include "Poco/Data/LOBStream.h"
|
||||
#include "Poco/JSON/Object.h"
|
||||
#include "Poco/Net/HTTPRequest.h"
|
||||
#include "framework/OpenWifiTypes.h"
|
||||
#include "framework/utils.h"
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <map>
|
||||
#include <set>
|
||||
|
||||
namespace OpenWifi {
|
||||
uint64_t Now();
|
||||
@@ -55,6 +60,10 @@ namespace OpenWifi {
|
||||
bool from_json(const Poco::JSON::Object::Ptr &Obj);
|
||||
};
|
||||
|
||||
// example entry {"/api/v1/device", {Poco::Net::HTTPRequest::HTTP_POST, Poco::Net::HTTPRequest::HTTP_PUT, Poco::Net::HTTPRequest::HTTP_DELETE}}
|
||||
const std::map<std::string, std::set<std::string>> API_WHITELIST = {
|
||||
};
|
||||
|
||||
enum USER_ROLE {
|
||||
UNKNOWN,
|
||||
ROOT,
|
||||
@@ -125,6 +134,72 @@ namespace OpenWifi {
|
||||
bool from_json(const Poco::JSON::Object::Ptr &Obj);
|
||||
};
|
||||
|
||||
// Represents particular permissions, i.e. what are you doing do the model
|
||||
enum PERMISSION_TYPE {
|
||||
PT_CREATE,
|
||||
PT_DELETE,
|
||||
PT_UPDATE,
|
||||
PT_READ_ONLY,
|
||||
PT_UNKNOWN
|
||||
};
|
||||
PERMISSION_TYPE PermTypeFromString(const std::string &U);
|
||||
std::string PermTypeToString(PERMISSION_TYPE U);
|
||||
|
||||
// Represents a model that can be operated on
|
||||
enum PERMISSION_MODEL {
|
||||
//Security
|
||||
PM_PERMISSIONS,
|
||||
|
||||
//Provisioning
|
||||
PM_VENUES_PROV,
|
||||
PM_VENUES_LIST_PROV,
|
||||
PM_ENTITIES_PROV,
|
||||
PM_ENTITIES_LIST_PROV,
|
||||
PM_INVENTORY_PROV,
|
||||
PM_INVENTORY_LIST_PROV,
|
||||
PM_MANAGEMENTPOLICY_PROV,
|
||||
PM_MANAGEMENTPOLICY_LIST_PROV,
|
||||
PM_MANAGEMENTROLE_PROV,
|
||||
PM_MANAGEMENTROLE_LIST_PROV,
|
||||
|
||||
//Gateway
|
||||
PM_DEVICE_CONFIGURE_GW,
|
||||
PM_DEVICE_UPGRADE_GW,
|
||||
PM_DEVICE_REBOOT_GW,
|
||||
PM_DEVICE_FACTORY_GW,
|
||||
PM_DEVICE_LEDS_GW,
|
||||
PM_DEVICE_TRACE_GW,
|
||||
PM_DEVICE_REQUEST_GW,
|
||||
PM_DEVICE_WIFISCAN_GW,
|
||||
PM_DEVICE_EVENTQUEUE_GW,
|
||||
PM_DEVICE_TELEMETRY_GW,
|
||||
PM_DEVICE_PING_GW,
|
||||
PM_DEVICE_SCRIPT_GW,
|
||||
PM_DEVICE_RRM_GW,
|
||||
PM_DEVICE_TRANSFER_GW,
|
||||
PM_DEVICE_CERTUPDATE_GW,
|
||||
PM_DEVICE_POWERCYCLE_GW,
|
||||
PM_DEVICE_LOGS_GW,
|
||||
PM_DEVICE_HEALTHCHECKS_GW,
|
||||
PM_DEVICE_CAPABILITIES_GW,
|
||||
PM_DEVICE_STATISTICS_GW,
|
||||
PM_DEVICE_STATUS_GW,
|
||||
PM_DEVICE_RTTY_GW,
|
||||
|
||||
PM_SCRIPTS_GW,
|
||||
|
||||
PM_UNKNOWN
|
||||
};
|
||||
PERMISSION_MODEL PermModelFromString(const std::string &U);
|
||||
std::string PermModelToString(PERMISSION_MODEL U);
|
||||
|
||||
// Map a permission (e.g. create, delete) to true/false
|
||||
typedef std::map<PERMISSION_TYPE, bool> ModelPermissionMap;
|
||||
// Map a model (e.g. venues, devices) to permissions
|
||||
typedef std::map<PERMISSION_MODEL, ModelPermissionMap> PermissionMap;
|
||||
Poco::JSON::Object permissions_to_json(const SecurityObjects::PermissionMap &Map);
|
||||
PermissionMap permissions_from_json(const Poco::JSON::Object::Ptr &Obj);
|
||||
|
||||
struct UserInfo {
|
||||
std::string id;
|
||||
std::string name;
|
||||
@@ -149,6 +224,7 @@ namespace OpenWifi {
|
||||
bool suspended = false;
|
||||
bool blackListed = false;
|
||||
USER_ROLE userRole;
|
||||
PermissionMap userPermissions;
|
||||
UserLoginLoginExtensions userTypeProprietaryInfo;
|
||||
std::string securityPolicy;
|
||||
uint64_t securityPolicyChange = 0;
|
||||
|
||||
@@ -24,7 +24,7 @@ namespace OpenWifi::StateUtils {
|
||||
}
|
||||
|
||||
bool ComputeAssociations(const Poco::JSON::Object::Ptr RawObject, uint64_t &Radios_2G,
|
||||
uint64_t &Radios_5G, uint64_t &Radios_6G) {
|
||||
uint64_t &Radios_5G, uint64_t &Radios_6G, uint64_t &UpTime ) {
|
||||
Radios_2G = 0;
|
||||
Radios_5G = 0;
|
||||
Radios_6G = 0;
|
||||
@@ -90,9 +90,15 @@ namespace OpenWifi::StateUtils {
|
||||
}
|
||||
}
|
||||
}
|
||||
// std::cout << Radios_2G << " " << Radios_5G << " " << Radios_6G << std::endl;
|
||||
return true;
|
||||
}
|
||||
|
||||
if(RawObject->has("unit") && !RawObject->isNull("unit") && RawObject->isObject("unit")) {
|
||||
auto unit = RawObject->getObject("unit");
|
||||
if(unit->has("uptime")) {
|
||||
UpTime = unit->get("uptime");
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
} // namespace OpenWifi::StateUtils
|
||||
@@ -8,5 +8,5 @@
|
||||
|
||||
namespace OpenWifi::StateUtils {
|
||||
bool ComputeAssociations(const Poco::JSON::Object::Ptr RawObject, uint64_t &Radios_2G,
|
||||
uint64_t &Radios_5G, uint64_t &Radio_6G);
|
||||
uint64_t &Radios_5G, uint64_t &Radio_6G, uint64_t &UpTime);
|
||||
}
|
||||
@@ -22,6 +22,8 @@ namespace OpenWifi {
|
||||
ScriptDB_->Create();
|
||||
ScriptDB_->Initialize();
|
||||
|
||||
FixDeviceTypeBug();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -143,26 +143,31 @@ namespace OpenWifi {
|
||||
bool simulated);
|
||||
bool CreateDevice(Poco::Data::Session &Sess, GWObjects::Device &DeviceDetails);
|
||||
|
||||
bool GetDevice(LockedDbSession &Session, std::string &SerialNumber, GWObjects::Device &);
|
||||
bool GetDevice(Poco::Data::Session &Session, std::string &SerialNumber, GWObjects::Device &DeviceDetails);
|
||||
bool GetDevice(std::string &SerialNumber, GWObjects::Device &);
|
||||
bool GetDevice(LockedDbSession &Session, const std::string &SerialNumber, GWObjects::Device &);
|
||||
bool GetDevice(Poco::Data::Session &Session, const std::string &SerialNumber, GWObjects::Device &DeviceDetails);
|
||||
bool GetDevice(const std::string &SerialNumber, GWObjects::Device &);
|
||||
bool GetDevices(uint64_t From, uint64_t HowMany, std::vector<GWObjects::Device> &Devices,
|
||||
const std::string &orderBy = "");
|
||||
const std::string &orderBy = "",
|
||||
const std::string &platform = "",
|
||||
bool includeProvisioned = true);
|
||||
// bool GetDevices(uint64_t From, uint64_t HowMany, const std::string & Select,
|
||||
// std::vector<GWObjects::Device> &Devices, const std::string & orderBy="");
|
||||
bool DeleteDevice(std::string &SerialNumber);
|
||||
bool DeleteDevices(std::string &SerialPattern, bool SimulatedOnly);
|
||||
bool DeleteDevices(std::uint64_t OlderContact, bool SimulatedOnly);
|
||||
std::string GetPlatform(const std::string &SerialNumber);
|
||||
|
||||
bool UpdateDevice(GWObjects::Device &);
|
||||
bool UpdateDevice(LockedDbSession &Session, GWObjects::Device &);
|
||||
bool UpdateDevice(Poco::Data::Session &Sess, GWObjects::Device &NewDeviceDetails);
|
||||
bool DeviceExists(std::string &SerialNumber);
|
||||
bool SetConnectInfo(std::string &SerialNumber, std::string &Firmware);
|
||||
bool GetDeviceCount(uint64_t &Count);
|
||||
bool GetDeviceCount(uint64_t &Count, const std::string &platform = "", bool includeProvisioned = true);
|
||||
bool GetDeviceSerialNumbers(uint64_t From, uint64_t HowMany,
|
||||
std::vector<std::string> &SerialNumbers,
|
||||
const std::string &orderBy = "");
|
||||
const std::string &orderBy = "",
|
||||
const std::string &platform = "",
|
||||
bool includeProvisioned = true);
|
||||
bool GetDeviceFWUpdatePolicy(std::string &SerialNumber, std::string &Policy);
|
||||
bool SetDevicePassword(LockedDbSession &Session, std::string &SerialNumber, std::string &Password);
|
||||
bool UpdateSerialNumberCache();
|
||||
@@ -198,6 +203,7 @@ namespace OpenWifi {
|
||||
bool GetDefaultConfigurations(uint64_t From, uint64_t HowMany,
|
||||
std::vector<GWObjects::DefaultConfiguration> &Devices);
|
||||
bool FindDefaultConfigurationForModel(const std::string &Model,
|
||||
const std::string &Platform,
|
||||
GWObjects::DefaultConfiguration &DefConfig);
|
||||
uint64_t GetDefaultConfigurationsCount();
|
||||
bool DefaultConfigurationAlreadyExists(std::string &Name);
|
||||
@@ -291,6 +297,8 @@ namespace OpenWifi {
|
||||
bool AnalyzeCommands(Types::CountedMap &R);
|
||||
bool AnalyzeDevices(GWObjects::Dashboard &D);
|
||||
|
||||
void FixDeviceTypeBug();
|
||||
|
||||
int Start() override;
|
||||
void Stop() override;
|
||||
|
||||
|
||||
@@ -111,7 +111,6 @@ namespace OpenWifi {
|
||||
}
|
||||
} break;
|
||||
case TelemetryNotification::NotificationType::unregister: {
|
||||
std::lock_guard G(Mutex_);
|
||||
|
||||
auto client = Clients_.find(Notification->Data_);
|
||||
if (client != Clients_.end()) {
|
||||
|
||||
@@ -129,4 +129,26 @@ namespace OpenWifi {
|
||||
return RetrieveApiKeyInformation(SessionToken, UInfo, TID, Expired, Contacted, Suspended);
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a role, remove the cached user info for any user with that role
|
||||
*/
|
||||
void AuthClient::EmptyCacheForRole(const std::string &role) {
|
||||
SecurityObjects::USER_ROLE roleEnum = SecurityObjects::UserTypeFromString(role);
|
||||
Poco::JSON::Object::ConstIterator it;
|
||||
std::set<std::string> tokens = Cache_.getAllKeys();
|
||||
for(const std::string &token : tokens) {
|
||||
auto UInfo = Cache_.get(token);
|
||||
if (UInfo->userinfo.userRole == roleEnum) {
|
||||
Cache_.remove(token);
|
||||
}
|
||||
}
|
||||
|
||||
tokens = ApiKeyCache_.getAllKeys();
|
||||
for(const std::string &token : tokens) {
|
||||
auto UInfo = ApiKeyCache_.get(token);
|
||||
if (UInfo->UserInfo.userinfo.userRole == roleEnum) {
|
||||
ApiKeyCache_.remove(token);
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace OpenWifi
|
||||
@@ -61,6 +61,8 @@ namespace OpenWifi {
|
||||
SecurityObjects::UserInfoAndPolicy &UInfo, std::uint64_t TID,
|
||||
bool &Expired, bool &Contacted, bool &Suspended);
|
||||
|
||||
void EmptyCacheForRole(const std::string &role);
|
||||
|
||||
private:
|
||||
Poco::ExpireLRUCache<std::string, OpenWifi::SecurityObjects::UserInfoAndPolicy> Cache_{
|
||||
512, 1200000};
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -5,7 +5,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "framework/SubSystemServer.h"
|
||||
|
||||
#include "framework/ow_constants.h"
|
||||
#include <valijson/adapters/poco_json_adapter.hpp>
|
||||
#include <valijson/constraints/constraint.hpp>
|
||||
#include <valijson/constraints/constraint_visitor.hpp>
|
||||
@@ -17,33 +17,42 @@
|
||||
namespace OpenWifi {
|
||||
class ConfigurationValidator : public SubSystemServer {
|
||||
public:
|
||||
|
||||
enum class ConfigurationType { AP = 0 , SWITCH = 1};
|
||||
|
||||
static auto instance() {
|
||||
static auto instance_ = new ConfigurationValidator;
|
||||
return instance_;
|
||||
}
|
||||
|
||||
bool Validate(const std::string &C, std::vector<std::string> &Errors, bool Strict);
|
||||
bool Validate(ConfigurationType Type, const std::string &C, std::string &Errors, bool Strict);
|
||||
int Start() override;
|
||||
void Stop() override;
|
||||
void reinitialize(Poco::Util::Application &self) override;
|
||||
|
||||
inline static ConfigurationType GetType(const std::string &type) {
|
||||
std::string Type = Poco::toLower(type);
|
||||
if (Type == Platforms::AP)
|
||||
return ConfigurationType::AP;
|
||||
if (Type == Platforms::SWITCH)
|
||||
return ConfigurationType::SWITCH;
|
||||
return ConfigurationType::AP;
|
||||
}
|
||||
|
||||
private:
|
||||
bool Initialized_ = false;
|
||||
bool Working_ = false;
|
||||
void Init();
|
||||
std::unique_ptr<valijson::Schema> RootSchema_;
|
||||
std::unique_ptr<valijson::SchemaParser> SchemaParser_;
|
||||
std::unique_ptr<valijson::adapters::PocoJsonAdapter> PocoJsonAdapter_;
|
||||
Poco::JSON::Object::Ptr SchemaDocPtr_;
|
||||
bool SetSchema(const std::string &SchemaStr);
|
||||
std::array<valijson::Schema,2> RootSchema_;
|
||||
bool SetSchema(ConfigurationType Type, const std::string &SchemaStr);
|
||||
|
||||
ConfigurationValidator()
|
||||
: SubSystemServer("ConfigValidator", "CFG-VALIDATOR", "config.validator") {}
|
||||
};
|
||||
|
||||
inline auto ConfigurationValidator() { return ConfigurationValidator::instance(); }
|
||||
inline bool ValidateUCentralConfiguration(const std::string &C, std::vector<std::string> &Error,
|
||||
inline bool ValidateUCentralConfiguration(ConfigurationValidator::ConfigurationType Type, const std::string &C, std::string &Errors,
|
||||
bool strict) {
|
||||
return ConfigurationValidator::instance()->Validate(C, Error, strict);
|
||||
return ConfigurationValidator::instance()->Validate(Type, C, Errors, strict);
|
||||
}
|
||||
} // namespace OpenWifi
|
||||
|
||||
@@ -16,9 +16,9 @@ namespace OpenWifi {
|
||||
KafkaManager()->PostMessage(KafkaTopics::SERVICE_EVENTS, MicroServicePrivateEndPoint(), Msg,
|
||||
false);
|
||||
while (Running_) {
|
||||
Poco::Thread::trySleep((unsigned long)MicroServiceDaemonBusTimer());
|
||||
if (!Running_)
|
||||
break;
|
||||
if(!Poco::Thread::trySleep((unsigned long)MicroServiceDaemonBusTimer())) {
|
||||
break;
|
||||
}
|
||||
Msg = (MicroServiceMakeSystemEventMessage(KafkaTopics::ServiceEvents::EVENT_KEEP_ALIVE));
|
||||
KafkaManager()->PostMessage(KafkaTopics::SERVICE_EVENTS, MicroServicePrivateEndPoint(),
|
||||
Msg, false);
|
||||
@@ -29,7 +29,7 @@ namespace OpenWifi {
|
||||
};
|
||||
|
||||
void EventBusManager::Start() {
|
||||
poco_information(Logger(), "Starting...");
|
||||
poco_information(Logger_, "Starting...");
|
||||
if (KafkaManager()->Enabled()) {
|
||||
Thread_.start(*this);
|
||||
}
|
||||
@@ -37,11 +37,11 @@ namespace OpenWifi {
|
||||
|
||||
void EventBusManager::Stop() {
|
||||
if (KafkaManager()->Enabled()) {
|
||||
poco_information(Logger(), "Stopping...");
|
||||
poco_information(Logger_, "Stopping...");
|
||||
Running_ = false;
|
||||
Thread_.wakeUp();
|
||||
Thread_.join();
|
||||
poco_information(Logger(), "Stopped...");
|
||||
poco_information(Logger_, "Stopped...");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -22,7 +22,6 @@ namespace OpenWifi {
|
||||
return instance_;
|
||||
}
|
||||
|
||||
explicit EventBusManager(Poco::Logger &L);
|
||||
void run() final;
|
||||
void Start();
|
||||
void Stop();
|
||||
|
||||
@@ -79,8 +79,10 @@ namespace OpenWifi {
|
||||
Utils::SetThreadName("Kafka:Prod");
|
||||
cppkafka::Configuration Config(
|
||||
{{"client.id", MicroServiceConfigGetString("openwifi.kafka.client.id", "")},
|
||||
{"metadata.broker.list",
|
||||
MicroServiceConfigGetString("openwifi.kafka.brokerlist", "")}});
|
||||
{"metadata.broker.list",MicroServiceConfigGetString("openwifi.kafka.brokerlist", "")} // ,
|
||||
// {"send.buffer.bytes", KafkaManager()->KafkaManagerMaximumPayloadSize() }
|
||||
}
|
||||
);
|
||||
|
||||
AddKafkaSecurity(Config);
|
||||
|
||||
@@ -105,7 +107,16 @@ namespace OpenWifi {
|
||||
NewMessage.partition(0);
|
||||
NewMessage.payload(Msg->Payload());
|
||||
Producer.produce(NewMessage);
|
||||
Producer.flush();
|
||||
if (Queue_.size() < 100) {
|
||||
// use flush when internal queue is lightly loaded, i.e. flush after each
|
||||
// message
|
||||
Producer.flush();
|
||||
}
|
||||
else {
|
||||
// use poll when internal queue is loaded to allow messages to be sent in
|
||||
// batches
|
||||
Producer.poll((std::chrono::milliseconds) 0);
|
||||
}
|
||||
}
|
||||
} catch (const cppkafka::HandleException &E) {
|
||||
poco_warning(Logger_,
|
||||
@@ -115,8 +126,13 @@ namespace OpenWifi {
|
||||
} catch (...) {
|
||||
poco_error(Logger_, "std::exception");
|
||||
}
|
||||
if (Queue_.size() == 0) {
|
||||
// message queue is empty, flush all previously sent messages
|
||||
Producer.flush();
|
||||
}
|
||||
Note = Queue_.waitDequeueNotification();
|
||||
}
|
||||
Producer.flush();
|
||||
poco_information(Logger_, "Stopped...");
|
||||
}
|
||||
|
||||
@@ -275,6 +291,7 @@ namespace OpenWifi {
|
||||
int KafkaManager::Start() {
|
||||
if (!KafkaEnabled_)
|
||||
return 0;
|
||||
MaxPayloadSize_ = MicroServiceConfigGetInt("openwifi.kafka.max.payload", 250000);
|
||||
ConsumerThr_.Start();
|
||||
ProducerThr_.Start();
|
||||
return 0;
|
||||
@@ -321,4 +338,4 @@ namespace OpenWifi {
|
||||
partitions.front().get_partition()));
|
||||
}
|
||||
|
||||
} // namespace OpenWifi
|
||||
} // namespace OpenWifi
|
||||
|
||||
@@ -94,11 +94,14 @@ namespace OpenWifi {
|
||||
return ConsumerThr_.UnregisterTopicWatcher(Topic,Id);
|
||||
}
|
||||
|
||||
std::uint64_t KafkaManagerMaximumPayloadSize() const { return MaxPayloadSize_; }
|
||||
|
||||
private:
|
||||
bool KafkaEnabled_ = false;
|
||||
std::string SystemInfoWrapper_;
|
||||
KafkaProducer ProducerThr_;
|
||||
KafkaConsumer ConsumerThr_;
|
||||
std::uint64_t MaxPayloadSize_ = 250000;
|
||||
|
||||
void PartitionAssignment(const cppkafka::TopicPartitionList &partitions);
|
||||
void PartitionRevocation(const cppkafka::TopicPartitionList &partitions);
|
||||
|
||||
@@ -27,6 +27,7 @@ namespace OpenWifi::KafkaTopics {
|
||||
inline const char * EVENT_LEAVE = "leave";
|
||||
inline const char * EVENT_KEEP_ALIVE = "keep-alive";
|
||||
inline const char * EVENT_REMOVE_TOKEN = "remove-token";
|
||||
inline const char * EVENT_PERMISSIONS_UPDATE = "permissions-update";
|
||||
|
||||
namespace Fields {
|
||||
inline const char * EVENT = "event";
|
||||
@@ -37,6 +38,7 @@ namespace OpenWifi::KafkaTopics {
|
||||
inline const char * KEY = "key";
|
||||
inline const char * VRSN = "version";
|
||||
inline const char * TOKEN = "token";
|
||||
inline const char * ROLE = "role";
|
||||
} // namespace Fields
|
||||
} // namespace ServiceEvents
|
||||
} // namespace OpenWifi::KafkaTopics
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
//
|
||||
//
|
||||
// Created by stephane bourque on 2022-10-26.
|
||||
//
|
||||
|
||||
@@ -29,11 +30,13 @@
|
||||
#include "framework/WebSocketLogger.h"
|
||||
#include "framework/utils.h"
|
||||
|
||||
#ifdef USE_MEDUSA_CLIENT
|
||||
#include <medusa/MedusaClient.h>
|
||||
#endif
|
||||
|
||||
namespace OpenWifi {
|
||||
|
||||
void MicroService::Exit(int Reason) { std::exit(Reason); }
|
||||
|
||||
static std::string MakeServiceListString(const Types::MicroServiceMetaMap &Services) {
|
||||
static std::string MakeServiceListString(const Types::MicroServiceMetaMap &Services) {
|
||||
std::string SvcList;
|
||||
for (const auto &Svc : Services) {
|
||||
if (SvcList.empty())
|
||||
@@ -152,6 +155,16 @@ namespace OpenWifi {
|
||||
BusLogger,
|
||||
fmt::format("KAFKA-MSG: invalid event '{}', missing token", Event));
|
||||
}
|
||||
} else if (Event == KafkaTopics::ServiceEvents::EVENT_PERMISSIONS_UPDATE) {
|
||||
if (Object->has(KafkaTopics::ServiceEvents::Fields::ROLE)) {
|
||||
// Permissions of this role have updated, cached user info is now invalid
|
||||
AuthClient()->EmptyCacheForRole(
|
||||
Object->get(KafkaTopics::ServiceEvents::Fields::ROLE).toString());
|
||||
} else {
|
||||
poco_information(
|
||||
logger(),
|
||||
fmt::format("KAFKA-MSG: invalid event '{}', missing role", Event));
|
||||
}
|
||||
} else {
|
||||
poco_information(BusLogger,
|
||||
fmt::format("Unknown Event: {} Source: {}", Event, ID));
|
||||
@@ -204,25 +217,29 @@ namespace OpenWifi {
|
||||
Res.push_back(ServiceRec);
|
||||
}
|
||||
return Res;
|
||||
|
||||
}
|
||||
|
||||
void MicroService::LoadConfigurationFile() {
|
||||
std::string Location = Poco::Environment::get(DAEMON_CONFIG_ENV_VAR, ".");
|
||||
ConfigFileName_ =
|
||||
ConfigFileName_.empty() ? Location + "/" + DAEMON_PROPERTIES_FILENAME : ConfigFileName_;
|
||||
Poco::Path ConfigFile(ConfigFileName_);
|
||||
if(ConfigContent_.empty()) {
|
||||
std::string Location = Poco::Environment::get(DAEMON_CONFIG_ENV_VAR, ".");
|
||||
ConfigFileName_ =
|
||||
ConfigFileName_.empty() ? Location + "/" + DAEMON_PROPERTIES_FILENAME : ConfigFileName_;
|
||||
Poco::Path ConfigFile(ConfigFileName_);
|
||||
|
||||
if (!ConfigFile.isFile()) {
|
||||
std::cerr << DAEMON_APP_NAME << ": Configuration " << ConfigFile.toString()
|
||||
<< " does not seem to exist. Please set " + DAEMON_CONFIG_ENV_VAR +
|
||||
" env variable the path of the " + DAEMON_PROPERTIES_FILENAME +
|
||||
" file."
|
||||
<< std::endl;
|
||||
std::exit(Poco::Util::Application::EXIT_CONFIG);
|
||||
}
|
||||
|
||||
// loadConfiguration(ConfigFile.toString());
|
||||
PropConfigurationFile_ = new Poco::Util::PropertyFileConfiguration(ConfigFile.toString());
|
||||
if (!ConfigFile.isFile()) {
|
||||
std::cerr << DAEMON_APP_NAME << ": Configuration " << ConfigFile.toString()
|
||||
<< " does not seem to exist. Please set " + DAEMON_CONFIG_ENV_VAR +
|
||||
" env variable the path of the " + DAEMON_PROPERTIES_FILENAME +
|
||||
" file."
|
||||
<< std::endl;
|
||||
std::exit(Poco::Util::Application::EXIT_CONFIG);
|
||||
}
|
||||
PropConfigurationFile_ = new Poco::Util::PropertyFileConfiguration(ConfigFile.toString());
|
||||
} else {
|
||||
std::istringstream is(ConfigContent_);
|
||||
PropConfigurationFile_ = new Poco::Util::PropertyFileConfiguration(is);
|
||||
}
|
||||
configPtr()->addWriteable(PropConfigurationFile_, PRIO_DEFAULT);
|
||||
}
|
||||
|
||||
@@ -425,49 +442,69 @@ namespace OpenWifi {
|
||||
|
||||
void DaemonPostInitialization(Poco::Util::Application &self);
|
||||
|
||||
void MicroService::initialize(Poco::Util::Application &self) {
|
||||
// add the default services
|
||||
LoadConfigurationFile();
|
||||
InitializeLoggingSystem();
|
||||
void MicroService::StartEverything(Poco::Util::Application &self) {
|
||||
LoadConfigurationFile();
|
||||
InitializeLoggingSystem();
|
||||
|
||||
SubSystems_.push_back(KafkaManager());
|
||||
SubSystems_.push_back(ALBHealthCheckServer());
|
||||
SubSystems_.push_back(RESTAPI_ExtServer());
|
||||
SubSystems_.push_back(RESTAPI_IntServer());
|
||||
static bool InitializedBaseService=false;
|
||||
if(!InitializedBaseService) {
|
||||
InitializedBaseService = true;
|
||||
SubSystems_.push_back(KafkaManager());
|
||||
SubSystems_.push_back(ALBHealthCheckServer());
|
||||
SubSystems_.push_back(RESTAPI_ExtServer());
|
||||
SubSystems_.push_back(RESTAPI_IntServer());
|
||||
#ifndef TIP_SECURITY_SERVICE
|
||||
SubSystems_.push_back(AuthClient());
|
||||
SubSystems_.push_back(AuthClient());
|
||||
#endif
|
||||
Poco::Net::initializeSSL();
|
||||
Poco::Net::HTTPStreamFactory::registerFactory();
|
||||
Poco::Net::HTTPSStreamFactory::registerFactory();
|
||||
Poco::Net::FTPStreamFactory::registerFactory();
|
||||
Poco::Net::FTPSStreamFactory::registerFactory();
|
||||
|
||||
Poco::File DataDir(ConfigPath("openwifi.system.data"));
|
||||
DataDir_ = DataDir.path();
|
||||
if (!DataDir.exists()) {
|
||||
try {
|
||||
DataDir.createDirectory();
|
||||
} catch (const Poco::Exception &E) {
|
||||
Logger_.log(E);
|
||||
}
|
||||
}
|
||||
WWWAssetsDir_ = ConfigPath("openwifi.restapi.wwwassets", "");
|
||||
if (WWWAssetsDir_.empty())
|
||||
WWWAssetsDir_ = DataDir_;
|
||||
Poco::Net::initializeSSL();
|
||||
Poco::Net::HTTPStreamFactory::registerFactory();
|
||||
Poco::Net::HTTPSStreamFactory::registerFactory();
|
||||
Poco::Net::FTPStreamFactory::registerFactory();
|
||||
Poco::Net::FTPSStreamFactory::registerFactory();
|
||||
}
|
||||
|
||||
LoadMyConfig();
|
||||
Poco::File DataDir(ConfigPath("openwifi.system.data"));
|
||||
DataDir_ = DataDir.path();
|
||||
if (!DataDir.exists()) {
|
||||
try {
|
||||
DataDir.createDirectory();
|
||||
} catch (const Poco::Exception &E) {
|
||||
Logger_.log(E);
|
||||
}
|
||||
}
|
||||
WWWAssetsDir_ = ConfigPath("openwifi.restapi.wwwassets", "");
|
||||
if (WWWAssetsDir_.empty())
|
||||
WWWAssetsDir_ = DataDir_;
|
||||
|
||||
AllowExternalMicroServices_ = ConfigGetBool("allowexternalmicroservices", true);
|
||||
LoadMyConfig();
|
||||
|
||||
InitializeSubSystemServers();
|
||||
ServerApplication::initialize(self);
|
||||
DaemonPostInitialization(self);
|
||||
AllowExternalMicroServices_ = ConfigGetBool("allowexternalmicroservices", true);
|
||||
|
||||
Types::TopicNotifyFunction F = [this](const std::string &Key, const std::string &Payload) {
|
||||
this->BusMessageReceived(Key, Payload);
|
||||
};
|
||||
KafkaManager()->RegisterTopicWatcher(KafkaTopics::SERVICE_EVENTS, F);
|
||||
InitializeSubSystemServers();
|
||||
ServerApplication::initialize(self);
|
||||
DaemonPostInitialization(self);
|
||||
|
||||
Types::TopicNotifyFunction F = [this](const std::string &Key, const std::string &Payload) {
|
||||
this->BusMessageReceived(Key, Payload);
|
||||
};
|
||||
KafkaManager()->RegisterTopicWatcher(KafkaTopics::SERVICE_EVENTS, F);
|
||||
}
|
||||
|
||||
void MicroService::StopEverything([[maybe_unused]] Poco::Util::Application &self) {
|
||||
LoadConfigurationFile();
|
||||
InitializeLoggingSystem();
|
||||
|
||||
Types::TopicNotifyFunction F = [this](const std::string &Key, const std::string &Payload) {
|
||||
this->BusMessageReceived(Key, Payload);
|
||||
};
|
||||
KafkaManager()->RegisterTopicWatcher(KafkaTopics::SERVICE_EVENTS, F);
|
||||
}
|
||||
|
||||
void MicroService::initialize([[maybe_unused]] Poco::Util::Application &self) {
|
||||
#ifndef USE_MEDUSA_CLIENT
|
||||
StartEverything(self);
|
||||
#endif
|
||||
}
|
||||
|
||||
void MicroService::uninitialize() {
|
||||
@@ -753,6 +790,8 @@ namespace OpenWifi {
|
||||
MicroServiceErrorHandler ErrorHandler(*this);
|
||||
Poco::ErrorHandler::set(&ErrorHandler);
|
||||
|
||||
Args_ = args;
|
||||
|
||||
if (!HelpRequested_) {
|
||||
SavePID();
|
||||
|
||||
@@ -768,11 +807,18 @@ namespace OpenWifi {
|
||||
poco_information(logger, "Starting as a daemon.");
|
||||
}
|
||||
|
||||
#ifdef USE_MEDUSA_CLIENT
|
||||
MedusaClient::instance()->SetSubSystems(SubSystems_);
|
||||
MedusaClient::instance()->Start();
|
||||
waitForTerminationRequest();
|
||||
MedusaClient::instance()->Stop();
|
||||
#else
|
||||
poco_information(logger, fmt::format("System ID set to {}", ID_));
|
||||
StartSubSystemServers();
|
||||
waitForTerminationRequest();
|
||||
StopSubSystemServers();
|
||||
logger.notice(fmt::format("Stopped {}...", DAEMON_APP_NAME));
|
||||
#endif
|
||||
}
|
||||
|
||||
return Application::EXIT_OK;
|
||||
|
||||
@@ -55,9 +55,6 @@ namespace OpenWifi {
|
||||
#include "nlohmann/json.hpp"
|
||||
#include "ow_version.h"
|
||||
|
||||
#define _OWDEBUG_ std::cout << __FILE__ << ":" << __LINE__ << std::endl;
|
||||
// #define _OWDEBUG_ Logger().debug(Poco::format("%s: %lu",__FILE__,__LINE__));
|
||||
|
||||
namespace OpenWifi {
|
||||
|
||||
class MicroService : public Poco::Util::ServerApplication {
|
||||
@@ -70,7 +67,6 @@ namespace OpenWifi {
|
||||
SubSystems_(std::move(Subsystems)), Logger_(Poco::Logger::get("FRAMEWORK")) {
|
||||
instance_ = this;
|
||||
RandomEngine_.seed(std::chrono::steady_clock::now().time_since_epoch().count());
|
||||
// Logger_ = Poco::Logger::root().get("BASE-SVC");
|
||||
}
|
||||
|
||||
inline static const char *ExtraConfigurationFilename = "/configuration_override.json";
|
||||
@@ -92,7 +88,7 @@ namespace OpenWifi {
|
||||
inline uint64_t DaemonBusTimer() const { return DAEMON_BUS_TIMER; };
|
||||
[[nodiscard]] const std::string &AppName() { return DAEMON_APP_NAME; }
|
||||
static inline uint64_t GetPID() { return Poco::Process::id(); };
|
||||
[[nodiscard]] inline const std::string GetPublicAPIEndPoint() {
|
||||
[[nodiscard]] inline std::string GetPublicAPIEndPoint() const {
|
||||
return MyPublicEndPoint_ + "/api/v1";
|
||||
};
|
||||
[[nodiscard]] inline const std::string &GetUIURI() const { return UIURI_; };
|
||||
@@ -107,7 +103,8 @@ namespace OpenWifi {
|
||||
}
|
||||
static MicroService &instance() { return *instance_; }
|
||||
|
||||
inline void Exit(int Reason);
|
||||
inline void Exit(int Reason) { std::exit(Reason); }
|
||||
|
||||
void BusMessageReceived(const std::string &Key, const std::string &Payload);
|
||||
Types::MicroServiceMetaVec GetServices(const std::string &Type);
|
||||
Types::MicroServiceMetaVec GetServices();
|
||||
@@ -115,7 +112,9 @@ namespace OpenWifi {
|
||||
void Reload();
|
||||
void LoadMyConfig();
|
||||
void initialize(Poco::Util::Application &self) override;
|
||||
void uninitialize() override;
|
||||
void StartEverything(Poco::Util::Application &self);
|
||||
void StopEverything(Poco::Util::Application &self);
|
||||
void uninitialize() override;
|
||||
void reinitialize(Poco::Util::Application &self) override;
|
||||
void defineOptions(Poco::Util::OptionSet &options) override;
|
||||
void handleHelp(const std::string &name, const std::string &value);
|
||||
@@ -132,7 +131,7 @@ namespace OpenWifi {
|
||||
void Reload(const std::string &Sub);
|
||||
Types::StringVec GetSubSystems() const;
|
||||
Types::StringPairVec GetLogLevels();
|
||||
const Types::StringVec &GetLogLevelNames();
|
||||
static const Types::StringVec &GetLogLevelNames();
|
||||
uint64_t ConfigGetInt(const std::string &Key, uint64_t Default);
|
||||
uint64_t ConfigGetInt(const std::string &Key);
|
||||
uint64_t ConfigGetBool(const std::string &Key, bool Default);
|
||||
@@ -166,12 +165,25 @@ namespace OpenWifi {
|
||||
const std::string &FormatterPattern,
|
||||
const std::string &root_env_var);
|
||||
inline bool AllowExternalMicroServices() const { return AllowExternalMicroServices_; }
|
||||
const ArgVec &Args() const { return Args_; }
|
||||
|
||||
inline void SetConfigContent(const std::string &Content) { ConfigContent_ = Content; }
|
||||
|
||||
inline std::optional<OpenWifi::Types::MicroServiceMeta> GetPrivateEndPointServiceKey( const std::string & ServicePrivateEndPoint ) {
|
||||
std::lock_guard G(InfraMutex_);
|
||||
auto K = Services_.find(ServicePrivateEndPoint);
|
||||
if(K==end(Services_)) {
|
||||
return std::nullopt;
|
||||
}
|
||||
return K->second;
|
||||
}
|
||||
|
||||
private:
|
||||
static MicroService *instance_;
|
||||
bool HelpRequested_ = false;
|
||||
std::string LogDir_;
|
||||
std::string ConfigFileName_;
|
||||
std::string ConfigContent_;
|
||||
uint64_t ID_ = 1;
|
||||
Poco::SharedPtr<Poco::Crypto::RSAKey> AppKey_;
|
||||
bool DebugMode_ = false;
|
||||
@@ -201,6 +213,7 @@ namespace OpenWifi {
|
||||
Poco::JWT::Signer Signer_;
|
||||
Poco::Logger &Logger_;
|
||||
Poco::ThreadPool TimerPool_{"timer:pool", 2, 32};
|
||||
ArgVec Args_;
|
||||
};
|
||||
|
||||
inline MicroService *MicroService::instance_ = nullptr;
|
||||
|
||||
@@ -133,4 +133,8 @@ namespace OpenWifi {
|
||||
return MicroService::instance().Hash();
|
||||
}
|
||||
|
||||
std::optional<OpenWifi::Types::MicroServiceMeta> MicroServicePrivateAccessKey(const std::string &servicePrivateEndPoint) {
|
||||
return MicroService::instance().GetPrivateEndPointServiceKey(servicePrivateEndPoint);
|
||||
}
|
||||
|
||||
} // namespace OpenWifi
|
||||
|
||||
@@ -23,7 +23,9 @@ namespace OpenWifi {
|
||||
std::string MicroServiceConfigGetString(const std::string &Key,
|
||||
const std::string &DefaultValue);
|
||||
std::string MicroServiceAccessKey();
|
||||
bool MicroServiceConfigGetBool(const std::string &Key, bool DefaultValue);
|
||||
std::optional<OpenWifi::Types::MicroServiceMeta> MicroServicePrivateAccessKey(const std::string &servicePrivateEndPoint);
|
||||
|
||||
bool MicroServiceConfigGetBool(const std::string &Key, bool DefaultValue);
|
||||
std::uint64_t MicroServiceConfigGetInt(const std::string &Key, std::uint64_t DefaultValue);
|
||||
std::string MicroServicePrivateEndPoint();
|
||||
std::uint64_t MicroServiceID();
|
||||
|
||||
@@ -60,9 +60,52 @@ namespace OpenWifi {
|
||||
AlwaysAuthorize_(AlwaysAuthorize), Server_(Server), MyRates_(Profile),
|
||||
TransactionId_(TransactionId) {}
|
||||
|
||||
inline int nthOccurrence(const std::string& str, const std::string& findMe, int nth) {
|
||||
/*
|
||||
Helper function to get the index of the nth occurence of string findMe in string str.
|
||||
if there are not n occurrences of findMe in str, returns -1.
|
||||
*/
|
||||
size_t pos = 0;
|
||||
int count = 0;
|
||||
|
||||
while(count != nth)
|
||||
{
|
||||
pos+=1;
|
||||
pos = str.find(findMe, pos);
|
||||
if (pos == std::string::npos)
|
||||
return -1;
|
||||
count++;
|
||||
}
|
||||
return pos;
|
||||
}
|
||||
|
||||
inline bool RoleIsAuthorized([[maybe_unused]] const std::string &Path,
|
||||
[[maybe_unused]] const std::string &Method,
|
||||
[[maybe_unused]] std::string &Reason) {
|
||||
// If user role is admin or root, authorized is true
|
||||
if (UserInfo_.userinfo.userRole == SecurityObjects::USER_ROLE::ADMIN || UserInfo_.userinfo.userRole == SecurityObjects::USER_ROLE::ROOT) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// We just want the /api/v1/x part of the path so we need to account for
|
||||
// extra path variables as well as query variables.
|
||||
std::string pathstubtmp = Path.substr(0, nthOccurrence(Path, "/", 3));
|
||||
std::string pathstub = pathstubtmp.substr(0, nthOccurrence(pathstubtmp, "?", 1));
|
||||
|
||||
// Next check the pathstub against the whitelist
|
||||
if (SecurityObjects::API_WHITELIST.find(pathstub) != SecurityObjects::API_WHITELIST.end()) {
|
||||
std::set<std::string> allowed_methods = SecurityObjects::API_WHITELIST.at(pathstub);
|
||||
// The API stub is in the whitelist, but we also need to check that this method is whitelisted for this stub.
|
||||
if (allowed_methods.find(Method) != allowed_methods.end()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// At this point, the user is not root/admin and the API + method is not whitelisted, so we disallow any method that is not a GET.
|
||||
if (Method != Poco::Net::HTTPRequest::HTTP_GET) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -552,8 +595,8 @@ namespace OpenWifi {
|
||||
|
||||
inline bool IsAuthorized(bool &Expired, bool &Contacted, bool SubOnly = false);
|
||||
|
||||
inline void ReturnObject(Poco::JSON::Object &Object) {
|
||||
PrepareResponse();
|
||||
inline void ReturnObject(Poco::JSON::Object &Object, Poco::Net::HTTPResponse::HTTPStatus Status = Poco::Net::HTTPResponse::HTTP_OK) {
|
||||
PrepareResponse(Status);
|
||||
if (Request != nullptr) {
|
||||
// can we compress ???
|
||||
auto AcceptedEncoding = Request->find("Accept-Encoding");
|
||||
|
||||
@@ -58,11 +58,9 @@ namespace OpenWifi {
|
||||
void UI_WebSocketClientServer::run() {
|
||||
Running_ = true;
|
||||
while (Running_) {
|
||||
Poco::Thread::trySleep(2000);
|
||||
|
||||
if (!Running_)
|
||||
break;
|
||||
|
||||
if(!Poco::Thread::trySleep(2000)) {
|
||||
break;
|
||||
}
|
||||
std::lock_guard G(LocalMutex_);
|
||||
for (const auto i : ToBeRemoved_) {
|
||||
// std::cout << "Erasing old WS UI connection..." << std::endl;
|
||||
|
||||
@@ -7,57 +7,59 @@
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
#include "ow_constants.h"
|
||||
|
||||
namespace OpenWifi {
|
||||
inline const std::vector<std::pair<std::string, std::string>> DefaultDeviceTypeList{
|
||||
{"actiontec_web7200", "AP"},
|
||||
{"cig_wf186w", "AP"},
|
||||
{"cig_wf188n", "AP"},
|
||||
{"cig_wf194c4", "AP"},
|
||||
{"cig_wf196", "AP"},
|
||||
{"cig_wf196-ca", "AP"},
|
||||
{"cig_wf196-ca-ath12", "AP"},
|
||||
{"cig_wf196-us", "AP"},
|
||||
{"cig_wf610d", "AP"},
|
||||
{"cig_wf660a", "AP"},
|
||||
{"cig_wf808", "AP"},
|
||||
{"cybertan_eww622-a1", "AP"},
|
||||
{"edgecore_eap101", "AP"},
|
||||
{"edgecore_eap101-ath12", "AP"},
|
||||
{"edgecore_eap102", "AP"},
|
||||
{"edgecore_eap104", "AP"},
|
||||
{"edgecore_eap104-ath12", "AP"},
|
||||
{"edgecore_ecs4100-12ph", "AP"},
|
||||
{"edgecore_ecw5211", "AP"},
|
||||
{"edgecore_ecw5410", "AP"},
|
||||
{"edgecore_oap100", "AP"},
|
||||
{"edgecore_spw2ac1200", "SWITCH"},
|
||||
{"edgecore_spw2ac1200-lan-poe", "SWITCH"},
|
||||
{"edgecore_ssw2ac2600", "SWITCH"},
|
||||
{"hfcl_ion4", "AP"},
|
||||
{"hfcl_ion4x", "AP"},
|
||||
{"hfcl_ion4x_2", "AP"},
|
||||
{"hfcl_ion4xe", "AP"},
|
||||
{"hfcl_ion4xi", "AP"},
|
||||
{"indio_um-305ac", "AP"},
|
||||
{"indio_um-305ax", "AP"},
|
||||
{"indio_um-310ax-v1", "AP"},
|
||||
{"indio_um-325ac", "AP"},
|
||||
{"indio_um-510ac-v3", "AP"},
|
||||
{"indio_um-510axm-v1", "AP"},
|
||||
{"indio_um-510axp-v1", "AP"},
|
||||
{"indio_um-550ac", "AP"},
|
||||
{"linksys_e8450-ubi", "AP"},
|
||||
{"linksys_ea6350-v4", "AP"},
|
||||
{"linksys_ea8300", "AP"},
|
||||
{"liteon_wpx8324", "AP"},
|
||||
{"meshpp_s618_cp01", "AP"},
|
||||
{"meshpp_s618_cp03", "AP"},
|
||||
{"udaya_a5-id2", "AP"},
|
||||
{"wallys_dr40x9", "AP"},
|
||||
{"wallys_dr6018", "AP"},
|
||||
{"wallys_dr6018_v4", "AP"},
|
||||
{"x64_vm", "AP"},
|
||||
{"yuncore_ax840", "AP"},
|
||||
{"yuncore_fap640", "AP"},
|
||||
{"yuncore_fap650", "AP"}};
|
||||
{"actiontec_web7200", Platforms::AP},
|
||||
{"cig_wf186w", Platforms::AP},
|
||||
{"cig_wf188n", Platforms::AP},
|
||||
{"cig_wf194c4", Platforms::AP},
|
||||
{"cig_wf196", Platforms::AP},
|
||||
{"cig_wf196-ca", Platforms::AP},
|
||||
{"cig_wf196-ca-ath12", Platforms::AP},
|
||||
{"cig_wf196-us", Platforms::AP},
|
||||
{"cig_wf610d", Platforms::AP},
|
||||
{"cig_wf660a", Platforms::AP},
|
||||
{"cig_wf808", Platforms::AP},
|
||||
{"cybertan_eww622-a1", Platforms::AP},
|
||||
{"edgecore_eap101", Platforms::AP},
|
||||
{"edgecore_eap101-ath12", Platforms::AP},
|
||||
{"edgecore_eap102", Platforms::AP},
|
||||
{"edgecore_eap104", Platforms::AP},
|
||||
{"edgecore_eap104-ath12", Platforms::AP},
|
||||
{"edgecore_ecs4100-12ph", Platforms::AP},
|
||||
{"edgecore_ecw5211", Platforms::AP},
|
||||
{"edgecore_ecw5410", Platforms::AP},
|
||||
{"edgecore_oap100", Platforms::AP},
|
||||
{"edgecore_spw2ac1200", Platforms::SWITCH},
|
||||
{"edgecore_spw2ac1200-lan-poe", Platforms::SWITCH},
|
||||
{"edgecore_ssw2ac2600", Platforms::SWITCH},
|
||||
{"hfcl_ion4", Platforms::AP},
|
||||
{"hfcl_ion4x", Platforms::AP},
|
||||
{"hfcl_ion4x_2", Platforms::AP},
|
||||
{"hfcl_ion4xe", Platforms::AP},
|
||||
{"hfcl_ion4xi", Platforms::AP},
|
||||
{"indio_um-305ac", Platforms::AP},
|
||||
{"indio_um-305ax", Platforms::AP},
|
||||
{"indio_um-310ax-v1", Platforms::AP},
|
||||
{"indio_um-325ac", Platforms::AP},
|
||||
{"indio_um-510ac-v3", Platforms::AP},
|
||||
{"indio_um-510axm-v1", Platforms::AP},
|
||||
{"indio_um-510axp-v1", Platforms::AP},
|
||||
{"indio_um-550ac", Platforms::AP},
|
||||
{"linksys_e8450-ubi", Platforms::AP},
|
||||
{"linksys_ea6350-v4", Platforms::AP},
|
||||
{"linksys_ea8300", Platforms::AP},
|
||||
{"liteon_wpx8324", Platforms::AP},
|
||||
{"meshpp_s618_cp01", Platforms::AP},
|
||||
{"meshpp_s618_cp03", Platforms::AP},
|
||||
{"udaya_a5-id2", Platforms::AP},
|
||||
{"wallys_dr40x9", Platforms::AP},
|
||||
{"wallys_dr6018", Platforms::AP},
|
||||
{"wallys_dr6018_v4", Platforms::AP},
|
||||
{"x64_vm", Platforms::AP},
|
||||
{"yuncore_ax840", Platforms::AP},
|
||||
{"yuncore_fap640", Platforms::AP},
|
||||
{"yuncore_fap650", Platforms::AP}};
|
||||
}
|
||||
|
||||
@@ -565,6 +565,7 @@ namespace OpenWifi::RESTAPI::Protocol {
|
||||
|
||||
static const char *TRANSFER = "transfer";
|
||||
static const char *CERTUPDATE = "certupdate";
|
||||
static const char *POWERCYCLE = "powercycle";
|
||||
static const char *RRM = "rrm";
|
||||
|
||||
static const char *REQUIREMENTS = "requirements";
|
||||
@@ -687,6 +688,7 @@ namespace OpenWifi::uCentralProtocol {
|
||||
|
||||
static const char *TRANSFER = "transfer";
|
||||
static const char *CERTUPDATE = "certupdate";
|
||||
static const char *POWERCYCLE = "powercycle";
|
||||
static const char *RRM = "rrm";
|
||||
static const char *ACTIONS = "actions";
|
||||
|
||||
@@ -785,6 +787,7 @@ namespace OpenWifi::APCommands {
|
||||
rrm,
|
||||
certupdate,
|
||||
transfer,
|
||||
powercycle,
|
||||
unknown
|
||||
};
|
||||
|
||||
@@ -799,7 +802,7 @@ namespace OpenWifi::APCommands {
|
||||
RESTAPI::Protocol::EVENTQUEUE, RESTAPI::Protocol::TELEMETRY,
|
||||
RESTAPI::Protocol::PING, RESTAPI::Protocol::SCRIPT,
|
||||
RESTAPI::Protocol::RRM, RESTAPI::Protocol::CERTUPDATE,
|
||||
RESTAPI::Protocol::TRANSFER
|
||||
RESTAPI::Protocol::TRANSFER, RESTAPI::Protocol::POWERCYCLE
|
||||
};
|
||||
|
||||
inline const char *to_string(Commands Cmd) { return uCentralAPCommands[(uint8_t)Cmd]; }
|
||||
@@ -828,6 +831,11 @@ namespace OpenWifi::Provisioning::DeviceClass {
|
||||
|
||||
} // namespace OpenWifi::Provisioning::DeviceClass
|
||||
|
||||
namespace OpenWifi::Platforms {
|
||||
static const std::string AP = "ap";
|
||||
static const std::string SWITCH = "switch";
|
||||
}
|
||||
|
||||
#if defined(__GNUC__)
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
@@ -19,37 +19,39 @@ namespace OpenWifi {
|
||||
"Models TEXT, "
|
||||
"Description TEXT, "
|
||||
"Created BIGINT , "
|
||||
"LastModified BIGINT)"};
|
||||
"LastModified BIGINT, Platform TEXT )"};
|
||||
|
||||
const static std::string DB_DefConfig_SelectFields{"Name, "
|
||||
"Configuration, "
|
||||
"Models, "
|
||||
"Description, "
|
||||
"Created, "
|
||||
"LastModified "};
|
||||
"LastModified, Platform "};
|
||||
|
||||
const static std::string DB_DefConfig_InsertValues{"?,?,?,?,?,?"};
|
||||
const static std::string DB_DefConfig_InsertValues{"?,?,?,?,?,?,?"};
|
||||
|
||||
typedef Poco::Tuple<std::string, std::string, std::string, std::string, uint64_t, uint64_t>
|
||||
typedef Poco::Tuple<std::string, std::string, std::string, std::string, uint64_t, uint64_t, std::string>
|
||||
DefConfigRecordTuple;
|
||||
typedef std::vector<DefConfigRecordTuple> DefConfigRecordList;
|
||||
|
||||
void Convert(const DefConfigRecordTuple &R, GWObjects::DefaultConfiguration &T) {
|
||||
T.Name = R.get<0>();
|
||||
T.Configuration = R.get<1>();
|
||||
T.Models = RESTAPI_utils::to_object_array(R.get<2>());
|
||||
T.Description = R.get<3>();
|
||||
T.Created = R.get<4>();
|
||||
T.LastModified = R.get<5>();
|
||||
T.name = R.get<0>();
|
||||
T.configuration = R.get<1>();
|
||||
T.models = RESTAPI_utils::to_object_array(R.get<2>());
|
||||
T.description = R.get<3>();
|
||||
T.created = R.get<4>();
|
||||
T.lastModified = R.get<5>();
|
||||
T.platform = R.get<6>();
|
||||
}
|
||||
|
||||
void Convert(const GWObjects::DefaultConfiguration &R, DefConfigRecordTuple &T) {
|
||||
T.set<0>(R.Name);
|
||||
T.set<1>(R.Configuration);
|
||||
T.set<2>(RESTAPI_utils::to_string(R.Models));
|
||||
T.set<3>(R.Description);
|
||||
T.set<4>(R.Created);
|
||||
T.set<5>(R.LastModified);
|
||||
T.set<0>(R.name);
|
||||
T.set<1>(R.configuration);
|
||||
T.set<2>(RESTAPI_utils::to_string(R.models));
|
||||
T.set<3>(R.description);
|
||||
T.set<4>(R.created);
|
||||
T.set<5>(R.lastModified);
|
||||
T.set<6>(R.platform);
|
||||
}
|
||||
|
||||
bool Storage::CreateDefaultConfiguration(std::string &Name,
|
||||
@@ -69,7 +71,7 @@ namespace OpenWifi {
|
||||
if (!TmpName.empty())
|
||||
return false;
|
||||
|
||||
Config::Config Cfg(DefConfig.Configuration);
|
||||
Config::Config Cfg(DefConfig.configuration);
|
||||
|
||||
if (Cfg.Valid()) {
|
||||
Sess.begin();
|
||||
@@ -124,10 +126,10 @@ namespace OpenWifi {
|
||||
Poco::Data::Session Sess = Pool_->get();
|
||||
Sess.begin();
|
||||
Poco::Data::Statement Update(Sess);
|
||||
DefConfig.LastModified = Now;
|
||||
DefConfig.lastModified = Now;
|
||||
|
||||
std::string St{"UPDATE DefaultConfigs SET Name=?, Configuration=?, Models=?, "
|
||||
"Description=?, Created=? , LastModified=? WHERE Name=?"};
|
||||
"Description=?, Created=? , LastModified=? , Platform=? WHERE Name=?"};
|
||||
|
||||
DefConfigRecordTuple R;
|
||||
Convert(DefConfig, R);
|
||||
@@ -219,31 +221,30 @@ namespace OpenWifi {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Storage::FindDefaultConfigurationForModel(const std::string &Model,
|
||||
GWObjects::DefaultConfiguration &DefConfig) {
|
||||
bool Storage::FindDefaultConfigurationForModel(const std::string &DeviceModel, const std::string &Platform,
|
||||
GWObjects::DefaultConfiguration &Config) {
|
||||
try {
|
||||
DefConfigRecordList Records;
|
||||
DefConfigRecordList DefConfigs;
|
||||
|
||||
Poco::Data::Session Sess = Pool_->get();
|
||||
Poco::Data::Statement Select(Sess);
|
||||
|
||||
Select << "SELECT " + DB_DefConfig_SelectFields + " FROM DefaultConfigs",
|
||||
Poco::Data::Keywords::into(Records);
|
||||
Poco::Data::Keywords::into(DefConfigs);
|
||||
Select.execute();
|
||||
|
||||
for (const auto &i : Records) {
|
||||
GWObjects::DefaultConfiguration Config;
|
||||
Convert(i, Config);
|
||||
for (const auto &j : Config.Models) {
|
||||
if (j == "*" || j == Model) {
|
||||
DefConfig = Config;
|
||||
for (const auto &DefConfig : DefConfigs) {
|
||||
GWObjects::DefaultConfiguration C;
|
||||
Convert(DefConfig, C);
|
||||
for (const auto &Model : C.models) {
|
||||
if ((Model == "*" || Model == DeviceModel) && (Config.platform == Platform)){
|
||||
Config = C;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
Logger().information(
|
||||
fmt::format("AUTO-PROVISIONING: no default configuration for model:{}", Model));
|
||||
return false;
|
||||
fmt::format("AUTO-PROVISIONING: no default configuration for model:{}", DeviceModel));
|
||||
} catch (const Poco::Exception &E) {
|
||||
poco_warning(Logger(), fmt::format("{}: Failed with: {}", std::string(__func__),
|
||||
E.displayText()));
|
||||
|
||||
@@ -172,13 +172,26 @@ namespace OpenWifi {
|
||||
R.set<30>(D.connectReason);
|
||||
}
|
||||
|
||||
bool Storage::GetDeviceCount(uint64_t &Count) {
|
||||
bool Storage::GetDeviceCount(uint64_t &Count, const std::string &platform, bool includeProvisioned) {
|
||||
try {
|
||||
Poco::Data::Session Sess = Pool_->get();
|
||||
Poco::Data::Statement Select(Sess);
|
||||
|
||||
std::string st{"SELECT COUNT(*) FROM Devices"};
|
||||
std::string st;
|
||||
std::string whereClause = "";
|
||||
|
||||
if(!platform.empty()) {
|
||||
if (includeProvisioned == false) {
|
||||
whereClause = fmt::format("WHERE entity='' and venue='' and DeviceType='" + platform + "'");
|
||||
} else {
|
||||
whereClause = fmt::format("WHERE DeviceType='" + platform + "'");
|
||||
}
|
||||
} else {
|
||||
if (includeProvisioned == false) {
|
||||
whereClause = fmt::format("WHERE entity='' and venue=''");
|
||||
}
|
||||
}
|
||||
st = fmt::format("SELECT COUNT(*) FROM Devices {}", whereClause);
|
||||
Select << st, Poco::Data::Keywords::into(Count);
|
||||
Select.execute();
|
||||
return true;
|
||||
@@ -190,16 +203,37 @@ namespace OpenWifi {
|
||||
|
||||
bool Storage::GetDeviceSerialNumbers(uint64_t From, uint64_t HowMany,
|
||||
std::vector<std::string> &SerialNumbers,
|
||||
const std::string &orderBy) {
|
||||
const std::string &orderBy,
|
||||
const std::string &platform, bool includeProvisioned) {
|
||||
try {
|
||||
Poco::Data::Session Sess = Pool_->get();
|
||||
Poco::Data::Statement Select(Sess);
|
||||
|
||||
std::string st;
|
||||
std::string whereClause = "";
|
||||
if(!platform.empty()) {
|
||||
if (includeProvisioned == false) {
|
||||
|
||||
whereClause = fmt::format("WHERE entity='' and venue='' and DeviceType='" + platform + "'");
|
||||
} else {
|
||||
whereClause = fmt::format("WHERE DeviceType='" + platform + "'");
|
||||
}
|
||||
|
||||
|
||||
//st = "SELECT SerialNumber From Devices WHERE DeviceType='" + platform + "' ";
|
||||
} else {
|
||||
if (includeProvisioned == false) {
|
||||
whereClause = fmt::format("WHERE entity='' and venue=''");
|
||||
}
|
||||
//st = "SELECT SerialNumber From Devices ";
|
||||
}
|
||||
|
||||
st = fmt::format("SELECT SerialNumber From Devices {}", whereClause);
|
||||
|
||||
if (orderBy.empty())
|
||||
st = "SELECT SerialNumber From Devices ORDER BY SerialNumber ASC ";
|
||||
st += " ORDER BY SerialNumber ASC ";
|
||||
else
|
||||
st = "SELECT SerialNumber From Devices " + orderBy;
|
||||
st += orderBy;
|
||||
|
||||
Select << st + ComputeRange(From, HowMany), Poco::Data::Keywords::into(SerialNumbers);
|
||||
Select.execute();
|
||||
@@ -265,7 +299,7 @@ namespace OpenWifi {
|
||||
D.pendingUUID = 0;
|
||||
D.LastConfigurationChange = Utils::Now();
|
||||
|
||||
ConfigurationCache().Add(Utils::SerialNumberToInt(SerialNumber), D.UUID);
|
||||
SetCurrentConfigurationID(Utils::SerialNumberToInt(SerialNumber), D.UUID);
|
||||
|
||||
Poco::Data::Session Sess = Pool_->get();
|
||||
Sess.begin();
|
||||
@@ -298,19 +332,30 @@ namespace OpenWifi {
|
||||
|
||||
bool Storage::CompleteDeviceConfigurationChange(Poco::Data::Session & Session, std::string & SerialNumber) {
|
||||
try {
|
||||
|
||||
GWObjects::Device D;
|
||||
if (!GetDevice(SerialNumber, D))
|
||||
return false;
|
||||
|
||||
if(D.pendingConfiguration.empty())
|
||||
return true;
|
||||
D.Configuration = D.pendingConfiguration;
|
||||
D.pendingConfiguration.clear();
|
||||
D.UUID = D.pendingUUID;
|
||||
D.pendingUUID = 0;
|
||||
D.LastConfigurationChange = Utils::Now();
|
||||
if(!D.pendingConfiguration.empty()) {
|
||||
D.Configuration = D.pendingConfiguration;
|
||||
D.pendingConfiguration.clear();
|
||||
}
|
||||
if(D.pendingUUID!=0) {
|
||||
D.UUID = D.pendingUUID;
|
||||
D.pendingUUID = 0;
|
||||
}
|
||||
|
||||
ConfigurationCache().Add(Utils::SerialNumberToInt(SerialNumber), D.UUID);
|
||||
// if this is a broken device, fix it...
|
||||
if(D.UUID==0) {
|
||||
Config::Config Cfg(D.Configuration);
|
||||
if(Cfg.Valid()) {
|
||||
D.UUID = Cfg.UUID();
|
||||
}
|
||||
}
|
||||
|
||||
D.LastConfigurationChange = Utils::Now();
|
||||
SetCurrentConfigurationID(Utils::SerialNumberToInt(SerialNumber), D.UUID);
|
||||
|
||||
Session.begin();
|
||||
Poco::Data::Statement Update(Session);
|
||||
@@ -525,7 +570,7 @@ namespace OpenWifi {
|
||||
} catch (const Poco::Exception &E) {
|
||||
Logger().log(E);
|
||||
}
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Storage::CreateDefaultDevice(Poco::Data::Session &Session, std::string &SerialNumber, const Config::Capabilities &Caps,
|
||||
@@ -557,21 +602,31 @@ namespace OpenWifi {
|
||||
}
|
||||
|
||||
if (!Found && AP_WS_Server()->UseDefaults() &&
|
||||
FindDefaultConfigurationForModel(Caps.Compatible(), DefConfig)) {
|
||||
Config::Config NewConfig(DefConfig.Configuration);
|
||||
FindDefaultConfigurationForModel(Caps.Compatible(), Caps.Platform(), DefConfig)) {
|
||||
Config::Config NewConfig(DefConfig.configuration);
|
||||
NewConfig.SetUUID(Now);
|
||||
D.Configuration = NewConfig.get();
|
||||
} else if (!Found) {
|
||||
Config::Config NewConfig;
|
||||
NewConfig.SetUUID(Now);
|
||||
D.Configuration = NewConfig.get();
|
||||
if(Caps.Platform()==Platforms::AP) {
|
||||
Config::Config NewConfig;
|
||||
NewConfig.SetUUID(Now);
|
||||
D.Configuration = NewConfig.get();
|
||||
} else {
|
||||
Poco::JSON::Object Obj;
|
||||
Obj.set("uuid", Now);
|
||||
std::ostringstream os;
|
||||
Obj.stringify(os);
|
||||
D.Configuration = os.str();
|
||||
}
|
||||
}
|
||||
|
||||
// We need to insert the country code according to the IP in the radios section...
|
||||
D.locale = InsertRadiosCountyRegulation(D.Configuration, IPAddress);
|
||||
D.SerialNumber = Poco::toLower(SerialNumber);
|
||||
D.Compatible = Caps.Compatible();
|
||||
D.DeviceType = Daemon()->IdentifyDevice(D.Compatible);
|
||||
if(D.Compatible.empty())
|
||||
D.Compatible = Caps.Model();
|
||||
D.DeviceType = Poco::toLower(Caps.Platform());
|
||||
D.MACAddress = Utils::SerialToMAC(SerialNumber);
|
||||
D.Manufacturer = Caps.Model();
|
||||
D.Firmware = Firmware;
|
||||
@@ -620,6 +675,22 @@ namespace OpenWifi {
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string Storage::GetPlatform(const std::string &SerialNumber) {
|
||||
try {
|
||||
Poco::Data::Session Sess = Pool_->get();
|
||||
Poco::Data::Statement Select(Sess);
|
||||
|
||||
std::string St = fmt::format("SELECT DeviceType FROM Devices WHERE SerialNumber='{}'", SerialNumber);
|
||||
std::string Platform;
|
||||
Select << ConvertParams(St), Poco::Data::Keywords::into(Platform);
|
||||
Select.execute();
|
||||
return Platform;
|
||||
} catch (const Poco::Exception &E) {
|
||||
Logger().log(E);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
bool Storage::DeleteDevice(std::string &SerialNumber) {
|
||||
try {
|
||||
std::vector<std::string> TableNames{"Devices", "Statistics", "CommandList",
|
||||
@@ -708,17 +779,14 @@ namespace OpenWifi {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Storage::GetDevice(Poco::Data::Session &Session, std::string &SerialNumber, GWObjects::Device &DeviceDetails) {
|
||||
bool Storage::GetDevice(Poco::Data::Session &Session, const std::string &SerialNumber, GWObjects::Device &DeviceDetails) {
|
||||
try {
|
||||
Poco::Data::Statement Select(Session);
|
||||
std::string St{"SELECT " + DB_DeviceSelectFields +
|
||||
" FROM Devices WHERE SerialNumber=?"};
|
||||
std::string St = fmt::format("SELECT {} FROM Devices WHERE SerialNumber='{}'", DB_DeviceSelectFields, SerialNumber);
|
||||
|
||||
DeviceRecordTuple R;
|
||||
Select << ConvertParams(St), Poco::Data::Keywords::into(R),
|
||||
Poco::Data::Keywords::use(SerialNumber);
|
||||
Select << St, Poco::Data::Keywords::into(R);
|
||||
Select.execute();
|
||||
|
||||
if (Select.rowsExtracted() == 0)
|
||||
return false;
|
||||
ConvertDeviceRecord(R, DeviceDetails);
|
||||
@@ -729,7 +797,7 @@ namespace OpenWifi {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Storage::GetDevice(std::string &SerialNumber, GWObjects::Device &DeviceDetails) {
|
||||
bool Storage::GetDevice(const std::string &SerialNumber, GWObjects::Device &DeviceDetails) {
|
||||
try {
|
||||
auto Sess = Pool_->get();
|
||||
return GetDevice(Sess, SerialNumber, DeviceDetails);
|
||||
@@ -739,7 +807,7 @@ namespace OpenWifi {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Storage::GetDevice(LockedDbSession &Session, std::string &SerialNumber, GWObjects::Device &DeviceDetails) {
|
||||
bool Storage::GetDevice(LockedDbSession &Session, const std::string &SerialNumber, GWObjects::Device &DeviceDetails) {
|
||||
try {
|
||||
std::lock_guard Lock(Session.Mutex());
|
||||
return GetDevice(Session.Session(), SerialNumber, DeviceDetails);
|
||||
@@ -817,18 +885,38 @@ namespace OpenWifi {
|
||||
}
|
||||
|
||||
bool Storage::GetDevices(uint64_t From, uint64_t HowMany,
|
||||
std::vector<GWObjects::Device> &Devices, const std::string &orderBy) {
|
||||
std::vector<GWObjects::Device> &Devices, const std::string &orderBy, const std::string &platform,
|
||||
bool includeProvisioned) {
|
||||
DeviceRecordList Records;
|
||||
try {
|
||||
Poco::Data::Session Sess = Pool_->get();
|
||||
Poco::Data::Statement Select(Sess);
|
||||
|
||||
// std::string st{"SELECT " + DB_DeviceSelectFields + " FROM Devices " + orderBy.empty()
|
||||
// ? " ORDER BY SerialNumber ASC " + ComputeRange(From, HowMany)};
|
||||
std::string st = fmt::format("SELECT {} FROM Devices {} {}", DB_DeviceSelectFields,
|
||||
orderBy.empty() ? " ORDER BY SerialNumber ASC " : orderBy,
|
||||
ComputeRange(From, HowMany));
|
||||
std::string st;
|
||||
std::string whereClause = "";
|
||||
if(platform.empty()) {
|
||||
|
||||
if (includeProvisioned == false) {
|
||||
whereClause = fmt::format("WHERE entity='' and venue=''");
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
if (includeProvisioned == false) {
|
||||
whereClause = fmt::format("WHERE DeviceType='{}' and entity='' and venue=''",platform);
|
||||
} else {
|
||||
whereClause = fmt::format("WHERE DeviceType='{}'", platform);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
st =
|
||||
fmt::format("SELECT {} FROM Devices {} {} {}", DB_DeviceSelectFields, whereClause,
|
||||
orderBy.empty() ? " ORDER BY SerialNumber ASC " : orderBy,
|
||||
ComputeRange(From, HowMany));
|
||||
|
||||
//Logger().information(fmt::format(" GetDevices st is {} ", st));
|
||||
|
||||
Select << ConvertParams(st), Poco::Data::Keywords::into(Records);
|
||||
Select.execute();
|
||||
|
||||
@@ -1056,9 +1144,9 @@ namespace OpenWifi {
|
||||
}
|
||||
}
|
||||
|
||||
uint64_t Associations_2G, Associations_5G, Associations_6G;
|
||||
uint64_t Associations_2G, Associations_5G, Associations_6G, uptime;
|
||||
StateUtils::ComputeAssociations(RawObject, Associations_2G, Associations_5G,
|
||||
Associations_6G);
|
||||
Associations_6G, uptime);
|
||||
UpdateCountedMap(Dashboard.associations, "2G", Associations_2G);
|
||||
UpdateCountedMap(Dashboard.associations, "5G", Associations_5G);
|
||||
UpdateCountedMap(Dashboard.associations, "6G", Associations_6G);
|
||||
@@ -1082,4 +1170,25 @@ namespace OpenWifi {
|
||||
FieldList.push_back(field);
|
||||
}
|
||||
|
||||
void Storage::FixDeviceTypeBug() {
|
||||
try {
|
||||
std::vector<std::string> ScriptLines{
|
||||
"update devices set devicetype='ap' where devicetype='AP';",
|
||||
"update devices set devicetype='switch' where devicetype='SWITCH';",
|
||||
"update devices set devicetype='ap' where devicetype!='ap' and devicetype!='switch';"
|
||||
};
|
||||
|
||||
for (const auto &ScriptLine : ScriptLines) {
|
||||
try {
|
||||
Poco::Data::Session Sess = Pool_->get();
|
||||
Poco::Data::Statement SqlStatement(Sess);
|
||||
SqlStatement << ScriptLine, Poco::Data::Keywords::now;
|
||||
} catch (...) {
|
||||
}
|
||||
}
|
||||
} catch (const Poco::Exception &E) {
|
||||
Logger().log(E);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace OpenWifi
|
||||
|
||||
@@ -275,9 +275,21 @@ namespace OpenWifi {
|
||||
"Models TEXT, "
|
||||
"Description TEXT, "
|
||||
"Created BIGINT , "
|
||||
"LastModified BIGINT)",
|
||||
"LastModified BIGINT, Platform TEXT)",
|
||||
Poco::Data::Keywords::now;
|
||||
}
|
||||
|
||||
std::vector<std::string> Script{
|
||||
"alter table DefaultConfigs add column Platform text"
|
||||
};
|
||||
|
||||
for (const auto &i : Script) {
|
||||
try {
|
||||
Sess << i, Poco::Data::Keywords::now;
|
||||
} catch (...) {
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
} catch (const Poco::Exception &E) {
|
||||
Logger().log(E);
|
||||
|
||||
Reference in New Issue
Block a user