mirror of
				https://github.com/Telecominfraproject/wlan-cloud-ucentralgw.git
				synced 2025-11-03 20:27:45 +00:00 
			
		
		
		
	Compare commits
	
		
			271 Commits
		
	
	
		
			revert-RC2
			...
			kv3.0.14
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					979707ce41 | ||
| 
						 | 
					e687981f81 | ||
| 
						 | 
					de3682d7ba | ||
| 
						 | 
					5fcc12b3ed | ||
| 
						 | 
					0795e046fe | ||
| 
						 | 
					8392b4bbc1 | ||
| 
						 | 
					5727432d1b | ||
| 
						 | 
					addd6ed346 | ||
| 
						 | 
					3ee2adf03c | ||
| 
						 | 
					1b915e988f | ||
| 
						 | 
					084cfb78dd | ||
| 
						 | 
					996cdba49d | ||
| 
						 | 
					d211222052 | ||
| 
						 | 
					b92d0ff308 | ||
| 
						 | 
					843e7039b3 | ||
| 
						 | 
					e9e0a6845d | ||
| 
						 | 
					3e255f3257 | ||
| 
						 | 
					b75a1aa923 | ||
| 
						 | 
					2333cc7a40 | ||
| 
						 | 
					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 | ||
| 
						 | 
					915a2c936d | ||
| 
						 | 
					e1bf6a9ab7 | ||
| 
						 | 
					58fc925a2f | ||
| 
						 | 
					3dda87b41f | ||
| 
						 | 
					a5fe59086a | ||
| 
						 | 
					c66b936c1e | ||
| 
						 | 
					0e763cf034 | ||
| 
						 | 
					eb441d71aa | ||
| 
						 | 
					082153a229 | ||
| 
						 | 
					25a03ca801 | ||
| 
						 | 
					0d549137de | ||
| 
						 | 
					40e814cab8 | ||
| 
						 | 
					e40d53f3e5 | ||
| 
						 | 
					607507ce9a | ||
| 
						 | 
					b3ec5b1e81 | ||
| 
						 | 
					c52d3c92f6 | ||
| 
						 | 
					d1216a8ac4 | ||
| 
						 | 
					c27f0390f8 | ||
| 
						 | 
					052d379e2b | ||
| 
						 | 
					4eda1b813f | ||
| 
						 | 
					5364adf509 | ||
| 
						 | 
					3b5580a525 | ||
| 
						 | 
					644918fa14 | ||
| 
						 | 
					8cdd398a6e | ||
| 
						 | 
					9f7f4683df | ||
| 
						 | 
					1c6e35fa8b | ||
| 
						 | 
					af17823df0 | ||
| 
						 | 
					0cff2163bb | ||
| 
						 | 
					0a5fe39bde | ||
| 
						 | 
					c42feca957 | ||
| 
						 | 
					d3c5b17733 | ||
| 
						 | 
					30bc8e8283 | ||
| 
						 | 
					336c94a25a | ||
| 
						 | 
					84f42e5a7d | ||
| 
						 | 
					17752fdefe | ||
| 
						 | 
					ef300b0349 | ||
| 
						 | 
					9c4ecb6165 | ||
| 
						 | 
					efd099b6fa | ||
| 
						 | 
					15805dcaf6 | ||
| 
						 | 
					e5ed1750cc | ||
| 
						 | 
					87d74568f2 | ||
| 
						 | 
					0cca3caa9b | ||
| 
						 | 
					1d22e1153f | ||
| 
						 | 
					f3ccc49647 | ||
| 
						 | 
					46fb410108 | ||
| 
						 | 
					fc680a6bc4 | ||
| 
						 | 
					246f9c8aad | ||
| 
						 | 
					3f06f00a88 | ||
| 
						 | 
					0288d905b7 | ||
| 
						 | 
					135b63c021 | ||
| 
						 | 
					12e07fa65f | ||
| 
						 | 
					567c2d1514 | ||
| 
						 | 
					b9bd768ca6 | ||
| 
						 | 
					f2dec010ee | ||
| 
						 | 
					329d8d4441 | ||
| 
						 | 
					d4dbbeb54b | ||
| 
						 | 
					b1c6884d49 | ||
| 
						 | 
					3ffa35bb14 | ||
| 
						 | 
					bd06722948 | ||
| 
						 | 
					8c70ec5280 | ||
| 
						 | 
					6c13d845f1 | ||
| 
						 | 
					77cc0b250b | ||
| 
						 | 
					a3c424d8fe | ||
| 
						 | 
					3f834a967b | ||
| 
						 | 
					4120aefcd4 | ||
| 
						 | 
					909ee66ef0 | ||
| 
						 | 
					c3ad34d84b | ||
| 
						 | 
					fbb9f40529 | ||
| 
						 | 
					5f6300bb17 | ||
| 
						 | 
					0bcfb26579 | ||
| 
						 | 
					5b199bc4f5 | ||
| 
						 | 
					4c6fb85542 | ||
| 
						 | 
					63993789ca | ||
| 
						 | 
					cc9d4c5f68 | ||
| 
						 | 
					50fa1de62c | ||
| 
						 | 
					14ef6608d6 | ||
| 
						 | 
					8e48d30d6a | ||
| 
						 | 
					46c6321674 | ||
| 
						 | 
					77f67fe545 | ||
| 
						 | 
					ceda1fc8f6 | ||
| 
						 | 
					5b1a4fb9c0 | ||
| 
						 | 
					2ddc0d3117 | ||
| 
						 | 
					2cfc6c30e9 | ||
| 
						 | 
					0318b475f5 | ||
| 
						 | 
					c5c2dc1a1e | ||
| 
						 | 
					7b899adb88 | ||
| 
						 | 
					aa472ed79e | ||
| 
						 | 
					1778912264 | ||
| 
						 | 
					142bc4f271 | ||
| 
						 | 
					a01d006d4e | ||
| 
						 | 
					135a195081 | ||
| 
						 | 
					ef7cb883fb | ||
| 
						 | 
					2e361a41d7 | ||
| 
						 | 
					84281ec58e | ||
| 
						 | 
					3560871f44 | ||
| 
						 | 
					b072f1e2ab | ||
| 
						 | 
					72173ed4b5 | ||
| 
						 | 
					ff53d4ba2e | ||
| 
						 | 
					81721b4a61 | ||
| 
						 | 
					3619be1832 | ||
| 
						 | 
					a8fc823b94 | ||
| 
						 | 
					a8a33013be | ||
| 
						 | 
					9560f908a6 | ||
| 
						 | 
					8400b8cfcb | ||
| 
						 | 
					82897f5b76 | ||
| 
						 | 
					4b472fd112 | ||
| 
						 | 
					ecb6312f0f | ||
| 
						 | 
					0aba846277 | ||
| 
						 | 
					5be884ef98 | ||
| 
						 | 
					10c890a196 | ||
| 
						 | 
					0974abd510 | ||
| 
						 | 
					8dbbfc3298 | ||
| 
						 | 
					c981ae14ee | ||
| 
						 | 
					97547068d7 | ||
| 
						 | 
					16cc443786 | 
							
								
								
									
										193
									
								
								.github/workflows/ci.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										193
									
								
								.github/workflows/ci.yml
									
									
									
									
										vendored
									
									
								
							@@ -1,19 +1,19 @@
 | 
				
			|||||||
name: CI
 | 
					name: Build Docker image
 | 
				
			||||||
 | 
					
 | 
				
			||||||
on:
 | 
					on:
 | 
				
			||||||
  push:
 | 
					  push:
 | 
				
			||||||
    paths-ignore:
 | 
					    paths-ignore:
 | 
				
			||||||
      - 'openapi/**'
 | 
					      - 'openapi/**'
 | 
				
			||||||
      - '**.md'
 | 
					      - '**.md'
 | 
				
			||||||
 | 
					      - 'version'
 | 
				
			||||||
 | 
					      - 'package*.json'
 | 
				
			||||||
 | 
					      - 'helm/*.yaml'
 | 
				
			||||||
 | 
					      - 'CMakeLists.txt'
 | 
				
			||||||
    branches:
 | 
					    branches:
 | 
				
			||||||
      - master
 | 
					      - kinara
 | 
				
			||||||
      - 'release/*'
 | 
					 | 
				
			||||||
    tags:
 | 
					 | 
				
			||||||
      - 'v*'
 | 
					 | 
				
			||||||
  pull_request:
 | 
					  pull_request:
 | 
				
			||||||
    branches:
 | 
					    branches:
 | 
				
			||||||
      - master
 | 
					      - kinara
 | 
				
			||||||
      - 'release/*'
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
defaults:
 | 
					defaults:
 | 
				
			||||||
  run:
 | 
					  run:
 | 
				
			||||||
@@ -21,81 +21,124 @@ defaults:
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
jobs:
 | 
					jobs:
 | 
				
			||||||
  docker:
 | 
					  docker:
 | 
				
			||||||
    runs-on: ubuntu-20.04
 | 
					    runs-on: ubuntu-latest
 | 
				
			||||||
    env:
 | 
					    env:
 | 
				
			||||||
      DOCKER_REGISTRY_URL: tip-tip-wlan-cloud-ucentral.jfrog.io
 | 
					      ECR_REGISTRY: 471112855615.dkr.ecr.us-east-1.amazonaws.com
 | 
				
			||||||
      DOCKER_REGISTRY_USERNAME: ucentral
 | 
					      ECR_REPOSITORY: owgw
 | 
				
			||||||
 | 
					      AWS_REGION: us-east-1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    steps:
 | 
					    steps:
 | 
				
			||||||
    - name: Checkout actions repo
 | 
					      - name: Checkout source
 | 
				
			||||||
      uses: actions/checkout@v3
 | 
					        uses: actions/checkout@v4
 | 
				
			||||||
      with:
 | 
					        with:
 | 
				
			||||||
        repository: Telecominfraproject/.github
 | 
					          path: build
 | 
				
			||||||
        path: github
 | 
					          token: ${{ secrets.GIT_PUSH_PAT }}
 | 
				
			||||||
 | 
					          persist-credentials: true
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    - name: Build and push Docker image
 | 
					      - name: Checkout dot github repo
 | 
				
			||||||
      uses: ./github/composite-actions/docker-image-build
 | 
					        uses: actions/checkout@v4
 | 
				
			||||||
      with:
 | 
					        with:
 | 
				
			||||||
        image_name: owgw
 | 
					          repository: kinarasystems/.github
 | 
				
			||||||
        registry: tip-tip-wlan-cloud-ucentral.jfrog.io
 | 
					          ref: main
 | 
				
			||||||
        registry_user: ucentral
 | 
					          path: tools
 | 
				
			||||||
        registry_password: ${{ secrets.DOCKER_REGISTRY_PASSWORD }}
 | 
					          token: ${{ secrets.GIT_PUSH_PAT }}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    - name: Notify on failure via Slack
 | 
					      - name: Bump version and checkin
 | 
				
			||||||
      if: failure() && github.ref == 'refs/heads/master'
 | 
					        if: github.ref == 'refs/heads/kinara'
 | 
				
			||||||
      uses: rtCamp/action-slack-notify@v2
 | 
					        id: bump-version
 | 
				
			||||||
      env:
 | 
					        run: |
 | 
				
			||||||
        SLACK_USERNAME: GitHub Actions failure notifier
 | 
					          cd build
 | 
				
			||||||
        SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK }}
 | 
					          ../tools/utils/setup-git-credentials "${{ secrets.GIT_PUSH_PAT}}"
 | 
				
			||||||
        SLACK_COLOR: "${{ job.status }}"
 | 
					          ../tools/utils/ver-bump -b -a -p -V kv -y helm/Chart.yaml -Y helm/values.yaml -M CMakeLists.txt
 | 
				
			||||||
        SLACK_ICON: https://raw.githubusercontent.com/quintessence/slack-icons/master/images/github-logo-slack-icon.png
 | 
					 | 
				
			||||||
        SLACK_TITLE: Docker build failed for OWGW service
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  trigger-testing:
 | 
					      - name: Configure AWS credentials
 | 
				
			||||||
    if: startsWith(github.ref, 'refs/pull/')
 | 
					        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-dev1:
 | 
				
			||||||
    runs-on: ubuntu-latest
 | 
					    runs-on: ubuntu-latest
 | 
				
			||||||
    needs: docker
 | 
					    if: github.ref == 'refs/heads/main'
 | 
				
			||||||
    steps:
 | 
					    env:
 | 
				
			||||||
    - name: Get base branch name and set as output
 | 
					      DEPLOY_NAME: owgw
 | 
				
			||||||
      id: get_base_branch
 | 
					      HOSTNAME: dev1.dev.kinsights.io
 | 
				
			||||||
      run: |
 | 
					      NAMESPACE: openlan
 | 
				
			||||||
        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'
 | 
					 | 
				
			||||||
    needs:
 | 
					    needs:
 | 
				
			||||||
      - docker
 | 
					      - docker
 | 
				
			||||||
    steps:
 | 
					    steps:
 | 
				
			||||||
    - name: Checkout actions repo
 | 
					      - name: Set up SSH key
 | 
				
			||||||
      uses: actions/checkout@v3
 | 
					        run: |
 | 
				
			||||||
      with:
 | 
					          echo "${{ secrets.PRIVATE_SSH_KEY }}" > .ssh_host_key
 | 
				
			||||||
        repository: Telecominfraproject/.github
 | 
					          chmod 600 .ssh_host_key
 | 
				
			||||||
        path: github
 | 
					      - name: Rolling update of deployment
 | 
				
			||||||
 | 
					        run: |
 | 
				
			||||||
 | 
					          ssh -i .ssh_host_key \
 | 
				
			||||||
 | 
					            -o "StrictHostKeyChecking=no" -o "UserKnownHostsFile=/dev/null" \
 | 
				
			||||||
 | 
					            ubuntu@${{ env.HOSTNAME }} \
 | 
				
			||||||
 | 
					            kubectl rollout restart deployment/${{ env.DEPLOY_NAME }} -n ${{ env.NAMESPACE }}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    - name: Trigger deployment of the latest version to dev instance and wait for result
 | 
					  # OLD EKS method - disabled via if:
 | 
				
			||||||
      uses: ./github/composite-actions/trigger-workflow-and-wait
 | 
					  deploy-to-dev-old-eks:
 | 
				
			||||||
      with:
 | 
					    runs-on: ubuntu-latest
 | 
				
			||||||
        owner: Telecominfraproject
 | 
					    if: false
 | 
				
			||||||
        repo: wlan-testing
 | 
					    env:
 | 
				
			||||||
        workflow: ucentralgw-dev-deployment.yaml
 | 
					      DEPLOY_NAME: owgw
 | 
				
			||||||
        token: ${{ secrets.WLAN_TESTING_PAT }}
 | 
					      AWS_DEFAULT_REGION: us-east-1
 | 
				
			||||||
        ref: master
 | 
					      AWS_NAMESPACE: kic-dev1
 | 
				
			||||||
        inputs: '{"force_latest": "true"}'
 | 
					      AWS_EKS_NAME: kinara-dev
 | 
				
			||||||
 | 
					      KUBECTL_VERSION: "v1.27.14"
 | 
				
			||||||
 | 
					    needs:
 | 
				
			||||||
 | 
					      - docker
 | 
				
			||||||
 | 
					    steps:
 | 
				
			||||||
 | 
					      - 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: 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
 | 
				
			||||||
/docker-compose/.env_*
 | 
					/docker-compose/.env_*
 | 
				
			||||||
/cmake-build/
 | 
					/cmake-build/
 | 
				
			||||||
/uploads/
 | 
					 | 
				
			||||||
test_scripts/curl/token.json
 | 
					test_scripts/curl/token.json
 | 
				
			||||||
.vscode/c_cpp_properties.json
 | 
					.vscode/c_cpp_properties.json
 | 
				
			||||||
test_scripts/curl/result.json
 | 
					test_scripts/curl/result.json
 | 
				
			||||||
*.swp
 | 
					*.swp
 | 
				
			||||||
helm/charts/*
 | 
					helm/charts/*
 | 
				
			||||||
!helm/charts/.gitkeep
 | 
					!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
 | 
					/dataSources.local.xml
 | 
				
			||||||
# Editor-based HTTP Client requests
 | 
					# Editor-based HTTP Client requests
 | 
				
			||||||
/httpRequests/
 | 
					/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"?>
 | 
					<?xml version="1.0" encoding="UTF-8"?>
 | 
				
			||||||
<project version="4">
 | 
					<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="CMakeWorkspace" PROJECT_DIR="$PROJECT_DIR$" />
 | 
				
			||||||
  <component name="CidrRootsConfiguration">
 | 
					  <component name="CidrRootsConfiguration">
 | 
				
			||||||
    <excludeRoots>
 | 
					    <excludeRoots>
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										62
									
								
								BUILDING.md
									
									
									
									
									
								
							
							
						
						
									
										62
									
								
								BUILDING.md
									
									
									
									
									
								
							@@ -1,5 +1,5 @@
 | 
				
			|||||||
# Building from source
 | 
					# 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
 | 
					- cmake
 | 
				
			||||||
- boost
 | 
					- boost
 | 
				
			||||||
- POCO 1.10.1 or later
 | 
					- 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
 | 
					The build is done in 2 parts. The first part is to build a local copy of the framework tailored to your environment. This
 | 
				
			||||||
framework is called [Poco](https://github.com/pocoproject/poco). The version used in this project has a couple of fixes
 | 
					framework is called [Poco](https://github.com/pocoproject/poco). The version used in this project has a couple of fixes
 | 
				
			||||||
from the master copy needed for cmake. Please use the version of this [Poco fix](https://github.com/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.
 | 
					Poco may take several minutes depending on the platform you are building on.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## Ubuntu
 | 
					## Ubuntu
 | 
				
			||||||
These instructions have proven to work on Ubuntu 20.4.
 | 
					These instructions have proven to work on Ubuntu 20.4.
 | 
				
			||||||
```bash
 | 
					```bash
 | 
				
			||||||
sudo apt install git cmake g++ libssl-dev libmariadb-dev 
 | 
					sudo apt install git cmake g++ libssl-dev libmariadb-dev \
 | 
				
			||||||
sudo apt install libpq-dev libaprutil1-dev apache2-dev libboost-all-dev
 | 
					    libpq-dev libaprutil1-dev apache2-dev libboost-all-dev \
 | 
				
			||||||
sudo apt install librdkafka-dev // default-libmysqlclient-dev
 | 
					    librdkafka-dev // default-libmysqlclient-dev \
 | 
				
			||||||
sudo apt install nlohmann-json-dev
 | 
					    nlohmann-json-dev
 | 
				
			||||||
 | 
					
 | 
				
			||||||
cd ~
 | 
					git clone https://github.com/Telecominfraproject/wlan-cloud-lib-poco --branch poco-tip-v1 poco
 | 
				
			||||||
git clone https://github.com/AriliaWireless/poco --branch poco-tip-v2
 | 
					 | 
				
			||||||
cd poco
 | 
					cd poco
 | 
				
			||||||
mkdir cmake-build
 | 
					mkdir cmake-build
 | 
				
			||||||
cd cmake-build
 | 
					cd cmake-build
 | 
				
			||||||
cmake ..
 | 
					cmake ..
 | 
				
			||||||
cmake --build . --config Release
 | 
					cmake --build . --config Release
 | 
				
			||||||
sudo cmake --build . --target install
 | 
					sudo cmake --build . --target install
 | 
				
			||||||
 | 
					cd ../..
 | 
				
			||||||
 | 
					
 | 
				
			||||||
cd ~
 | 
					git clone https://github.com/Telecominfraproject/wlan-cloud-lib-cppkafka --branch tip-v1 cppkafka
 | 
				
			||||||
git clone https://github.com/AriliaWireless/cppkafka --branch tip-v1
 | 
					 | 
				
			||||||
cd cppkafka
 | 
					cd cppkafka
 | 
				
			||||||
mkdir cmake-build
 | 
					mkdir cmake-build
 | 
				
			||||||
cd cmake-build
 | 
					cd cmake-build
 | 
				
			||||||
cmake ..
 | 
					cmake ..
 | 
				
			||||||
cmake --build . --config Release
 | 
					cmake --build . --config Release
 | 
				
			||||||
sudo cmake --build . --target install
 | 
					sudo cmake --build . --target install
 | 
				
			||||||
 | 
					cd ../..
 | 
				
			||||||
 | 
					
 | 
				
			||||||
cd ~
 | 
					git clone https://github.com/Telecominfraproject/wlan-cloud-lib-valijson --branch tip-v1 valijson
 | 
				
			||||||
git clone https://github.com/AriliaWireless/valijson --branch tip-v1
 | 
					 | 
				
			||||||
cd valijson
 | 
					cd valijson
 | 
				
			||||||
mkdir cmake-build
 | 
					mkdir cmake-build
 | 
				
			||||||
cd cmake-build
 | 
					cd cmake-build
 | 
				
			||||||
cmake ..
 | 
					cmake ..
 | 
				
			||||||
cmake --build . --config Release
 | 
					cmake --build . --config Release
 | 
				
			||||||
sudo cmake --build . --target install
 | 
					sudo cmake --build . --target install
 | 
				
			||||||
 | 
					cd ../..
 | 
				
			||||||
 | 
					
 | 
				
			||||||
git clone https://github.com/fmtlib/fmt --branch 9.0.0 /fmtlib
 | 
					git clone https://github.com/fmtlib/fmt --branch 9.0.0 /fmtlib
 | 
				
			||||||
cd fmtlib
 | 
					cd fmtlib
 | 
				
			||||||
@@ -57,56 +57,59 @@ cd cmake-build
 | 
				
			|||||||
cmake ..
 | 
					cmake ..
 | 
				
			||||||
make
 | 
					make
 | 
				
			||||||
make install
 | 
					make install
 | 
				
			||||||
 | 
					cd ../..
 | 
				
			||||||
 | 
					
 | 
				
			||||||
cd ~
 | 
					 | 
				
			||||||
git clone https://github.com/Telecominfraproject/wlan-cloud-ucentralgw
 | 
					git clone https://github.com/Telecominfraproject/wlan-cloud-ucentralgw
 | 
				
			||||||
cd wlan-cloud-ucentralgw
 | 
					cd wlan-cloud-ucentralgw
 | 
				
			||||||
mkdir cmake-build
 | 
					mkdir cmake-build
 | 
				
			||||||
cd cmake-build
 | 
					cd cmake-build
 | 
				
			||||||
cmake ..
 | 
					cmake ..
 | 
				
			||||||
make -j 8
 | 
					make -j 8
 | 
				
			||||||
 | 
					cd ../..
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## Fedora
 | 
					## Fedora
 | 
				
			||||||
The following instructions have proven to work on Fedora 33
 | 
					The following instructions have proven to work on Fedora 33
 | 
				
			||||||
```bash
 | 
					```bash
 | 
				
			||||||
sudo yum install cmake g++ openssl-devel mysql-devel mysql apr-util-devel boost boost-devel
 | 
					sudo yum install cmake g++ openssl-devel mysql-devel mysql apr-util-devel boost boost-devel \
 | 
				
			||||||
sudo yum install yaml-cpp-devel lua-devel 
 | 
					    yaml-cpp-devel lua-devel
 | 
				
			||||||
sudo dnf install postgresql.x86_64 librdkafka-devel
 | 
					sudo dnf install postgresql.x86_64 librdkafka-devel
 | 
				
			||||||
sudo dnf install postgresql-devel json-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
 | 
					cd poco
 | 
				
			||||||
mkdir cmake-build
 | 
					mkdir cmake-build
 | 
				
			||||||
cd cmake-build
 | 
					cd cmake-build
 | 
				
			||||||
cmake ..
 | 
					cmake ..
 | 
				
			||||||
cmake --build . --config Release
 | 
					cmake --build . --config Release
 | 
				
			||||||
sudo cmake --build . --target install
 | 
					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
 | 
					cd cppkafka
 | 
				
			||||||
mkdir cmake-build
 | 
					mkdir cmake-build
 | 
				
			||||||
cd cmake-build
 | 
					cd cmake-build
 | 
				
			||||||
cmake ..
 | 
					cmake ..
 | 
				
			||||||
cmake --build . --config Release
 | 
					cmake --build . --config Release
 | 
				
			||||||
sudo cmake --build . --target install
 | 
					sudo cmake --build . --target install
 | 
				
			||||||
 | 
					cd ../..
 | 
				
			||||||
 | 
					
 | 
				
			||||||
cd ~
 | 
					git clone https://github.com/Telecominfraproject/wlan-cloud-lib-valijson --branch tip-v1 valijson
 | 
				
			||||||
git clone https://github.com/AriliaWireless/valijson --branch tip-v1
 | 
					 | 
				
			||||||
cd valijson
 | 
					cd valijson
 | 
				
			||||||
mkdir cmake-build
 | 
					mkdir cmake-build
 | 
				
			||||||
cd cmake-build
 | 
					cd cmake-build
 | 
				
			||||||
cmake ..
 | 
					cmake ..
 | 
				
			||||||
cmake --build . --config Release
 | 
					cmake --build . --config Release
 | 
				
			||||||
sudo cmake --build . --target install
 | 
					sudo cmake --build . --target install
 | 
				
			||||||
 | 
					cd ../..
 | 
				
			||||||
 | 
					
 | 
				
			||||||
cd ~
 | 
					 | 
				
			||||||
git clone https://github.com/Telecominfraproject/wlan-cloud-ucentralgw
 | 
					git clone https://github.com/Telecominfraproject/wlan-cloud-ucentralgw
 | 
				
			||||||
cd wlan-cloud-ucentralgw
 | 
					cd wlan-cloud-ucentralgw
 | 
				
			||||||
mkdir cmake-build
 | 
					mkdir cmake-build
 | 
				
			||||||
cd cmake-build
 | 
					cd cmake-build
 | 
				
			||||||
cmake ..
 | 
					cmake ..
 | 
				
			||||||
make
 | 
					make
 | 
				
			||||||
 | 
					cd ../..
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## macOS Build
 | 
					## macOS Build
 | 
				
			||||||
@@ -125,7 +128,7 @@ brew install openssl \
 | 
				
			|||||||
	nlohmann-json \
 | 
						nlohmann-json \
 | 
				
			||||||
	fmt
 | 
						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
 | 
					pushd poco
 | 
				
			||||||
mkdir cmake-build
 | 
					mkdir cmake-build
 | 
				
			||||||
push cmake-build
 | 
					push cmake-build
 | 
				
			||||||
@@ -135,7 +138,7 @@ sudo cmake --build . --target install
 | 
				
			|||||||
popd
 | 
					popd
 | 
				
			||||||
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
 | 
					pushd cppkafka
 | 
				
			||||||
mkdir cmake-build
 | 
					mkdir cmake-build
 | 
				
			||||||
pushd cmake-build
 | 
					pushd cmake-build
 | 
				
			||||||
@@ -145,10 +148,10 @@ sudo cmake --build . --target install
 | 
				
			|||||||
popd
 | 
					popd
 | 
				
			||||||
popd
 | 
					popd
 | 
				
			||||||
 | 
					
 | 
				
			||||||
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
 | 
					pushd valijson
 | 
				
			||||||
mkdir cmake-build
 | 
					mkdir cmake-build
 | 
				
			||||||
cd cmake-build
 | 
					pushd cmake-build
 | 
				
			||||||
cmake ..
 | 
					cmake ..
 | 
				
			||||||
cmake --build . --config Release
 | 
					cmake --build . --config Release
 | 
				
			||||||
sudo cmake --build . --target install
 | 
					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.
 | 
					adding -DSMALL_BUILD=1 on the cmake build line.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
```bash
 | 
					```bash
 | 
				
			||||||
sudo apt install git cmake g++ libssl-dev libaprutil1-dev apache2-dev libboost-all-dev libyaml-cpp-dev
 | 
					sudo apt install git cmake g++ libssl-dev libaprutil1-dev apache2-dev \
 | 
				
			||||||
git clone https://github.com/stephb9959/poco
 | 
					    libboost-all-dev libyaml-cpp-dev
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					git clone https://github.com/Telecominfraproject/wlan-cloud-lib-poco --branch poco-tip-v1 poco
 | 
				
			||||||
cd poco
 | 
					cd poco
 | 
				
			||||||
mkdir cmake-build
 | 
					mkdir cmake-build
 | 
				
			||||||
cd cmake-build
 | 
					cd cmake-build
 | 
				
			||||||
cmake ..
 | 
					cmake ..
 | 
				
			||||||
cmake --build . --config Release
 | 
					cmake --build . --config Release
 | 
				
			||||||
sudo cmake --build . --target install
 | 
					sudo cmake --build . --target install
 | 
				
			||||||
 | 
					cd ../..
 | 
				
			||||||
 | 
					
 | 
				
			||||||
cd ~
 | 
					 | 
				
			||||||
git clone https://github.com/Telecominfraproject/wlan-cloud-ucentralgw
 | 
					git clone https://github.com/Telecominfraproject/wlan-cloud-ucentralgw
 | 
				
			||||||
cd wlan-cloud-ucentralgw
 | 
					cd wlan-cloud-ucentralgw
 | 
				
			||||||
mkdir cmake-build
 | 
					mkdir cmake-build
 | 
				
			||||||
cd cmake-build
 | 
					cd cmake-build
 | 
				
			||||||
cmake -DSMALL_BUILD=1 ..
 | 
					cmake -DSMALL_BUILD=1 ..
 | 
				
			||||||
make
 | 
					make
 | 
				
			||||||
 | 
					cd ../..
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										48
									
								
								CHANGELOG.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										48
									
								
								CHANGELOG.md
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,48 @@
 | 
				
			|||||||
 | 
					## 3.0.14 (November 06, 2024)
 | 
				
			||||||
 | 
					- chore: updated package.json, updated helm/Chart.yaml, updated helm/values.yaml, updated CMakeLists.txt, updated version, updated CHANGELOG.md, bumped 3.0.13 -> 3.0.14
 | 
				
			||||||
 | 
					- New deploy step
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## 3.0.13 (October 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.12 -> 3.0.13
 | 
				
			||||||
 | 
					- Merge pull request #16 from kinarasystems/WIFI-14227-feat-compressed-config
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## 3.0.12 (September 27, 2024)
 | 
				
			||||||
 | 
					- chore: updated package.json, updated helm/Chart.yaml, updated helm/values.yaml, updated CMakeLists.txt, updated version, updated CHANGELOG.md, bumped 3.0.11 -> 3.0.12
 | 
				
			||||||
 | 
					- Merge pull request #15 from kinarasystems/WIFI-14134-fix_file_upload_status
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## 3.0.11 (September 27, 2024)
 | 
				
			||||||
 | 
					- chore: updated package.json, updated helm/Chart.yaml, updated helm/values.yaml, updated CMakeLists.txt, updated version, updated CHANGELOG.md, bumped 3.0.10 -> 3.0.11
 | 
				
			||||||
 | 
					- Merge pull request #14 from kinarasystems/WIFI-14134-fix_file_upload_status
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## 3.0.10 (September 18, 2024)
 | 
				
			||||||
 | 
					- chore: updated package.json, updated helm/Chart.yaml, updated helm/values.yaml, updated CMakeLists.txt, updated version, updated CHANGELOG.md, bumped 3.0.9 -> 3.0.10
 | 
				
			||||||
 | 
					- Merge pull request #12 from kinarasystems/cable_diag
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## 3.0.9 (August 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.8 -> 3.0.9
 | 
				
			||||||
 | 
					- Merge pull request #11 from kinarasystems/fixedconfig
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## 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)
 | 
					cmake_minimum_required(VERSION 3.13)
 | 
				
			||||||
project(owgw VERSION 3.0.0)
 | 
					project(owgw VERSION 3.0.14)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
set(CMAKE_CXX_STANDARD 17)
 | 
					set(CMAKE_CXX_STANDARD 20)
 | 
				
			||||||
 | 
					set(CMAKE_CXX_STANDARD_REQUIRED True)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
if(UNIX AND APPLE)
 | 
					if(UNIX AND APPLE)
 | 
				
			||||||
    set(OPENSSL_ROOT_DIR /usr/local/opt/openssl)
 | 
					    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_script_handler.cpp src/RESTAPI/RESTAPI_script_handler.h
 | 
				
			||||||
        src/RESTAPI/RESTAPI_regulatory.cpp src/RESTAPI/RESTAPI_regulatory.h
 | 
					        src/RESTAPI/RESTAPI_regulatory.cpp src/RESTAPI/RESTAPI_regulatory.h
 | 
				
			||||||
        src/RESTAPI/RESTAPI_radiussessions_handler.cpp src/RESTAPI/RESTAPI_radiussessions_handler.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_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_command.cpp src/storage/storage_healthcheck.cpp src/storage/storage_statistics.cpp
 | 
				
			||||||
        src/storage/storage_device.cpp src/storage/storage_capabilities.cpp src/storage/storage_defconfig.cpp
 | 
					        src/storage/storage_device.cpp src/storage/storage_capabilities.cpp src/storage/storage_defconfig.cpp
 | 
				
			||||||
@@ -175,7 +177,7 @@ add_executable( owgw
 | 
				
			|||||||
        src/SDKcalls.cpp
 | 
					        src/SDKcalls.cpp
 | 
				
			||||||
        src/SDKcalls.h
 | 
					        src/SDKcalls.h
 | 
				
			||||||
        src/StateUtils.cpp src/StateUtils.h
 | 
					        src/StateUtils.cpp src/StateUtils.h
 | 
				
			||||||
        src/AP_WS_ReactorPool.h
 | 
					        src/AP_WS_Reactor_Pool.h
 | 
				
			||||||
        src/AP_WS_Connection.h
 | 
					        src/AP_WS_Connection.h
 | 
				
			||||||
        src/AP_WS_Connection.cpp
 | 
					        src/AP_WS_Connection.cpp
 | 
				
			||||||
        src/TelemetryClient.h src/TelemetryClient.cpp
 | 
					        src/TelemetryClient.h src/TelemetryClient.cpp
 | 
				
			||||||
@@ -211,7 +213,8 @@ add_executable( owgw
 | 
				
			|||||||
        src/RegulatoryInfo.cpp src/RegulatoryInfo.h
 | 
					        src/RegulatoryInfo.cpp src/RegulatoryInfo.h
 | 
				
			||||||
        src/RADIUSSessionTracker.cpp src/RADIUSSessionTracker.h
 | 
					        src/RADIUSSessionTracker.cpp src/RADIUSSessionTracker.h
 | 
				
			||||||
        src/libs/Scheduler.h src/libs/InterruptableSleep.h src/libs/ctpl_stl.h src/libs/Cron.h
 | 
					        src/libs/Scheduler.h src/libs/InterruptableSleep.h src/libs/ctpl_stl.h src/libs/Cron.h
 | 
				
			||||||
        src/GenericScheduler.cpp src/GenericScheduler.h src/framework/default_device_types.h src/AP_WS_Process_rebootLog.cpp src/AP_WS_ConfigAutoUpgrader.cpp src/AP_WS_ConfigAutoUpgrader.h src/RESTAPI/RESTAPI_default_firmwares.cpp src/RESTAPI/RESTAPI_default_firmwares.h src/RESTAPI/RESTAPI_default_firmware.cpp src/RESTAPI/RESTAPI_default_firmware.h src/storage/storage_def_firmware.cpp src/firmware_revision_cache.h src/sdks/sdk_fms.h)
 | 
					        src/GenericScheduler.cpp src/GenericScheduler.h src/framework/default_device_types.h src/AP_WS_Process_rebootLog.cpp src/AP_WS_ConfigAutoUpgrader.cpp src/AP_WS_ConfigAutoUpgrader.h src/RESTAPI/RESTAPI_default_firmwares.cpp src/RESTAPI/RESTAPI_default_firmwares.h src/RESTAPI/RESTAPI_default_firmware.cpp src/RESTAPI/RESTAPI_default_firmware.h src/storage/storage_def_firmware.cpp src/firmware_revision_cache.h src/sdks/sdk_fms.h
 | 
				
			||||||
 | 
					        src/AP_WS_LookForUpgrade.cpp)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
if(NOT SMALL_BUILD)
 | 
					if(NOT SMALL_BUILD)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										14
									
								
								Dockerfile
									
									
									
									
									
								
							
							
						
						
									
										14
									
								
								Dockerfile
									
									
									
									
									
								
							@@ -1,7 +1,7 @@
 | 
				
			|||||||
ARG DEBIAN_VERSION=11.5-slim
 | 
					ARG DEBIAN_VERSION=11.5-slim
 | 
				
			||||||
ARG POCO_VERSION=poco-tip-v2
 | 
					ARG POCO_VERSION=poco-tip-v2
 | 
				
			||||||
ARG CPPKAFKA_VERSION=tip-v1
 | 
					ARG CPPKAFKA_VERSION=tip-v1
 | 
				
			||||||
ARG VALIJASON_VERSION=tip-v1
 | 
					ARG VALIJASON_VERSION=tip-v1.0.2
 | 
				
			||||||
ARG APP_NAME=owgw
 | 
					ARG APP_NAME=owgw
 | 
				
			||||||
ARG APP_HOME_DIR=/openwifi
 | 
					ARG APP_HOME_DIR=/openwifi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -17,8 +17,8 @@ FROM build-base AS poco-build
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
ARG POCO_VERSION
 | 
					ARG POCO_VERSION
 | 
				
			||||||
 | 
					
 | 
				
			||||||
ADD https://api.github.com/repos/AriliaWireless/poco/git/refs/tags/${POCO_VERSION} version.json
 | 
					ADD https://api.github.com/repos/Telecominfraproject/wlan-cloud-lib-poco/git/refs/tags/${POCO_VERSION} version.json
 | 
				
			||||||
RUN git clone https://github.com/AriliaWireless/poco --branch ${POCO_VERSION} /poco
 | 
					RUN git clone https://github.com/Telecominfraproject/wlan-cloud-lib-poco --branch ${POCO_VERSION} /poco
 | 
				
			||||||
 | 
					
 | 
				
			||||||
WORKDIR /poco
 | 
					WORKDIR /poco
 | 
				
			||||||
RUN mkdir cmake-build
 | 
					RUN mkdir cmake-build
 | 
				
			||||||
@@ -31,8 +31,8 @@ FROM build-base AS cppkafka-build
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
ARG CPPKAFKA_VERSION
 | 
					ARG CPPKAFKA_VERSION
 | 
				
			||||||
 | 
					
 | 
				
			||||||
ADD https://api.github.com/repos/AriliaWireless/cppkafka/git/refs/tags/${CPPKAFKA_VERSION} version.json
 | 
					ADD https://api.github.com/repos/Telecominfraproject/wlan-cloud-lib-cppkafka/git/refs/tags/${CPPKAFKA_VERSION} version.json
 | 
				
			||||||
RUN git clone https://github.com/AriliaWireless/cppkafka --branch ${CPPKAFKA_VERSION} /cppkafka
 | 
					RUN git clone https://github.com/Telecominfraproject/wlan-cloud-lib-cppkafka --branch ${CPPKAFKA_VERSION} /cppkafka
 | 
				
			||||||
 | 
					
 | 
				
			||||||
WORKDIR /cppkafka
 | 
					WORKDIR /cppkafka
 | 
				
			||||||
RUN mkdir cmake-build
 | 
					RUN mkdir cmake-build
 | 
				
			||||||
@@ -45,8 +45,8 @@ FROM build-base AS valijson-build
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
ARG VALIJASON_VERSION
 | 
					ARG VALIJASON_VERSION
 | 
				
			||||||
 | 
					
 | 
				
			||||||
ADD https://api.github.com/repos/AriliaWireless/valijson/git/refs/tags/${VALIJASON_VERSION} version.json
 | 
					ADD https://api.github.com/repos/Telecominfraproject/wlan-cloud-lib-valijson/git/refs/tags/${VALIJASON_VERSION} version.json
 | 
				
			||||||
RUN git clone https://github.com/AriliaWireless/valijson --branch ${VALIJASON_VERSION} /valijson
 | 
					RUN git clone https://github.com/Telecominfraproject/wlan-cloud-lib-valijson --branch ${VALIJASON_VERSION} /valijson
 | 
				
			||||||
 | 
					
 | 
				
			||||||
WORKDIR /valijson
 | 
					WORKDIR /valijson
 | 
				
			||||||
RUN mkdir cmake-build
 | 
					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.
 | 
					- 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.
 | 
					- 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 wants the device to upgrade its firmware
 | 
				
			||||||
Controller sends this command when it believes the device should upgrade its firmware.
 | 
					Controller sends this command when it believes the device should upgrade its firmware.
 | 
				
			||||||
```json
 | 
					```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
 | 
					apiVersion: v2
 | 
				
			||||||
appVersion: "1.0"
 | 
					appVersion: "3.0.14"
 | 
				
			||||||
description: A Helm chart for Kubernetes
 | 
					description: A Helm chart for Kubernetes
 | 
				
			||||||
name: owgw
 | 
					name: owgw
 | 
				
			||||||
version: 0.1.0
 | 
					version: 0.1.0
 | 
				
			||||||
dependencies:
 | 
					dependencies:
 | 
				
			||||||
- name: postgresql
 | 
					  - name: postgresql
 | 
				
			||||||
  repository: https://tip.jfrog.io/artifactory/tip-wlan-cloud-ucentral-helm/
 | 
					    repository: https://tip.jfrog.io/artifactory/tip-wlan-cloud-ucentral-helm/
 | 
				
			||||||
  version: 10.9.2
 | 
					    version: 10.9.2
 | 
				
			||||||
  condition: postgresql.enabled
 | 
					    condition: postgresql.enabled
 | 
				
			||||||
- name: mysql
 | 
					  - name: mysql
 | 
				
			||||||
  repository: https://tip.jfrog.io/artifactory/tip-wlan-cloud-ucentral-helm/
 | 
					    repository: https://tip.jfrog.io/artifactory/tip-wlan-cloud-ucentral-helm/
 | 
				
			||||||
  version: 8.8.3
 | 
					    version: 8.8.3
 | 
				
			||||||
  condition: mysql.enabled
 | 
					    condition: mysql.enabled
 | 
				
			||||||
- name: mariadb
 | 
					  - name: mariadb
 | 
				
			||||||
  repository: https://tip.jfrog.io/artifactory/tip-wlan-cloud-ucentral-helm/
 | 
					    repository: https://tip.jfrog.io/artifactory/tip-wlan-cloud-ucentral-helm/
 | 
				
			||||||
  version: 9.4.2
 | 
					    version: 9.4.2
 | 
				
			||||||
  condition: mariadb.enabled
 | 
					    condition: mariadb.enabled
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2,24 +2,21 @@
 | 
				
			|||||||
replicaCount: 1
 | 
					replicaCount: 1
 | 
				
			||||||
strategyType: Recreate
 | 
					strategyType: Recreate
 | 
				
			||||||
revisionHistoryLimit: 2
 | 
					revisionHistoryLimit: 2
 | 
				
			||||||
 | 
					 | 
				
			||||||
nameOverride: ""
 | 
					nameOverride: ""
 | 
				
			||||||
fullnameOverride: ""
 | 
					fullnameOverride: ""
 | 
				
			||||||
 | 
					 | 
				
			||||||
images:
 | 
					images:
 | 
				
			||||||
  owgw:
 | 
					  owgw:
 | 
				
			||||||
    repository: tip-tip-wlan-cloud-ucentral.jfrog.io/owgw
 | 
					    repository: 471112855615.dkr.ecr.us-east-1.amazonaws.com/owgw
 | 
				
			||||||
    tag: master
 | 
					    tag: kv3.0.14
 | 
				
			||||||
    pullPolicy: Always
 | 
					    pullPolicy: Always
 | 
				
			||||||
#    regcred:
 | 
					    #    regcred:
 | 
				
			||||||
#      registry: tip-tip-wlan-cloud-ucentral.jfrog.io
 | 
					    #      registry: tip-tip-wlan-cloud-ucentral.jfrog.io
 | 
				
			||||||
#      username: username
 | 
					    #      username: username
 | 
				
			||||||
#      password: password
 | 
					    #      password: password
 | 
				
			||||||
  dockerize:
 | 
					  dockerize:
 | 
				
			||||||
    repository: tip-tip-wlan-cloud-ucentral.jfrog.io/dockerize
 | 
					    repository: 471112855615.dkr.ecr.us-east-1.amazonaws.com/wait-ready
 | 
				
			||||||
    tag: 0.16.0
 | 
					    tag: latest
 | 
				
			||||||
    pullPolicy: IfNotPresent
 | 
					    pullPolicy: IfNotPresent
 | 
				
			||||||
 | 
					 | 
				
			||||||
services:
 | 
					services:
 | 
				
			||||||
  owgw:
 | 
					  owgw:
 | 
				
			||||||
    type: ClusterIP
 | 
					    type: ClusterIP
 | 
				
			||||||
@@ -62,7 +59,6 @@ services:
 | 
				
			|||||||
        servicePort: 3799
 | 
					        servicePort: 3799
 | 
				
			||||||
        targetPort: 3799
 | 
					        targetPort: 3799
 | 
				
			||||||
        protocol: UDP
 | 
					        protocol: UDP
 | 
				
			||||||
 | 
					 | 
				
			||||||
checks:
 | 
					checks:
 | 
				
			||||||
  owgw:
 | 
					  owgw:
 | 
				
			||||||
    liveness:
 | 
					    liveness:
 | 
				
			||||||
@@ -73,33 +69,31 @@ checks:
 | 
				
			|||||||
      exec:
 | 
					      exec:
 | 
				
			||||||
        command:
 | 
					        command:
 | 
				
			||||||
          - /readiness_check
 | 
					          - /readiness_check
 | 
				
			||||||
 | 
					 | 
				
			||||||
ingresses:
 | 
					ingresses:
 | 
				
			||||||
  restapi:
 | 
					  restapi:
 | 
				
			||||||
    enabled: false
 | 
					    enabled: false
 | 
				
			||||||
    annotations: {}
 | 
					    annotations: {}
 | 
				
			||||||
      # kubernetes.io/ingress.class: nginx
 | 
					    # kubernetes.io/ingress.class: nginx
 | 
				
			||||||
      # kubernetes.io/tls-acme: "true"
 | 
					    # kubernetes.io/tls-acme: "true"
 | 
				
			||||||
    hosts:
 | 
					    hosts:
 | 
				
			||||||
    - restapi.chart-example.local
 | 
					      - restapi.chart-example.local
 | 
				
			||||||
    paths:
 | 
					    paths:
 | 
				
			||||||
    - path: /
 | 
					      - path: /
 | 
				
			||||||
      pathType: ImplementationSpecific
 | 
					        pathType: ImplementationSpecific
 | 
				
			||||||
      serviceName: owgw
 | 
					        serviceName: owgw
 | 
				
			||||||
      servicePort: restapi
 | 
					        servicePort: restapi
 | 
				
			||||||
  fileuploader:
 | 
					  fileuploader:
 | 
				
			||||||
    enabled: false
 | 
					    enabled: false
 | 
				
			||||||
    annotations: {}
 | 
					    annotations: {}
 | 
				
			||||||
      # kubernetes.io/ingress.class: nginx
 | 
					    # kubernetes.io/ingress.class: nginx
 | 
				
			||||||
      # kubernetes.io/tls-acme: "true"
 | 
					    # kubernetes.io/tls-acme: "true"
 | 
				
			||||||
    hosts:
 | 
					    hosts:
 | 
				
			||||||
    - fileuploader.chart-example.local
 | 
					      - fileuploader.chart-example.local
 | 
				
			||||||
    paths:
 | 
					    paths:
 | 
				
			||||||
    - path: /
 | 
					      - path: /
 | 
				
			||||||
      pathType: ImplementationSpecific
 | 
					        pathType: ImplementationSpecific
 | 
				
			||||||
      serviceName: owgw
 | 
					        serviceName: owgw
 | 
				
			||||||
      servicePort: fileuploader
 | 
					        servicePort: fileuploader
 | 
				
			||||||
 | 
					 | 
				
			||||||
volumes:
 | 
					volumes:
 | 
				
			||||||
  owgw:
 | 
					  owgw:
 | 
				
			||||||
    - name: config
 | 
					    - name: config
 | 
				
			||||||
@@ -125,18 +119,17 @@ volumes:
 | 
				
			|||||||
      volumeDefinition: |
 | 
					      volumeDefinition: |
 | 
				
			||||||
        persistentVolumeClaim:
 | 
					        persistentVolumeClaim:
 | 
				
			||||||
          claimName: {{ template "owgw.fullname" . }}-pvc
 | 
					          claimName: {{ template "owgw.fullname" . }}-pvc
 | 
				
			||||||
 | 
					 | 
				
			||||||
resources: {}
 | 
					resources: {}
 | 
				
			||||||
  # We usually recommend not to specify default resources and to leave this as a conscious
 | 
					# 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
 | 
					# 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
 | 
					# 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:'.
 | 
					# lines, adjust them as necessary, and remove the curly braces after 'resources:'.
 | 
				
			||||||
  # requests:
 | 
					# requests:
 | 
				
			||||||
  #  cpu: 100m
 | 
					#  cpu: 100m
 | 
				
			||||||
  #  memory: 128Mi
 | 
					#  memory: 128Mi
 | 
				
			||||||
  # limits:
 | 
					# limits:
 | 
				
			||||||
  #  cpu: 100m
 | 
					#  cpu: 100m
 | 
				
			||||||
  #  memory: 128Mi
 | 
					#  memory: 128Mi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
securityContext:
 | 
					securityContext:
 | 
				
			||||||
  fsGroup: 1000
 | 
					  fsGroup: 1000
 | 
				
			||||||
@@ -151,18 +144,12 @@ securityContext:
 | 
				
			|||||||
  #  value: "2"
 | 
					  #  value: "2"
 | 
				
			||||||
  #- name: net.ipv4.tcp_keepalive_time
 | 
					  #- name: net.ipv4.tcp_keepalive_time
 | 
				
			||||||
  #  value: "45"
 | 
					  #  value: "45"
 | 
				
			||||||
 | 
					 | 
				
			||||||
nodeSelector: {}
 | 
					nodeSelector: {}
 | 
				
			||||||
 | 
					 | 
				
			||||||
tolerations: []
 | 
					tolerations: []
 | 
				
			||||||
 | 
					 | 
				
			||||||
affinity: {}
 | 
					affinity: {}
 | 
				
			||||||
 | 
					 | 
				
			||||||
podAnnotations: {}
 | 
					podAnnotations: {}
 | 
				
			||||||
 | 
					 | 
				
			||||||
podSecurityPolicy:
 | 
					podSecurityPolicy:
 | 
				
			||||||
  enabled: false
 | 
					  enabled: false
 | 
				
			||||||
 | 
					 | 
				
			||||||
persistence:
 | 
					persistence:
 | 
				
			||||||
  enabled: true
 | 
					  enabled: true
 | 
				
			||||||
  # storageClassName: "-"
 | 
					  # storageClassName: "-"
 | 
				
			||||||
@@ -170,7 +157,6 @@ persistence:
 | 
				
			|||||||
    - ReadWriteOnce
 | 
					    - ReadWriteOnce
 | 
				
			||||||
  size: 10Gi
 | 
					  size: 10Gi
 | 
				
			||||||
  annotations: {}
 | 
					  annotations: {}
 | 
				
			||||||
 | 
					 | 
				
			||||||
# Application
 | 
					# Application
 | 
				
			||||||
public_env_variables:
 | 
					public_env_variables:
 | 
				
			||||||
  OWGW_ROOT: /owgw-data
 | 
					  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
 | 
					  # 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
 | 
					  #READINESS_METHOD: systeminfo
 | 
				
			||||||
  #OWSEC: gw-qa01.cicd.lab.wlan.tip.build:16001
 | 
					  #OWSEC: gw-qa01.cicd.lab.wlan.tip.build:16001
 | 
				
			||||||
 | 
					 | 
				
			||||||
secret_env_variables:
 | 
					secret_env_variables:
 | 
				
			||||||
  # NOTE in order for readiness check to use system info method you need to override these values to the real OWSEC credentials
 | 
					  # 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_USERNAME: tip@ucentral.com
 | 
				
			||||||
  OWSEC_PASSWORD: openwifi
 | 
					  OWSEC_PASSWORD: openwifi
 | 
				
			||||||
 | 
					 | 
				
			||||||
configProperties:
 | 
					configProperties:
 | 
				
			||||||
  # -> Public part
 | 
					  # -> Public part
 | 
				
			||||||
  # Websocket
 | 
					  # Websocket
 | 
				
			||||||
@@ -310,7 +294,6 @@ configProperties:
 | 
				
			|||||||
  archiver.db.2.keep: 7
 | 
					  archiver.db.2.keep: 7
 | 
				
			||||||
  archiver.db.3.name: commandlist
 | 
					  archiver.db.3.name: commandlist
 | 
				
			||||||
  archiver.db.3.keep: 7
 | 
					  archiver.db.3.keep: 7
 | 
				
			||||||
 | 
					 | 
				
			||||||
  # -> Secret part
 | 
					  # -> Secret part
 | 
				
			||||||
  # Websocket
 | 
					  # Websocket
 | 
				
			||||||
  ucentral.websocket.host.0.key.password: mypassword
 | 
					  ucentral.websocket.host.0.key.password: mypassword
 | 
				
			||||||
@@ -332,10 +315,8 @@ configProperties:
 | 
				
			|||||||
  ## MySQL
 | 
					  ## MySQL
 | 
				
			||||||
  storage.type.mysql.username: stephb
 | 
					  storage.type.mysql.username: stephb
 | 
				
			||||||
  storage.type.mysql.password: snoopy99
 | 
					  storage.type.mysql.password: snoopy99
 | 
				
			||||||
 | 
					 | 
				
			||||||
# NOTE: List of required certificates may be found in "certs" key. Alternative way to pass required certificates is to create external secret with all required certificates and set secret name in "existingCertsSecret" key. Details may be found in https://github.com/Telecominfraproject/wlan-cloud-ucentral-deploy/tree/main/chart#tldr
 | 
					# 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: ""
 | 
					existingCertsSecret: ""
 | 
				
			||||||
 | 
					 | 
				
			||||||
certs:
 | 
					certs:
 | 
				
			||||||
  clientcas.pem: ""
 | 
					  clientcas.pem: ""
 | 
				
			||||||
  issuer.pem: ""
 | 
					  issuer.pem: ""
 | 
				
			||||||
@@ -345,66 +326,53 @@ certs:
 | 
				
			|||||||
  root.pem: ""
 | 
					  root.pem: ""
 | 
				
			||||||
  websocket-cert.pem: ""
 | 
					  websocket-cert.pem: ""
 | 
				
			||||||
  websocket-key.pem: ""
 | 
					  websocket-key.pem: ""
 | 
				
			||||||
 | 
					 | 
				
			||||||
certsCAs:
 | 
					certsCAs:
 | 
				
			||||||
  issuer.pem: ""
 | 
					  issuer.pem: ""
 | 
				
			||||||
  root.pem: ""
 | 
					  root.pem: ""
 | 
				
			||||||
 | 
					 | 
				
			||||||
# PostgreSQL (https://github.com/bitnami/charts/tree/master/bitnami/postgresql)
 | 
					# PostgreSQL (https://github.com/bitnami/charts/tree/master/bitnami/postgresql)
 | 
				
			||||||
postgresql:
 | 
					postgresql:
 | 
				
			||||||
  enabled: false
 | 
					  enabled: false
 | 
				
			||||||
 | 
					 | 
				
			||||||
  image:
 | 
					  image:
 | 
				
			||||||
    registry: docker.io
 | 
					    registry: docker.io
 | 
				
			||||||
    repository: bitnami/postgresql
 | 
					    repository: bitnami/postgresql
 | 
				
			||||||
    tag: 11.13.0-debian-10-r0
 | 
					    tag: 11.13.0-debian-10-r0
 | 
				
			||||||
 | 
					 | 
				
			||||||
  postgresqlPostgresPassword: "rootPassword"
 | 
					  postgresqlPostgresPassword: "rootPassword"
 | 
				
			||||||
  postgresqlUsername: stephb
 | 
					  postgresqlUsername: stephb
 | 
				
			||||||
  postgresqlPassword: snoopy99
 | 
					  postgresqlPassword: snoopy99
 | 
				
			||||||
  postgresqlDatabase: owgw
 | 
					  postgresqlDatabase: owgw
 | 
				
			||||||
 | 
					 | 
				
			||||||
  persistence:
 | 
					  persistence:
 | 
				
			||||||
    enabled: true
 | 
					    enabled: true
 | 
				
			||||||
    storageClass: ""
 | 
					    storageClass: ""
 | 
				
			||||||
    size: 8Gi
 | 
					    size: 8Gi
 | 
				
			||||||
 | 
					 | 
				
			||||||
# MySQL (https://github.com/bitnami/charts/tree/master/bitnami/mysql)
 | 
					# MySQL (https://github.com/bitnami/charts/tree/master/bitnami/mysql)
 | 
				
			||||||
mysql:
 | 
					mysql:
 | 
				
			||||||
  enabled: false
 | 
					  enabled: false
 | 
				
			||||||
 | 
					 | 
				
			||||||
  image:
 | 
					  image:
 | 
				
			||||||
    registry: docker.io
 | 
					    registry: docker.io
 | 
				
			||||||
    repository: bitnami/mysql
 | 
					    repository: bitnami/mysql
 | 
				
			||||||
    tag: 8.0.26-debian-10-r10
 | 
					    tag: 8.0.26-debian-10-r10
 | 
				
			||||||
 | 
					 | 
				
			||||||
  auth:
 | 
					  auth:
 | 
				
			||||||
    rootPassword: rootPassword
 | 
					    rootPassword: rootPassword
 | 
				
			||||||
    database: owgw
 | 
					    database: owgw
 | 
				
			||||||
    username: stephb
 | 
					    username: stephb
 | 
				
			||||||
    password: snoopy99
 | 
					    password: snoopy99
 | 
				
			||||||
 | 
					 | 
				
			||||||
  primary:
 | 
					  primary:
 | 
				
			||||||
    persistence:
 | 
					    persistence:
 | 
				
			||||||
      enabled: true
 | 
					      enabled: true
 | 
				
			||||||
      storageClass: ""
 | 
					      storageClass: ""
 | 
				
			||||||
      size: 8Gi
 | 
					      size: 8Gi
 | 
				
			||||||
 | 
					 | 
				
			||||||
# MariaDB (https://github.com/bitnami/charts/tree/master/bitnami/mariadb)
 | 
					# MariaDB (https://github.com/bitnami/charts/tree/master/bitnami/mariadb)
 | 
				
			||||||
mariadb:
 | 
					mariadb:
 | 
				
			||||||
  enabled: false
 | 
					  enabled: false
 | 
				
			||||||
 | 
					 | 
				
			||||||
  image:
 | 
					  image:
 | 
				
			||||||
    registry: docker.io
 | 
					    registry: docker.io
 | 
				
			||||||
    repository: bitnami/mariadb
 | 
					    repository: bitnami/mariadb
 | 
				
			||||||
    tag: 10.5.12-debian-10-r0
 | 
					    tag: 10.5.12-debian-10-r0
 | 
				
			||||||
 | 
					 | 
				
			||||||
  auth:
 | 
					  auth:
 | 
				
			||||||
    rootPassword: rootPassword
 | 
					    rootPassword: rootPassword
 | 
				
			||||||
    database: owgw
 | 
					    database: owgw
 | 
				
			||||||
    username: stephb
 | 
					    username: stephb
 | 
				
			||||||
    password: snoopy99
 | 
					    password: snoopy99
 | 
				
			||||||
 | 
					 | 
				
			||||||
  primary:
 | 
					  primary:
 | 
				
			||||||
    persistence:
 | 
					    persistence:
 | 
				
			||||||
      enabled: true
 | 
					      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
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -12,7 +12,7 @@ info:
 | 
				
			|||||||
    url: https://www.ucentral.info/support
 | 
					    url: https://www.ucentral.info/support
 | 
				
			||||||
 | 
					
 | 
				
			||||||
servers:
 | 
					servers:
 | 
				
			||||||
  - url: 'https://localhost:16001/api/v1'
 | 
					  - url: 'https://localhost:16002/api/v1'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
security:
 | 
					security:
 | 
				
			||||||
  - bearerAuth: []
 | 
					  - bearerAuth: []
 | 
				
			||||||
@@ -42,12 +42,10 @@ components:
 | 
				
			|||||||
  schemas:
 | 
					  schemas:
 | 
				
			||||||
    DeviceType:
 | 
					    DeviceType:
 | 
				
			||||||
      type: string
 | 
					      type: string
 | 
				
			||||||
      default: AP
 | 
					      default: ap
 | 
				
			||||||
      enum:
 | 
					      enum:
 | 
				
			||||||
        - AP
 | 
					        - ap
 | 
				
			||||||
        - SWITCH
 | 
					        - switch
 | 
				
			||||||
        - IOT
 | 
					 | 
				
			||||||
        - MESH
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    DeviceRestrictionsKeyInfo:
 | 
					    DeviceRestrictionsKeyInfo:
 | 
				
			||||||
      type: object
 | 
					      type: object
 | 
				
			||||||
@@ -157,6 +155,9 @@ components:
 | 
				
			|||||||
        lastRecordedContact:
 | 
					        lastRecordedContact:
 | 
				
			||||||
          type: integer
 | 
					          type: integer
 | 
				
			||||||
          format: int64
 | 
					          format: int64
 | 
				
			||||||
 | 
					        blackListed:
 | 
				
			||||||
 | 
					          type: boolean
 | 
				
			||||||
 | 
					          readOnly: true
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    DeviceWithStatus:
 | 
					    DeviceWithStatus:
 | 
				
			||||||
      type: object
 | 
					      type: object
 | 
				
			||||||
@@ -281,6 +282,9 @@ components:
 | 
				
			|||||||
          format: float
 | 
					          format: float
 | 
				
			||||||
        connectReason:
 | 
					        connectReason:
 | 
				
			||||||
          type: string
 | 
					          type: string
 | 
				
			||||||
 | 
					        blackListed:
 | 
				
			||||||
 | 
					          type: boolean
 | 
				
			||||||
 | 
					          readOnly: true
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    DeviceList:
 | 
					    DeviceList:
 | 
				
			||||||
      type: object
 | 
					      type: object
 | 
				
			||||||
@@ -545,6 +549,12 @@ components:
 | 
				
			|||||||
        lastModified:
 | 
					        lastModified:
 | 
				
			||||||
          type: integer
 | 
					          type: integer
 | 
				
			||||||
          format: int64
 | 
					          format: int64
 | 
				
			||||||
 | 
					        platform:
 | 
				
			||||||
 | 
					          type: string
 | 
				
			||||||
 | 
					          enum:
 | 
				
			||||||
 | 
					            - ap
 | 
				
			||||||
 | 
					            - switch
 | 
				
			||||||
 | 
					          default: ap
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    DefaultConfigurationList:
 | 
					    DefaultConfigurationList:
 | 
				
			||||||
      properties:
 | 
					      properties:
 | 
				
			||||||
@@ -1566,6 +1576,30 @@ components:
 | 
				
			|||||||
          format: base64
 | 
					          format: base64
 | 
				
			||||||
          description: This is a base64 encoded string of the certificate bundle (the current bundle .tar.gz file from the PKI portal)
 | 
					          description: This is a base64 encoded string of the certificate bundle (the current bundle .tar.gz file from the PKI portal)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    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:
 | 
					paths:
 | 
				
			||||||
  /devices:
 | 
					  /devices:
 | 
				
			||||||
    get:
 | 
					    get:
 | 
				
			||||||
@@ -1657,6 +1691,22 @@ paths:
 | 
				
			|||||||
            type: integer
 | 
					            type: integer
 | 
				
			||||||
            default: 70
 | 
					            default: 70
 | 
				
			||||||
          required: false
 | 
					          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:
 | 
					      responses:
 | 
				
			||||||
        200:
 | 
					        200:
 | 
				
			||||||
          description: List devices
 | 
					          description: List devices
 | 
				
			||||||
@@ -3006,6 +3056,34 @@ paths:
 | 
				
			|||||||
        404:
 | 
					        404:
 | 
				
			||||||
          $ref: '#/components/responses/NotFound'
 | 
					          $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:
 | 
					  /ouis:
 | 
				
			||||||
    get:
 | 
					    get:
 | 
				
			||||||
      tags:
 | 
					      tags:
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -145,7 +145,7 @@ storage.type.sqlite.db = devices.db
 | 
				
			|||||||
storage.type.sqlite.idletime = 120
 | 
					storage.type.sqlite.idletime = 120
 | 
				
			||||||
storage.type.sqlite.maxsessions = 128
 | 
					storage.type.sqlite.maxsessions = 128
 | 
				
			||||||
 | 
					
 | 
				
			||||||
storage.type.postgresql.maxsessions = 64
 | 
					storage.type.postgresql.maxsessions = 250
 | 
				
			||||||
storage.type.postgresql.idletime = 60
 | 
					storage.type.postgresql.idletime = 60
 | 
				
			||||||
storage.type.postgresql.host = ${STORAGE_TYPE_POSTGRESQL_HOST}
 | 
					storage.type.postgresql.host = ${STORAGE_TYPE_POSTGRESQL_HOST}
 | 
				
			||||||
storage.type.postgresql.username = ${STORAGE_TYPE_POSTGRESQL_USERNAME}
 | 
					storage.type.postgresql.username = ${STORAGE_TYPE_POSTGRESQL_USERNAME}
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										15
									
								
								package.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								package.json
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,15 @@
 | 
				
			|||||||
 | 
					{
 | 
				
			||||||
 | 
					  "name": "owgw",
 | 
				
			||||||
 | 
					  "version": "3.0.14",
 | 
				
			||||||
 | 
					  "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 {
 | 
					namespace OpenWifi {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	int AP_WS_ConfigAutoUpgrader::Start() {
 | 
						int AP_WS_ConfigAutoUpgradeAgent::Start() {
 | 
				
			||||||
		poco_notice(Logger(), "Starting...");
 | 
							poco_notice(Logger(), "Starting...");
 | 
				
			||||||
		QueueManager_.start(*this);
 | 
							QueueManager_.start(*this);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		return 0;
 | 
							return 0;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	void AP_WS_ConfigAutoUpgrader::Stop() {
 | 
						void AP_WS_ConfigAutoUpgradeAgent::Stop() {
 | 
				
			||||||
		poco_notice(Logger(), "Stopping...");
 | 
							poco_notice(Logger(), "Stopping...");
 | 
				
			||||||
		Running_ = false;
 | 
							Running_ = false;
 | 
				
			||||||
		Queue_.wakeUpAll();
 | 
							Queue_.wakeUpAll();
 | 
				
			||||||
@@ -24,7 +24,7 @@ namespace OpenWifi {
 | 
				
			|||||||
		poco_notice(Logger(), "Stopped...");
 | 
							poco_notice(Logger(), "Stopped...");
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	void AP_WS_ConfigAutoUpgrader::run() {
 | 
						void AP_WS_ConfigAutoUpgradeAgent::run() {
 | 
				
			||||||
		Utils::SetThreadName("auto:cfgmgr");
 | 
							Utils::SetThreadName("auto:cfgmgr");
 | 
				
			||||||
		Running_ = true;
 | 
							Running_ = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -28,14 +28,14 @@ namespace OpenWifi {
 | 
				
			|||||||
		std::uint64_t pending_config_=0;
 | 
							std::uint64_t pending_config_=0;
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	class AP_WS_ConfigAutoUpgrader : public SubSystemServer, Poco::Runnable {
 | 
						class AP_WS_ConfigAutoUpgradeAgent : public SubSystemServer, Poco::Runnable {
 | 
				
			||||||
	  public:
 | 
						  public:
 | 
				
			||||||
		int Start() final;
 | 
							int Start() final;
 | 
				
			||||||
		void Stop() final;
 | 
							void Stop() final;
 | 
				
			||||||
		void run() final;
 | 
							void run() final;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		static auto instance() {
 | 
							static auto instance() {
 | 
				
			||||||
			static auto instance = new AP_WS_ConfigAutoUpgrader;
 | 
								static auto instance = new AP_WS_ConfigAutoUpgradeAgent;
 | 
				
			||||||
			return instance;
 | 
								return instance;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -126,12 +126,12 @@ namespace OpenWifi {
 | 
				
			|||||||
		mutable std::mutex			CacheMutex_;
 | 
							mutable std::mutex			CacheMutex_;
 | 
				
			||||||
		std::map<std::uint64_t, ConfigurationCacheEntry> Cache_;
 | 
							std::map<std::uint64_t, ConfigurationCacheEntry> Cache_;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		AP_WS_ConfigAutoUpgrader() noexcept
 | 
							AP_WS_ConfigAutoUpgradeAgent() noexcept
 | 
				
			||||||
			: SubSystemServer("AutoConfigUpgrade", "AUTO-CFG-MGR", "auto.config.updater") {
 | 
								: 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
 | 
					} // namespace OpenWifi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2,56 +2,49 @@
 | 
				
			|||||||
// Created by stephane bourque on 2022-02-03.
 | 
					// Created by stephane bourque on 2022-02-03.
 | 
				
			||||||
//
 | 
					//
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "AP_WS_Connection.h"
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "Poco/Base64Decoder.h"
 | 
					#include <Poco/Base64Decoder.h>
 | 
				
			||||||
#include "Poco/Net/Context.h"
 | 
					#include <Poco/Net/Context.h>
 | 
				
			||||||
#include "Poco/Net/HTTPServerRequestImpl.h"
 | 
					#include <Poco/Net/HTTPServerRequestImpl.h>
 | 
				
			||||||
#include "Poco/Net/HTTPServerResponseImpl.h"
 | 
					#include <Poco/Net/HTTPServerResponseImpl.h>
 | 
				
			||||||
#include "Poco/Net/NetException.h"
 | 
					#include <Poco/Net/NetException.h>
 | 
				
			||||||
#include "Poco/Net/SSLException.h"
 | 
					#include <Poco/Net/SSLException.h>
 | 
				
			||||||
#include "Poco/Net/SecureStreamSocketImpl.h"
 | 
					#include <Poco/Net/SecureStreamSocketImpl.h>
 | 
				
			||||||
#include "Poco/Net/WebSocketImpl.h"
 | 
					#include <Poco/Net/WebSocketImpl.h>
 | 
				
			||||||
#include "Poco/zlib.h"
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "AP_WS_Server.h"
 | 
					#include <framework/KafkaManager.h>
 | 
				
			||||||
#include "CentralConfig.h"
 | 
					#include <framework/MicroServiceFuncs.h>
 | 
				
			||||||
#include "CommandManager.h"
 | 
					#include <framework/utils.h>
 | 
				
			||||||
#include "ConfigurationCache.h"
 | 
					#include <framework/ow_constants.h>
 | 
				
			||||||
#include "StorageService.h"
 | 
					 | 
				
			||||||
#include "TelemetryStream.h"
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "GWKafkaEvents.h"
 | 
					#include <fmt/format.h>
 | 
				
			||||||
#include "UI_GW_WebSocketNotifications.h"
 | 
					 | 
				
			||||||
#include "framework/KafkaManager.h"
 | 
					 | 
				
			||||||
#include "framework/MicroServiceFuncs.h"
 | 
					 | 
				
			||||||
#include "framework/utils.h"
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "fmt/format.h"
 | 
					#include <AP_WS_Connection.h>
 | 
				
			||||||
 | 
					#include <AP_WS_Server.h>
 | 
				
			||||||
#include "framework/ow_constants.h"
 | 
					#include <CentralConfig.h>
 | 
				
			||||||
 | 
					#include <CommandManager.h>
 | 
				
			||||||
#include "RADIUSSessionTracker.h"
 | 
					#include <StorageService.h>
 | 
				
			||||||
#include "RADIUS_proxy_server.h"
 | 
					#include <RADIUSSessionTracker.h>
 | 
				
			||||||
 | 
					#include <RADIUS_proxy_server.h>
 | 
				
			||||||
 | 
					#include <GWKafkaEvents.h>
 | 
				
			||||||
 | 
					#include <UI_GW_WebSocketNotifications.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace OpenWifi {
 | 
					namespace OpenWifi {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define DBL                                                                                        \
 | 
					 | 
				
			||||||
	{                                                                                              \
 | 
					 | 
				
			||||||
		std::cout << __LINE__ << "  ID: " << ConnectionId_ << "  Ser: " << SerialNumber_           \
 | 
					 | 
				
			||||||
				  << std::endl;                                                                    \
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	void AP_WS_Connection::LogException(const Poco::Exception &E) {
 | 
						void AP_WS_Connection::LogException(const Poco::Exception &E) {
 | 
				
			||||||
		poco_information(Logger_, fmt::format("EXCEPTION({}): {}", CId_, E.displayText()));
 | 
							poco_information(Logger_, fmt::format("EXCEPTION({}): {}", CId_, E.displayText()));
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	AP_WS_Connection::AP_WS_Connection(Poco::Net::HTTPServerRequest &request,
 | 
						AP_WS_Connection::AP_WS_Connection(Poco::Net::HTTPServerRequest &request,
 | 
				
			||||||
									   Poco::Net::HTTPServerResponse &response,
 | 
														   Poco::Net::HTTPServerResponse &response,
 | 
				
			||||||
									   uint64_t connection_id, Poco::Logger &L,
 | 
														   uint64_t session_id, Poco::Logger &L,
 | 
				
			||||||
									   Poco::Net::SocketReactor &R)
 | 
														   std::pair<std::shared_ptr<Poco::Net::SocketReactor>, std::shared_ptr<LockedDbSession>> R)
 | 
				
			||||||
		: Logger_(L), Reactor_(R) {
 | 
							: Logger_(L) {
 | 
				
			||||||
		State_.sessionId = connection_id;
 | 
					
 | 
				
			||||||
 | 
							Reactor_ = R.first;
 | 
				
			||||||
 | 
							DbSession_ = R.second;
 | 
				
			||||||
 | 
							State_.sessionId = session_id;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		WS_ = std::make_unique<Poco::Net::WebSocket>(request, response);
 | 
							WS_ = std::make_unique<Poco::Net::WebSocket>(request, response);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		auto TS = Poco::Timespan(360, 0);
 | 
							auto TS = Poco::Timespan(360, 0);
 | 
				
			||||||
@@ -61,29 +54,86 @@ namespace OpenWifi {
 | 
				
			|||||||
		WS_->setNoDelay(false);
 | 
							WS_->setNoDelay(false);
 | 
				
			||||||
		WS_->setKeepAlive(true);
 | 
							WS_->setKeepAlive(true);
 | 
				
			||||||
		WS_->setBlocking(false);
 | 
							WS_->setBlocking(false);
 | 
				
			||||||
 | 
					 | 
				
			||||||
		Reactor_.addEventHandler(*WS_,
 | 
					 | 
				
			||||||
								 Poco::NObserver<AP_WS_Connection, Poco::Net::ReadableNotification>(
 | 
					 | 
				
			||||||
									 *this, &AP_WS_Connection::OnSocketReadable));
 | 
					 | 
				
			||||||
		Reactor_.addEventHandler(*WS_,
 | 
					 | 
				
			||||||
								 Poco::NObserver<AP_WS_Connection, Poco::Net::ShutdownNotification>(
 | 
					 | 
				
			||||||
									 *this, &AP_WS_Connection::OnSocketShutdown));
 | 
					 | 
				
			||||||
		Reactor_.addEventHandler(*WS_,
 | 
					 | 
				
			||||||
								 Poco::NObserver<AP_WS_Connection, Poco::Net::ErrorNotification>(
 | 
					 | 
				
			||||||
									 *this, &AP_WS_Connection::OnSocketError));
 | 
					 | 
				
			||||||
		Registered_ = true;
 | 
					 | 
				
			||||||
		Valid_ = true;
 | 
					 | 
				
			||||||
		uuid_ = MicroServiceRandom(std::numeric_limits<std::uint64_t>::max()-1);
 | 
							uuid_ = MicroServiceRandom(std::numeric_limits<std::uint64_t>::max()-1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							AP_WS_Server()->IncrementConnectionCount();
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						void AP_WS_Connection::Start() {
 | 
				
			||||||
 | 
							Registered_ = true;
 | 
				
			||||||
 | 
							LastContact_ = Utils::Now();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							Reactor_->addEventHandler(*WS_,
 | 
				
			||||||
 | 
													  Poco::NObserver<AP_WS_Connection, Poco::Net::ReadableNotification>(
 | 
				
			||||||
 | 
														  *this, &AP_WS_Connection::OnSocketReadable));
 | 
				
			||||||
 | 
							Reactor_->addEventHandler(*WS_,
 | 
				
			||||||
 | 
													  Poco::NObserver<AP_WS_Connection, Poco::Net::ShutdownNotification>(
 | 
				
			||||||
 | 
														  *this, &AP_WS_Connection::OnSocketShutdown));
 | 
				
			||||||
 | 
							Reactor_->addEventHandler(*WS_,
 | 
				
			||||||
 | 
													  Poco::NObserver<AP_WS_Connection, Poco::Net::ErrorNotification>(
 | 
				
			||||||
 | 
														  *this, &AP_WS_Connection::OnSocketError));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						AP_WS_Connection::~AP_WS_Connection() {
 | 
				
			||||||
 | 
							std::lock_guard G(ConnectionMutex_);
 | 
				
			||||||
 | 
							AP_WS_Server()->DecrementConnectionCount();
 | 
				
			||||||
 | 
							EndConnection();
 | 
				
			||||||
 | 
							poco_debug(Logger_, fmt::format("TERMINATION({}): Session={}, Connection removed.", SerialNumber_,
 | 
				
			||||||
 | 
															State_.sessionId));
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						static void NotifyKafkaDisconnect(const std::string &SerialNumber, std::uint64_t uuid) {
 | 
				
			||||||
 | 
							try {
 | 
				
			||||||
 | 
								Poco::JSON::Object Disconnect;
 | 
				
			||||||
 | 
								Poco::JSON::Object Details;
 | 
				
			||||||
 | 
								Details.set(uCentralProtocol::SERIALNUMBER, SerialNumber);
 | 
				
			||||||
 | 
								Details.set(uCentralProtocol::TIMESTAMP, Utils::Now());
 | 
				
			||||||
 | 
								Details.set(uCentralProtocol::UUID,uuid);
 | 
				
			||||||
 | 
								Disconnect.set(uCentralProtocol::DISCONNECTION, Details);
 | 
				
			||||||
 | 
								KafkaManager()->PostMessage(KafkaTopics::CONNECTION, SerialNumber, Disconnect);
 | 
				
			||||||
 | 
							} catch (...) {
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						void AP_WS_Connection::EndConnection() {
 | 
				
			||||||
 | 
							bool expectedValue=false;
 | 
				
			||||||
 | 
							if (Dead_.compare_exchange_strong(expectedValue,true,std::memory_order_release,std::memory_order_relaxed)) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if(!SerialNumber_.empty() && State_.LastContact!=0) {
 | 
				
			||||||
 | 
									StorageService()->SetDeviceLastRecordedContact(SerialNumber_, State_.LastContact);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if (Registered_) {
 | 
				
			||||||
 | 
									Registered_ = false;
 | 
				
			||||||
 | 
									Reactor_->removeEventHandler(
 | 
				
			||||||
 | 
										*WS_, Poco::NObserver<AP_WS_Connection, Poco::Net::ReadableNotification>(
 | 
				
			||||||
 | 
												  *this, &AP_WS_Connection::OnSocketReadable));
 | 
				
			||||||
 | 
									Reactor_->removeEventHandler(
 | 
				
			||||||
 | 
										*WS_, Poco::NObserver<AP_WS_Connection, Poco::Net::ShutdownNotification>(
 | 
				
			||||||
 | 
												  *this, &AP_WS_Connection::OnSocketShutdown));
 | 
				
			||||||
 | 
									Reactor_->removeEventHandler(
 | 
				
			||||||
 | 
										*WS_, Poco::NObserver<AP_WS_Connection, Poco::Net::ErrorNotification>(
 | 
				
			||||||
 | 
												  *this, &AP_WS_Connection::OnSocketError));
 | 
				
			||||||
 | 
									Registered_=false;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								WS_->close();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if(!SerialNumber_.empty()) {
 | 
				
			||||||
 | 
									DeviceDisconnectionCleanup(SerialNumber_, uuid_);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								AP_WS_Server()->AddCleanupSession(State_.sessionId, SerialNumberInt_);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	bool AP_WS_Connection::ValidatedDevice() {
 | 
						bool AP_WS_Connection::ValidatedDevice() {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if(Dead_)
 | 
				
			||||||
 | 
								return false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (DeviceValidated_)
 | 
							if (DeviceValidated_)
 | 
				
			||||||
			return true;
 | 
								return true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (!Valid_)
 | 
					 | 
				
			||||||
			return false;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		std::lock_guard Lock(ConnectionMutex_);
 | 
					 | 
				
			||||||
		try {
 | 
							try {
 | 
				
			||||||
			auto SockImpl = dynamic_cast<Poco::Net::WebSocketImpl *>(WS_->impl());
 | 
								auto SockImpl = dynamic_cast<Poco::Net::WebSocketImpl *>(WS_->impl());
 | 
				
			||||||
			auto SS =
 | 
								auto SS =
 | 
				
			||||||
@@ -98,7 +148,6 @@ namespace OpenWifi {
 | 
				
			|||||||
				poco_warning(Logger_, fmt::format("TLS-CONNECTION({}): Session={} Connection is "
 | 
									poco_warning(Logger_, fmt::format("TLS-CONNECTION({}): Session={} Connection is "
 | 
				
			||||||
												  "NOT secure. Device is not allowed.",
 | 
																	  "NOT secure. Device is not allowed.",
 | 
				
			||||||
												  CId_, State_.sessionId));
 | 
																	  CId_, State_.sessionId));
 | 
				
			||||||
				EndConnection();
 | 
					 | 
				
			||||||
				return false;
 | 
									return false;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -111,7 +160,6 @@ namespace OpenWifi {
 | 
				
			|||||||
					Logger_,
 | 
										Logger_,
 | 
				
			||||||
					fmt::format("TLS-CONNECTION({}): Session={} No certificates available..", CId_,
 | 
										fmt::format("TLS-CONNECTION({}): Session={} No certificates available..", CId_,
 | 
				
			||||||
								State_.sessionId));
 | 
													State_.sessionId));
 | 
				
			||||||
				EndConnection();
 | 
					 | 
				
			||||||
				return false;
 | 
									return false;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -122,11 +170,19 @@ namespace OpenWifi {
 | 
				
			|||||||
							 fmt::format("TLS-CONNECTION({}): Session={} Device certificate is not "
 | 
												 fmt::format("TLS-CONNECTION({}): Session={} Device certificate is not "
 | 
				
			||||||
										 "valid. Device is not allowed.",
 | 
															 "valid. Device is not allowed.",
 | 
				
			||||||
										 CId_, State_.sessionId));
 | 
															 CId_, State_.sessionId));
 | 
				
			||||||
				EndConnection();
 | 
					 | 
				
			||||||
				return false;
 | 
									return false;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			CN_ = Poco::trim(Poco::toLower(PeerCert.commonName()));
 | 
								CN_ = Poco::trim(Poco::toLower(PeerCert.commonName()));
 | 
				
			||||||
 | 
								if(!Utils::ValidSerialNumber(CN_)) {
 | 
				
			||||||
 | 
									poco_trace(Logger_,
 | 
				
			||||||
 | 
											   fmt::format("TLS-CONNECTION({}): Session={} Invalid serial number: CN={}", CId_,
 | 
				
			||||||
 | 
														   State_.sessionId, CN_));
 | 
				
			||||||
 | 
									return false;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								SerialNumber_ = CN_;
 | 
				
			||||||
 | 
								SerialNumberInt_ = Utils::SerialNumberToInt(SerialNumber_);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			State_.VerifiedCertificate = GWObjects::VALID_CERTIFICATE;
 | 
								State_.VerifiedCertificate = GWObjects::VALID_CERTIFICATE;
 | 
				
			||||||
			poco_trace(Logger_,
 | 
								poco_trace(Logger_,
 | 
				
			||||||
					   fmt::format("TLS-CONNECTION({}): Session={} Valid certificate: CN={}", CId_,
 | 
										   fmt::format("TLS-CONNECTION({}): Session={} Valid certificate: CN={}", CId_,
 | 
				
			||||||
@@ -136,31 +192,27 @@ namespace OpenWifi {
 | 
				
			|||||||
				poco_warning(Logger_, fmt::format("TLS-CONNECTION({}): Session={} Sim Device {} is "
 | 
									poco_warning(Logger_, fmt::format("TLS-CONNECTION({}): Session={} Sim Device {} is "
 | 
				
			||||||
												  "not allowed. Disconnecting.",
 | 
																	  "not allowed. Disconnecting.",
 | 
				
			||||||
												  CId_, State_.sessionId, CN_));
 | 
																	  CId_, State_.sessionId, CN_));
 | 
				
			||||||
				EndConnection();
 | 
					 | 
				
			||||||
				return false;
 | 
									return false;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if(AP_WS_Server::IsSim(CN_)) {
 | 
								if(AP_WS_Server::IsSim(SerialNumber_)) {
 | 
				
			||||||
				State_.VerifiedCertificate = GWObjects::SIMULATED;
 | 
									State_.VerifiedCertificate = GWObjects::SIMULATED;
 | 
				
			||||||
				Simulated_ = true;
 | 
									Simulated_ = true;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			std::string reason, author;
 | 
								std::string reason, author;
 | 
				
			||||||
			std::uint64_t created;
 | 
								std::uint64_t created;
 | 
				
			||||||
			if (!CN_.empty() && StorageService()->IsBlackListed(CN_, reason, author, created)) {
 | 
								if (!CN_.empty() && StorageService()->IsBlackListed(SerialNumberInt_, reason, author, created)) {
 | 
				
			||||||
				DeviceBlacklistedKafkaEvent KE(Utils::SerialNumberToInt(CN_), Utils::Now(), reason, author, created, CId_);
 | 
									DeviceBlacklistedKafkaEvent KE(Utils::SerialNumberToInt(CN_), Utils::Now(), reason, author, created, CId_);
 | 
				
			||||||
				poco_warning(
 | 
									poco_warning(
 | 
				
			||||||
					Logger_,
 | 
										Logger_,
 | 
				
			||||||
					fmt::format(
 | 
										fmt::format(
 | 
				
			||||||
						"TLS-CONNECTION({}): Session={} Device {} is black listed. Disconnecting.",
 | 
											"TLS-CONNECTION({}): Session={} Device {} is black listed. Disconnecting.",
 | 
				
			||||||
						CId_, State_.sessionId, CN_));
 | 
											CId_, State_.sessionId, CN_));
 | 
				
			||||||
				EndConnection();
 | 
					 | 
				
			||||||
				return false;
 | 
									return false;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			State_.certificateExpiryDate = PeerCert.expiresOn().timestamp().epochTime();
 | 
								State_.certificateExpiryDate = PeerCert.expiresOn().timestamp().epochTime();
 | 
				
			||||||
			SerialNumber_ = CN_;
 | 
					 | 
				
			||||||
			SerialNumberInt_ = Utils::SerialNumberToInt(SerialNumber_);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
			poco_trace(Logger_,
 | 
								poco_trace(Logger_,
 | 
				
			||||||
					   fmt::format("TLS-CONNECTION({}): Session={} CN={} Completed. (t={})", CId_,
 | 
										   fmt::format("TLS-CONNECTION({}): Session={} CN={} Completed. (t={})", CId_,
 | 
				
			||||||
@@ -224,149 +276,14 @@ namespace OpenWifi {
 | 
				
			|||||||
		return false;
 | 
							return false;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	static void NotifyKafkaDisconnect(const std::string &SerialNumber, std::uint64_t uuid) {
 | 
						void AP_WS_Connection::DeviceDisconnectionCleanup(const std::string &SerialNumber, std::uint64_t uuid) {
 | 
				
			||||||
		try {
 | 
					 | 
				
			||||||
			Poco::JSON::Object Disconnect;
 | 
					 | 
				
			||||||
			Poco::JSON::Object Details;
 | 
					 | 
				
			||||||
			Details.set(uCentralProtocol::SERIALNUMBER, SerialNumber);
 | 
					 | 
				
			||||||
			Details.set(uCentralProtocol::TIMESTAMP, Utils::Now());
 | 
					 | 
				
			||||||
			Details.set(uCentralProtocol::UUID,uuid);
 | 
					 | 
				
			||||||
			Disconnect.set(uCentralProtocol::DISCONNECTION, Details);
 | 
					 | 
				
			||||||
			KafkaManager()->PostMessage(KafkaTopics::CONNECTION, SerialNumber, Disconnect);
 | 
					 | 
				
			||||||
		} catch (...) {
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	AP_WS_Connection::~AP_WS_Connection() {
 | 
					 | 
				
			||||||
		Valid_ = false;
 | 
					 | 
				
			||||||
		EndConnection();
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	void DeviceDisconnectionCleanup(const std::string &SerialNumber, std::uint64_t uuid) {
 | 
					 | 
				
			||||||
		if (KafkaManager()->Enabled()) {
 | 
							if (KafkaManager()->Enabled()) {
 | 
				
			||||||
			NotifyKafkaDisconnect(SerialNumber, uuid);
 | 
								NotifyKafkaDisconnect(SerialNumber, uuid);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		RADIUSSessionTracker()->DeviceDisconnect(SerialNumber);
 | 
							RADIUSSessionTracker()->DeviceDisconnect(SerialNumber);
 | 
				
			||||||
	}
 | 
							GWWebSocketNotifications::SingleDevice_t N;
 | 
				
			||||||
 | 
							N.content.serialNumber = SerialNumber;
 | 
				
			||||||
	void AP_WS_Connection::EndConnection(bool DeleteSession) {
 | 
							GWWebSocketNotifications::DeviceDisconnected(N);
 | 
				
			||||||
    	Valid_ = false;
 | 
					 | 
				
			||||||
		if (!Dead_.test_and_set()) {
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			if(!SerialNumber_.empty() && State_.LastContact!=0) {
 | 
					 | 
				
			||||||
				StorageService()->SetDeviceLastRecordedContact(SerialNumber_, State_.LastContact);
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			if (Registered_) {
 | 
					 | 
				
			||||||
				Registered_ = false;
 | 
					 | 
				
			||||||
				Reactor_.removeEventHandler(
 | 
					 | 
				
			||||||
					*WS_, Poco::NObserver<AP_WS_Connection, Poco::Net::ReadableNotification>(
 | 
					 | 
				
			||||||
							  *this, &AP_WS_Connection::OnSocketReadable));
 | 
					 | 
				
			||||||
				Reactor_.removeEventHandler(
 | 
					 | 
				
			||||||
					*WS_, Poco::NObserver<AP_WS_Connection, Poco::Net::ShutdownNotification>(
 | 
					 | 
				
			||||||
							  *this, &AP_WS_Connection::OnSocketShutdown));
 | 
					 | 
				
			||||||
				Reactor_.removeEventHandler(
 | 
					 | 
				
			||||||
					*WS_, Poco::NObserver<AP_WS_Connection, Poco::Net::ErrorNotification>(
 | 
					 | 
				
			||||||
							  *this, &AP_WS_Connection::OnSocketError));
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			WS_->close();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			if(!SerialNumber_.empty()) {
 | 
					 | 
				
			||||||
				std::thread	Cleanup(DeviceDisconnectionCleanup,SerialNumber_, uuid_);
 | 
					 | 
				
			||||||
				Cleanup.detach();
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			bool SessionDeleted = false;
 | 
					 | 
				
			||||||
			if(DeleteSession)
 | 
					 | 
				
			||||||
				SessionDeleted = AP_WS_Server()->EndSession(State_.sessionId, SerialNumberInt_);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			if (SessionDeleted || !DeleteSession) {
 | 
					 | 
				
			||||||
				GWWebSocketNotifications::SingleDevice_t N;
 | 
					 | 
				
			||||||
				N.content.serialNumber = SerialNumber_;
 | 
					 | 
				
			||||||
				GWWebSocketNotifications::DeviceDisconnected(N);
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	bool AP_WS_Connection::LookForUpgrade(const uint64_t UUID, uint64_t &UpgradedUUID) {
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		//	A UUID of zero means ignore updates for that connection.
 | 
					 | 
				
			||||||
		if (UUID == 0)
 | 
					 | 
				
			||||||
			return false;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		uint64_t GoodConfig = ConfigurationCache().CurrentConfig(SerialNumberInt_);
 | 
					 | 
				
			||||||
		if (GoodConfig && (GoodConfig == UUID || GoodConfig == State_.PendingUUID)) {
 | 
					 | 
				
			||||||
			UpgradedUUID = UUID;
 | 
					 | 
				
			||||||
			return false;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		GWObjects::Device D;
 | 
					 | 
				
			||||||
		if (StorageService()->GetDevice(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(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);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			return true;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		return false;
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	void AP_WS_Connection::ProcessJSONRPCResult(Poco::JSON::Object::Ptr Doc) {
 | 
						void AP_WS_Connection::ProcessJSONRPCResult(Poco::JSON::Object::Ptr Doc) {
 | 
				
			||||||
@@ -447,7 +364,7 @@ namespace OpenWifi {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
		std::string reason, author;
 | 
							std::string reason, author;
 | 
				
			||||||
		std::uint64_t created;
 | 
							std::uint64_t created;
 | 
				
			||||||
		if (StorageService()->IsBlackListed(Serial, reason, author, created)) {
 | 
							if (StorageService()->IsBlackListed(SerialNumberInt_, reason, author, created)) {
 | 
				
			||||||
			DeviceBlacklistedKafkaEvent KE(Utils::SerialNumberToInt(CN_), Utils::Now(), reason, author, created, CId_);
 | 
								DeviceBlacklistedKafkaEvent KE(Utils::SerialNumberToInt(CN_), Utils::Now(), reason, author, created, CId_);
 | 
				
			||||||
			Poco::Exception E(
 | 
								Poco::Exception E(
 | 
				
			||||||
				fmt::format("BLACKLIST({}): device is blacklisted and not allowed to connect.",
 | 
									fmt::format("BLACKLIST({}): device is blacklisted and not allowed to connect.",
 | 
				
			||||||
@@ -578,17 +495,17 @@ namespace OpenWifi {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	bool AP_WS_Connection::SetWebSocketTelemetryReporting(
 | 
						bool AP_WS_Connection::SetWebSocketTelemetryReporting(
 | 
				
			||||||
		uint64_t RPCID, uint64_t Interval, uint64_t LifeTime,
 | 
							std::uint64_t RPCID, std::uint64_t Interval, std::uint64_t LifeTime,
 | 
				
			||||||
		const std::vector<std::string> &TelemetryTypes) {
 | 
							const std::vector<std::string> &TelemetryTypes) {
 | 
				
			||||||
		std::unique_lock Lock(TelemetryMutex_);
 | 
							std::unique_lock Lock(TelemetryMutex_);
 | 
				
			||||||
		TelemetryWebSocketRefCount_++;
 | 
							TelemetryWebSocketRefCount_++;
 | 
				
			||||||
		TelemetryInterval_ = TelemetryInterval_
 | 
							TelemetryInterval_ = TelemetryInterval_
 | 
				
			||||||
								 ? (Interval < TelemetryInterval_ ? Interval : TelemetryInterval_)
 | 
													 ? (Interval < (std::uint64_t)TelemetryInterval_ ? Interval : (std::uint64_t )TelemetryInterval_)
 | 
				
			||||||
								 : Interval;
 | 
													 : Interval;
 | 
				
			||||||
		auto TelemetryWebSocketTimer = LifeTime + Utils::Now();
 | 
							auto TelemetryWebSocketTimer = LifeTime + Utils::Now();
 | 
				
			||||||
		TelemetryWebSocketTimer_ = TelemetryWebSocketTimer > TelemetryWebSocketTimer_
 | 
							TelemetryWebSocketTimer_ = TelemetryWebSocketTimer > (std::uint64_t)TelemetryWebSocketTimer_
 | 
				
			||||||
									   ? TelemetryWebSocketTimer
 | 
														   ? (std::uint64_t)TelemetryWebSocketTimer
 | 
				
			||||||
									   : TelemetryWebSocketTimer_;
 | 
														   : (std::uint64_t)TelemetryWebSocketTimer_;
 | 
				
			||||||
		UpdateCounts();
 | 
							UpdateCounts();
 | 
				
			||||||
		if (!TelemetryReporting_) {
 | 
							if (!TelemetryReporting_) {
 | 
				
			||||||
			TelemetryReporting_ = true;
 | 
								TelemetryReporting_ = true;
 | 
				
			||||||
@@ -604,11 +521,11 @@ namespace OpenWifi {
 | 
				
			|||||||
		std::unique_lock Lock(TelemetryMutex_);
 | 
							std::unique_lock Lock(TelemetryMutex_);
 | 
				
			||||||
		TelemetryKafkaRefCount_++;
 | 
							TelemetryKafkaRefCount_++;
 | 
				
			||||||
		TelemetryInterval_ = TelemetryInterval_
 | 
							TelemetryInterval_ = TelemetryInterval_
 | 
				
			||||||
								 ? (Interval < TelemetryInterval_ ? Interval : TelemetryInterval_)
 | 
													 ? (Interval < (std::uint64_t)TelemetryInterval_ ? (std::uint64_t)Interval : (std::uint64_t)TelemetryInterval_)
 | 
				
			||||||
								 : Interval;
 | 
													 : Interval;
 | 
				
			||||||
		auto TelemetryKafkaTimer = LifeTime + Utils::Now();
 | 
							auto TelemetryKafkaTimer = LifeTime + Utils::Now();
 | 
				
			||||||
		TelemetryKafkaTimer_ =
 | 
							TelemetryKafkaTimer_ =
 | 
				
			||||||
			TelemetryKafkaTimer > TelemetryKafkaTimer_ ? TelemetryKafkaTimer : TelemetryKafkaTimer_;
 | 
								TelemetryKafkaTimer > (std::uint64_t)TelemetryKafkaTimer_ ? (std::uint64_t)TelemetryKafkaTimer : (std::uint64_t)TelemetryKafkaTimer_;
 | 
				
			||||||
		UpdateCounts();
 | 
							UpdateCounts();
 | 
				
			||||||
		if (!TelemetryReporting_) {
 | 
							if (!TelemetryReporting_) {
 | 
				
			||||||
			TelemetryReporting_ = true;
 | 
								TelemetryReporting_ = true;
 | 
				
			||||||
@@ -644,49 +561,50 @@ namespace OpenWifi {
 | 
				
			|||||||
	void AP_WS_Connection::OnSocketShutdown(
 | 
						void AP_WS_Connection::OnSocketShutdown(
 | 
				
			||||||
		[[maybe_unused]] const Poco::AutoPtr<Poco::Net::ShutdownNotification> &pNf) {
 | 
							[[maybe_unused]] const Poco::AutoPtr<Poco::Net::ShutdownNotification> &pNf) {
 | 
				
			||||||
		poco_trace(Logger_, fmt::format("SOCKET-SHUTDOWN({}): Closing.", CId_));
 | 
							poco_trace(Logger_, fmt::format("SOCKET-SHUTDOWN({}): Closing.", CId_));
 | 
				
			||||||
 | 
					//		std::lock_guard	G(ConnectionMutex_);
 | 
				
			||||||
		return EndConnection();
 | 
							return EndConnection();
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	void AP_WS_Connection::OnSocketError(
 | 
						void AP_WS_Connection::OnSocketError(
 | 
				
			||||||
		[[maybe_unused]] const Poco::AutoPtr<Poco::Net::ErrorNotification> &pNf) {
 | 
							[[maybe_unused]] const Poco::AutoPtr<Poco::Net::ErrorNotification> &pNf) {
 | 
				
			||||||
		poco_trace(Logger_, fmt::format("SOCKET-ERROR({}): Closing.", CId_));
 | 
							poco_trace(Logger_, fmt::format("SOCKET-ERROR({}): Closing.", CId_));
 | 
				
			||||||
 | 
					//		std::lock_guard	G(ConnectionMutex_);
 | 
				
			||||||
		return EndConnection();
 | 
							return EndConnection();
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	void AP_WS_Connection::OnSocketReadable(
 | 
						void AP_WS_Connection::OnSocketReadable(
 | 
				
			||||||
		[[maybe_unused]] const Poco::AutoPtr<Poco::Net::ReadableNotification> &pNf) {
 | 
							[[maybe_unused]] const Poco::AutoPtr<Poco::Net::ReadableNotification> &pNf) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (!Valid_)
 | 
							if (Dead_) //	we are dead, so we do not process anything.
 | 
				
			||||||
			return;
 | 
								return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (!AP_WS_Server()->Running())
 | 
							std::lock_guard	G(ConnectionMutex_);
 | 
				
			||||||
			return EndConnection();
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (!ValidatedDevice())
 | 
							State_.LastContact = LastContact_ = Utils::Now();
 | 
				
			||||||
			return;
 | 
							if (AP_WS_Server()->Running() && (DeviceValidated_ || ValidatedDevice())) {
 | 
				
			||||||
 | 
								try {
 | 
				
			||||||
		try {
 | 
									return ProcessIncomingFrame();
 | 
				
			||||||
			return ProcessIncomingFrame();
 | 
								} catch (const Poco::Exception &E) {
 | 
				
			||||||
		} catch (const Poco::Exception &E) {
 | 
									Logger_.log(E);
 | 
				
			||||||
			Logger_.log(E);
 | 
								} catch (const std::exception &E) {
 | 
				
			||||||
			return EndConnection();
 | 
									std::string W = E.what();
 | 
				
			||||||
		} catch (const std::exception &E) {
 | 
									poco_information(
 | 
				
			||||||
			std::string W = E.what();
 | 
										Logger_, fmt::format("std::exception caught: {}. Connection terminated with {}",
 | 
				
			||||||
			poco_information(
 | 
															 W, CId_));
 | 
				
			||||||
				Logger_,
 | 
								} catch (...) {
 | 
				
			||||||
				fmt::format("std::exception caught: {}. Connection terminated with {}", W, CId_));
 | 
									poco_information(
 | 
				
			||||||
			return EndConnection();
 | 
										Logger_, fmt::format("Unknown exception for {}. Connection terminated.", CId_));
 | 
				
			||||||
		} catch (...) {
 | 
								}
 | 
				
			||||||
			poco_information(Logger_,
 | 
					 | 
				
			||||||
							 fmt::format("Unknown exception for {}. Connection terminated.", CId_));
 | 
					 | 
				
			||||||
			return EndConnection();
 | 
					 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
							EndConnection();
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	void AP_WS_Connection::ProcessIncomingFrame() {
 | 
						void AP_WS_Connection::ProcessIncomingFrame() {
 | 
				
			||||||
		Poco::Buffer<char> IncomingFrame(0);
 | 
							Poco::Buffer<char> IncomingFrame(0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							bool	KillConnection=false;
 | 
				
			||||||
		try {
 | 
							try {
 | 
				
			||||||
			int Op, flags;
 | 
								int 	Op, flags;
 | 
				
			||||||
			auto IncomingSize = WS_->receiveFrame(IncomingFrame, flags);
 | 
								auto IncomingSize = WS_->receiveFrame(IncomingFrame, flags);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			Op = flags & Poco::Net::WebSocket::FRAME_OP_BITMASK;
 | 
								Op = flags & Poco::Net::WebSocket::FRAME_OP_BITMASK;
 | 
				
			||||||
@@ -706,83 +624,81 @@ namespace OpenWifi {
 | 
				
			|||||||
			State_.LastContact = Utils::Now();
 | 
								State_.LastContact = Utils::Now();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			switch (Op) {
 | 
								switch (Op) {
 | 
				
			||||||
			case Poco::Net::WebSocket::FRAME_OP_PING: {
 | 
									case Poco::Net::WebSocket::FRAME_OP_PING: {
 | 
				
			||||||
				poco_trace(Logger_, fmt::format("WS-PING({}): received. PONG sent back.", CId_));
 | 
										poco_trace(Logger_, fmt::format("WS-PING({}): received. PONG sent back.", CId_));
 | 
				
			||||||
				WS_->sendFrame("", 0,
 | 
										WS_->sendFrame("", 0,
 | 
				
			||||||
							   (int)Poco::Net::WebSocket::FRAME_OP_PONG |
 | 
													   (int)Poco::Net::WebSocket::FRAME_OP_PONG |
 | 
				
			||||||
								   (int)Poco::Net::WebSocket::FRAME_FLAG_FIN);
 | 
														   (int)Poco::Net::WebSocket::FRAME_FLAG_FIN);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				if (KafkaManager()->Enabled()) {
 | 
										if (KafkaManager()->Enabled()) {
 | 
				
			||||||
					Poco::JSON::Object PingObject;
 | 
											Poco::JSON::Object PingObject;
 | 
				
			||||||
					Poco::JSON::Object PingDetails;
 | 
											Poco::JSON::Object PingDetails;
 | 
				
			||||||
					PingDetails.set(uCentralProtocol::FIRMWARE, State_.Firmware);
 | 
											PingDetails.set(uCentralProtocol::FIRMWARE, State_.Firmware);
 | 
				
			||||||
					PingDetails.set(uCentralProtocol::SERIALNUMBER, SerialNumber_);
 | 
											PingDetails.set(uCentralProtocol::SERIALNUMBER, SerialNumber_);
 | 
				
			||||||
					PingDetails.set(uCentralProtocol::COMPATIBLE, Compatible_);
 | 
											PingDetails.set(uCentralProtocol::COMPATIBLE, Compatible_);
 | 
				
			||||||
					PingDetails.set(uCentralProtocol::CONNECTIONIP, CId_);
 | 
											PingDetails.set(uCentralProtocol::CONNECTIONIP, CId_);
 | 
				
			||||||
					PingDetails.set(uCentralProtocol::TIMESTAMP, Utils::Now());
 | 
											PingDetails.set(uCentralProtocol::TIMESTAMP, Utils::Now());
 | 
				
			||||||
					PingDetails.set(uCentralProtocol::UUID, uuid_);
 | 
											PingDetails.set(uCentralProtocol::UUID, uuid_);
 | 
				
			||||||
					PingDetails.set("locale", State_.locale);
 | 
											PingDetails.set("locale", State_.locale);
 | 
				
			||||||
					PingObject.set(uCentralProtocol::PING, PingDetails);
 | 
											PingObject.set(uCentralProtocol::PING, PingDetails);
 | 
				
			||||||
					poco_trace(Logger_,fmt::format("Sending PING for {}", SerialNumber_));
 | 
											poco_trace(Logger_,fmt::format("Sending PING for {}", SerialNumber_));
 | 
				
			||||||
					KafkaManager()->PostMessage(KafkaTopics::CONNECTION, SerialNumber_,PingObject);
 | 
											KafkaManager()->PostMessage(KafkaTopics::CONNECTION, SerialNumber_,PingObject);
 | 
				
			||||||
				}
 | 
										}
 | 
				
			||||||
				return;
 | 
									} break;
 | 
				
			||||||
			} break;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
			case Poco::Net::WebSocket::FRAME_OP_PONG: {
 | 
									case Poco::Net::WebSocket::FRAME_OP_PONG: {
 | 
				
			||||||
				poco_trace(Logger_, fmt::format("PONG({}): received and ignored.", CId_));
 | 
										poco_trace(Logger_, fmt::format("PONG({}): received and ignored.", CId_));
 | 
				
			||||||
				return;
 | 
									} break;
 | 
				
			||||||
			} break;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
			case Poco::Net::WebSocket::FRAME_OP_TEXT: {
 | 
									case Poco::Net::WebSocket::FRAME_OP_TEXT: {
 | 
				
			||||||
				poco_trace(Logger_,
 | 
										poco_trace(Logger_,
 | 
				
			||||||
						   fmt::format("FRAME({}): Frame received (length={}, flags={}). Msg={}",
 | 
												   fmt::format("FRAME({}): Frame received (length={}, flags={}). Msg={}",
 | 
				
			||||||
									   CId_, IncomingSize, flags, IncomingFrame.begin()));
 | 
															   CId_, IncomingSize, flags, IncomingFrame.begin()));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				Poco::JSON::Parser parser;
 | 
										Poco::JSON::Parser parser;
 | 
				
			||||||
				auto ParsedMessage = parser.parse(IncomingFrame.begin());
 | 
										auto ParsedMessage = parser.parse(IncomingFrame.begin());
 | 
				
			||||||
				auto IncomingJSON = ParsedMessage.extract<Poco::JSON::Object::Ptr>();
 | 
										auto IncomingJSON = ParsedMessage.extract<Poco::JSON::Object::Ptr>();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				if (IncomingJSON->has(uCentralProtocol::JSONRPC)) {
 | 
										if (IncomingJSON->has(uCentralProtocol::JSONRPC)) {
 | 
				
			||||||
					if (IncomingJSON->has(uCentralProtocol::METHOD) &&
 | 
											if (IncomingJSON->has(uCentralProtocol::METHOD) &&
 | 
				
			||||||
						IncomingJSON->has(uCentralProtocol::PARAMS)) {
 | 
												IncomingJSON->has(uCentralProtocol::PARAMS)) {
 | 
				
			||||||
						ProcessJSONRPCEvent(IncomingJSON);
 | 
												ProcessJSONRPCEvent(IncomingJSON);
 | 
				
			||||||
					} else if (IncomingJSON->has(uCentralProtocol::RESULT) &&
 | 
											} else if (IncomingJSON->has(uCentralProtocol::RESULT) &&
 | 
				
			||||||
							   IncomingJSON->has(uCentralProtocol::ID)) {
 | 
													   IncomingJSON->has(uCentralProtocol::ID)) {
 | 
				
			||||||
						poco_trace(Logger_, fmt::format("RPC-RESULT({}): payload: {}", CId_,
 | 
												poco_trace(Logger_, fmt::format("RPC-RESULT({}): payload: {}", CId_,
 | 
				
			||||||
														IncomingFrame.begin()));
 | 
																				IncomingFrame.begin()));
 | 
				
			||||||
						ProcessJSONRPCResult(IncomingJSON);
 | 
												ProcessJSONRPCResult(IncomingJSON);
 | 
				
			||||||
 | 
											} else {
 | 
				
			||||||
 | 
												poco_warning(
 | 
				
			||||||
 | 
													Logger_,
 | 
				
			||||||
 | 
													fmt::format("INVALID-PAYLOAD({}): Payload is not JSON-RPC 2.0: {}",
 | 
				
			||||||
 | 
																CId_, IncomingFrame.begin()));
 | 
				
			||||||
 | 
											}
 | 
				
			||||||
 | 
										} else if (IncomingJSON->has(uCentralProtocol::RADIUS)) {
 | 
				
			||||||
 | 
											ProcessIncomingRadiusData(IncomingJSON);
 | 
				
			||||||
					} else {
 | 
										} else {
 | 
				
			||||||
 | 
											std::ostringstream iS;
 | 
				
			||||||
 | 
											IncomingJSON->stringify(iS);
 | 
				
			||||||
						poco_warning(
 | 
											poco_warning(
 | 
				
			||||||
							Logger_,
 | 
												Logger_,
 | 
				
			||||||
							fmt::format("INVALID-PAYLOAD({}): Payload is not JSON-RPC 2.0: {}",
 | 
												fmt::format("FRAME({}): illegal transaction header, missing 'jsonrpc': {}",
 | 
				
			||||||
										CId_, IncomingFrame.begin()));
 | 
															CId_, iS.str()));
 | 
				
			||||||
 | 
											Errors_++;
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
				} else if (IncomingJSON->has(uCentralProtocol::RADIUS)) {
 | 
									} break;
 | 
				
			||||||
					ProcessIncomingRadiusData(IncomingJSON);
 | 
					
 | 
				
			||||||
				} else {
 | 
									case Poco::Net::WebSocket::FRAME_OP_CLOSE: {
 | 
				
			||||||
					std::ostringstream iS;
 | 
										poco_information(Logger_,
 | 
				
			||||||
					IncomingJSON->stringify(iS);
 | 
														 fmt::format("CLOSE({}): Device is closing its connection.", CId_));
 | 
				
			||||||
					std::cout << iS.str() << std::endl;
 | 
										KillConnection=true;
 | 
				
			||||||
					poco_warning(
 | 
									} break;
 | 
				
			||||||
						Logger_,
 | 
					
 | 
				
			||||||
						fmt::format("FRAME({}): illegal transaction header, missing 'jsonrpc'",
 | 
									default: {
 | 
				
			||||||
									CId_));
 | 
										poco_warning(Logger_, fmt::format("UNKNOWN({}): unknown WS Frame operation: {}",
 | 
				
			||||||
 | 
																		  CId_, std::to_string(Op)));
 | 
				
			||||||
					Errors_++;
 | 
										Errors_++;
 | 
				
			||||||
 | 
										return;
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
				return;
 | 
					 | 
				
			||||||
			} break;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			case Poco::Net::WebSocket::FRAME_OP_CLOSE: {
 | 
					 | 
				
			||||||
				poco_information(Logger_,
 | 
					 | 
				
			||||||
								 fmt::format("CLOSE({}): Device is closing its connection.", CId_));
 | 
					 | 
				
			||||||
				return EndConnection();
 | 
					 | 
				
			||||||
			} break;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			default: {
 | 
					 | 
				
			||||||
				poco_warning(Logger_, fmt::format("UNKNOWN({}): unknown WS Frame operation: {}",
 | 
					 | 
				
			||||||
												  CId_, std::to_string(Op)));
 | 
					 | 
				
			||||||
			} break;
 | 
					 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		} catch (const Poco::Net::ConnectionResetException &E) {
 | 
							} catch (const Poco::Net::ConnectionResetException &E) {
 | 
				
			||||||
			poco_warning(Logger_,
 | 
								poco_warning(Logger_,
 | 
				
			||||||
@@ -790,21 +706,21 @@ namespace OpenWifi {
 | 
				
			|||||||
									 CId_, E.displayText(),
 | 
														 CId_, E.displayText(),
 | 
				
			||||||
									 IncomingFrame.begin() == nullptr ? "" : IncomingFrame.begin(),
 | 
														 IncomingFrame.begin() == nullptr ? "" : IncomingFrame.begin(),
 | 
				
			||||||
									 State_.sessionId));
 | 
														 State_.sessionId));
 | 
				
			||||||
			return EndConnection();
 | 
								KillConnection=true;
 | 
				
			||||||
		} catch (const Poco::JSON::JSONException &E) {
 | 
							} catch (const Poco::JSON::JSONException &E) {
 | 
				
			||||||
			poco_warning(Logger_,
 | 
								poco_warning(Logger_,
 | 
				
			||||||
						 fmt::format("JSONException({}): Text:{} Payload:{} Session:{}", CId_,
 | 
											 fmt::format("JSONException({}): Text:{} Payload:{} Session:{}", CId_,
 | 
				
			||||||
									 E.displayText(),
 | 
														 E.displayText(),
 | 
				
			||||||
									 IncomingFrame.begin() == nullptr ? "" : IncomingFrame.begin(),
 | 
														 IncomingFrame.begin() == nullptr ? "" : IncomingFrame.begin(),
 | 
				
			||||||
									 State_.sessionId));
 | 
														 State_.sessionId));
 | 
				
			||||||
			return EndConnection();
 | 
								KillConnection=true;
 | 
				
			||||||
		} catch (const Poco::Net::WebSocketException &E) {
 | 
							} catch (const Poco::Net::WebSocketException &E) {
 | 
				
			||||||
			poco_warning(Logger_,
 | 
								poco_warning(Logger_,
 | 
				
			||||||
						 fmt::format("WebSocketException({}): Text:{} Payload:{} Session:{}", CId_,
 | 
											 fmt::format("WebSocketException({}): Text:{} Payload:{} Session:{}", CId_,
 | 
				
			||||||
									 E.displayText(),
 | 
														 E.displayText(),
 | 
				
			||||||
									 IncomingFrame.begin() == nullptr ? "" : IncomingFrame.begin(),
 | 
														 IncomingFrame.begin() == nullptr ? "" : IncomingFrame.begin(),
 | 
				
			||||||
									 State_.sessionId));
 | 
														 State_.sessionId));
 | 
				
			||||||
			return EndConnection();
 | 
								KillConnection=true;
 | 
				
			||||||
		} catch (const Poco::Net::SSLConnectionUnexpectedlyClosedException &E) {
 | 
							} catch (const Poco::Net::SSLConnectionUnexpectedlyClosedException &E) {
 | 
				
			||||||
			poco_warning(
 | 
								poco_warning(
 | 
				
			||||||
				Logger_,
 | 
									Logger_,
 | 
				
			||||||
@@ -813,54 +729,54 @@ namespace OpenWifi {
 | 
				
			|||||||
					CId_, E.displayText(),
 | 
										CId_, E.displayText(),
 | 
				
			||||||
					IncomingFrame.begin() == nullptr ? "" : IncomingFrame.begin(),
 | 
										IncomingFrame.begin() == nullptr ? "" : IncomingFrame.begin(),
 | 
				
			||||||
					State_.sessionId));
 | 
										State_.sessionId));
 | 
				
			||||||
			return EndConnection();
 | 
								KillConnection=true;
 | 
				
			||||||
		} catch (const Poco::Net::SSLException &E) {
 | 
							} catch (const Poco::Net::SSLException &E) {
 | 
				
			||||||
			poco_warning(Logger_,
 | 
								poco_warning(Logger_,
 | 
				
			||||||
						 fmt::format("SSLException({}): Text:{} Payload:{} Session:{}", CId_,
 | 
											 fmt::format("SSLException({}): Text:{} Payload:{} Session:{}", CId_,
 | 
				
			||||||
									 E.displayText(),
 | 
														 E.displayText(),
 | 
				
			||||||
									 IncomingFrame.begin() == nullptr ? "" : IncomingFrame.begin(),
 | 
														 IncomingFrame.begin() == nullptr ? "" : IncomingFrame.begin(),
 | 
				
			||||||
									 State_.sessionId));
 | 
														 State_.sessionId));
 | 
				
			||||||
			return EndConnection();
 | 
								KillConnection=true;
 | 
				
			||||||
		} catch (const Poco::Net::NetException &E) {
 | 
							} catch (const Poco::Net::NetException &E) {
 | 
				
			||||||
			poco_warning(Logger_,
 | 
								poco_warning(Logger_,
 | 
				
			||||||
						 fmt::format("NetException({}): Text:{} Payload:{} Session:{}", CId_,
 | 
											 fmt::format("NetException({}): Text:{} Payload:{} Session:{}", CId_,
 | 
				
			||||||
									 E.displayText(),
 | 
														 E.displayText(),
 | 
				
			||||||
									 IncomingFrame.begin() == nullptr ? "" : IncomingFrame.begin(),
 | 
														 IncomingFrame.begin() == nullptr ? "" : IncomingFrame.begin(),
 | 
				
			||||||
									 State_.sessionId));
 | 
														 State_.sessionId));
 | 
				
			||||||
			return EndConnection();
 | 
								KillConnection=true;
 | 
				
			||||||
		} catch (const Poco::IOException &E) {
 | 
							} catch (const Poco::IOException &E) {
 | 
				
			||||||
			poco_warning(Logger_,
 | 
								poco_warning(Logger_,
 | 
				
			||||||
						 fmt::format("IOException({}): Text:{} Payload:{} Session:{}", CId_,
 | 
											 fmt::format("IOException({}): Text:{} Payload:{} Session:{}", CId_,
 | 
				
			||||||
									 E.displayText(),
 | 
														 E.displayText(),
 | 
				
			||||||
									 IncomingFrame.begin() == nullptr ? "" : IncomingFrame.begin(),
 | 
														 IncomingFrame.begin() == nullptr ? "" : IncomingFrame.begin(),
 | 
				
			||||||
									 State_.sessionId));
 | 
														 State_.sessionId));
 | 
				
			||||||
			return EndConnection();
 | 
								KillConnection=true;
 | 
				
			||||||
		} catch (const Poco::Exception &E) {
 | 
							} catch (const Poco::Exception &E) {
 | 
				
			||||||
			poco_warning(Logger_,
 | 
								poco_warning(Logger_,
 | 
				
			||||||
						 fmt::format("Exception({}): Text:{} Payload:{} Session:{}", CId_,
 | 
											 fmt::format("Exception({}): Text:{} Payload:{} Session:{}", CId_,
 | 
				
			||||||
									 E.displayText(),
 | 
														 E.displayText(),
 | 
				
			||||||
									 IncomingFrame.begin() == nullptr ? "" : IncomingFrame.begin(),
 | 
														 IncomingFrame.begin() == nullptr ? "" : IncomingFrame.begin(),
 | 
				
			||||||
									 State_.sessionId));
 | 
														 State_.sessionId));
 | 
				
			||||||
			return EndConnection();
 | 
								KillConnection=true;
 | 
				
			||||||
		} catch (const std::exception &E) {
 | 
							} catch (const std::exception &E) {
 | 
				
			||||||
			poco_warning(Logger_,
 | 
								poco_warning(Logger_,
 | 
				
			||||||
						 fmt::format("std::exception({}): Text:{} Payload:{} Session:{}", CId_,
 | 
											 fmt::format("std::exception({}): Text:{} Payload:{} Session:{}", CId_,
 | 
				
			||||||
									 E.what(),
 | 
														 E.what(),
 | 
				
			||||||
									 IncomingFrame.begin() == nullptr ? "" : IncomingFrame.begin(),
 | 
														 IncomingFrame.begin() == nullptr ? "" : IncomingFrame.begin(),
 | 
				
			||||||
									 State_.sessionId));
 | 
														 State_.sessionId));
 | 
				
			||||||
			return EndConnection();
 | 
								KillConnection=true;
 | 
				
			||||||
		} catch (...) {
 | 
							} catch (...) {
 | 
				
			||||||
			poco_error(Logger_, fmt::format("UnknownException({}): Device must be disconnected. "
 | 
								poco_error(Logger_, fmt::format("UnknownException({}): Device must be disconnected. "
 | 
				
			||||||
											"Unknown exception.  Session:{}",
 | 
																"Unknown exception.  Session:{}",
 | 
				
			||||||
											CId_, State_.sessionId));
 | 
																CId_, State_.sessionId));
 | 
				
			||||||
			return EndConnection();
 | 
								KillConnection=true;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (Errors_ < 10)
 | 
							if (!KillConnection && Errors_ < 10)
 | 
				
			||||||
			return;
 | 
								return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		poco_warning(Logger_, fmt::format("DISCONNECTING({}): Too many errors", CId_));
 | 
							poco_warning(Logger_, fmt::format("DISCONNECTING({}): ConnectionException: {} Errors: {}", CId_, KillConnection, Errors_ ));
 | 
				
			||||||
		return EndConnection();
 | 
							EndConnection();
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	bool AP_WS_Connection::Send(const std::string &Payload) {
 | 
						bool AP_WS_Connection::Send(const std::string &Payload) {
 | 
				
			||||||
@@ -972,4 +888,36 @@ namespace OpenWifi {
 | 
				
			|||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						void AP_WS_Connection::SetLastStats(const std::string &LastStats) {
 | 
				
			||||||
 | 
							RawLastStats_ = LastStats;
 | 
				
			||||||
 | 
							try {
 | 
				
			||||||
 | 
								Poco::JSON::Parser P;
 | 
				
			||||||
 | 
								auto Stats = P.parse(LastStats).extract<Poco::JSON::Object::Ptr>();
 | 
				
			||||||
 | 
								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) {
 | 
				
			||||||
 | 
									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) {
 | 
				
			||||||
 | 
										State_.load = Load->get(1);
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								if (Unit->isArray("temperature")) {
 | 
				
			||||||
 | 
									Poco::JSON::Array::Ptr Temperature = Unit->getArray("temperature");
 | 
				
			||||||
 | 
									if (Temperature->size() > 1) {
 | 
				
			||||||
 | 
										State_.temperature = Temperature->get(0);
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							} catch (const Poco::Exception &E) {
 | 
				
			||||||
 | 
								poco_error(Logger_, "Failed to parse last stats: " + E.displayText());
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
} // namespace OpenWifi
 | 
					} // namespace OpenWifi
 | 
				
			||||||
@@ -14,8 +14,10 @@
 | 
				
			|||||||
#include "Poco/Net/SocketReactor.h"
 | 
					#include "Poco/Net/SocketReactor.h"
 | 
				
			||||||
#include "Poco/Net/StreamSocket.h"
 | 
					#include "Poco/Net/StreamSocket.h"
 | 
				
			||||||
#include "Poco/Net/WebSocket.h"
 | 
					#include "Poco/Net/WebSocket.h"
 | 
				
			||||||
 | 
					#include <Poco/Data/Session.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "RESTObjects/RESTAPI_GWobjects.h"
 | 
					#include "RESTObjects/RESTAPI_GWobjects.h"
 | 
				
			||||||
 | 
					#include <AP_WS_Reactor_Pool.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace OpenWifi {
 | 
					namespace OpenWifi {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -25,16 +27,17 @@ namespace OpenWifi {
 | 
				
			|||||||
	  public:
 | 
						  public:
 | 
				
			||||||
		explicit AP_WS_Connection(Poco::Net::HTTPServerRequest &request,
 | 
							explicit AP_WS_Connection(Poco::Net::HTTPServerRequest &request,
 | 
				
			||||||
								  Poco::Net::HTTPServerResponse &response, uint64_t connection_id,
 | 
													  Poco::Net::HTTPServerResponse &response, uint64_t connection_id,
 | 
				
			||||||
								  Poco::Logger &L, Poco::Net::SocketReactor &R);
 | 
													  Poco::Logger &L, std::pair<std::shared_ptr<Poco::Net::SocketReactor>, std::shared_ptr<LockedDbSession>> R);
 | 
				
			||||||
		~AP_WS_Connection();
 | 
							~AP_WS_Connection();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		void EndConnection(bool DeleteSession=true);
 | 
							void EndConnection();
 | 
				
			||||||
		void ProcessJSONRPCEvent(Poco::JSON::Object::Ptr &Doc);
 | 
							void ProcessJSONRPCEvent(Poco::JSON::Object::Ptr &Doc);
 | 
				
			||||||
		void ProcessJSONRPCResult(Poco::JSON::Object::Ptr Doc);
 | 
							void ProcessJSONRPCResult(Poco::JSON::Object::Ptr Doc);
 | 
				
			||||||
		void ProcessIncomingFrame();
 | 
							void ProcessIncomingFrame();
 | 
				
			||||||
		void ProcessIncomingRadiusData(const Poco::JSON::Object::Ptr &Doc);
 | 
							void ProcessIncomingRadiusData(const Poco::JSON::Object::Ptr &Doc);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		[[nodiscard]] bool Send(const std::string &Payload);
 | 
							[[nodiscard]] bool Send(const std::string &Payload);
 | 
				
			||||||
 | 
							[[nodiscard]] inline bool MustBeSecureRTTY() const { return RTTYMustBeSecure_; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		bool SendRadiusAuthenticationData(const unsigned char *buffer, std::size_t size);
 | 
							bool SendRadiusAuthenticationData(const unsigned char *buffer, std::size_t size);
 | 
				
			||||||
		bool SendRadiusAccountingData(const unsigned char *buffer, std::size_t size);
 | 
							bool SendRadiusAccountingData(const unsigned char *buffer, std::size_t size);
 | 
				
			||||||
@@ -43,10 +46,7 @@ namespace OpenWifi {
 | 
				
			|||||||
		void OnSocketReadable(const Poco::AutoPtr<Poco::Net::ReadableNotification> &pNf);
 | 
							void OnSocketReadable(const Poco::AutoPtr<Poco::Net::ReadableNotification> &pNf);
 | 
				
			||||||
		void OnSocketShutdown(const Poco::AutoPtr<Poco::Net::ShutdownNotification> &pNf);
 | 
							void OnSocketShutdown(const Poco::AutoPtr<Poco::Net::ShutdownNotification> &pNf);
 | 
				
			||||||
		void OnSocketError(const Poco::AutoPtr<Poco::Net::ErrorNotification> &pNf);
 | 
							void OnSocketError(const Poco::AutoPtr<Poco::Net::ErrorNotification> &pNf);
 | 
				
			||||||
		bool LookForUpgrade(uint64_t UUID, uint64_t &UpgradedUUID);
 | 
							bool LookForUpgrade(Poco::Data::Session &Session, uint64_t UUID, uint64_t &UpgradedUUID);
 | 
				
			||||||
		static bool ExtractBase64CompressedData(const std::string &CompressedData,
 | 
					 | 
				
			||||||
												std::string &UnCompressedData,
 | 
					 | 
				
			||||||
												uint64_t compress_sz);
 | 
					 | 
				
			||||||
		void LogException(const Poco::Exception &E);
 | 
							void LogException(const Poco::Exception &E);
 | 
				
			||||||
		inline Poco::Logger &Logger() { return Logger_; }
 | 
							inline Poco::Logger &Logger() { return Logger_; }
 | 
				
			||||||
		bool SetWebSocketTelemetryReporting(uint64_t RPCID, uint64_t interval,
 | 
							bool SetWebSocketTelemetryReporting(uint64_t RPCID, uint64_t interval,
 | 
				
			||||||
@@ -59,81 +59,33 @@ namespace OpenWifi {
 | 
				
			|||||||
		bool StopKafkaTelemetry(uint64_t RPCID);
 | 
							bool StopKafkaTelemetry(uint64_t RPCID);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		inline void GetLastStats(std::string &LastStats) {
 | 
							inline void GetLastStats(std::string &LastStats) {
 | 
				
			||||||
			std::lock_guard G(ConnectionMutex_);
 | 
								if(!Dead_) {
 | 
				
			||||||
			LastStats = RawLastStats_;
 | 
									std::lock_guard G(ConnectionMutex_);
 | 
				
			||||||
		}
 | 
									LastStats = RawLastStats_;
 | 
				
			||||||
 | 
					 | 
				
			||||||
		inline void SetLastStats(const std::string &LastStats) {
 | 
					 | 
				
			||||||
			std::lock_guard G(ConnectionMutex_);
 | 
					 | 
				
			||||||
			RawLastStats_ = LastStats;
 | 
					 | 
				
			||||||
			try {
 | 
					 | 
				
			||||||
				Poco::JSON::Parser P;
 | 
					 | 
				
			||||||
				auto Stats = P.parse(LastStats).extract<Poco::JSON::Object::Ptr>();
 | 
					 | 
				
			||||||
				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_ =
 | 
					 | 
				
			||||||
						(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);
 | 
					 | 
				
			||||||
					}
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
				if(Unit->isArray("temperature")) {
 | 
					 | 
				
			||||||
					Poco::JSON::Array::Ptr Temperature = Unit->getArray("temperature");
 | 
					 | 
				
			||||||
					if(Temperature->size()>1) {
 | 
					 | 
				
			||||||
						temperature_ = Temperature->get(0);
 | 
					 | 
				
			||||||
					}
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
			} catch (...) {
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		inline void SetLastHealthCheck(const GWObjects::HealthCheck &H) {
 | 
					 | 
				
			||||||
			std::lock_guard G(ConnectionMutex_);
 | 
					 | 
				
			||||||
			RawLastHealthcheck_ = H;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		inline void GetLastHealthCheck(GWObjects::HealthCheck &H) {
 | 
							inline void GetLastHealthCheck(GWObjects::HealthCheck &H) {
 | 
				
			||||||
			std::lock_guard G(ConnectionMutex_);
 | 
								if(!Dead_) {
 | 
				
			||||||
			H = RawLastHealthcheck_;
 | 
									std::lock_guard G(ConnectionMutex_);
 | 
				
			||||||
 | 
									H = RawLastHealthcheck_;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		inline void GetState(GWObjects::ConnectionState &State) const {
 | 
							inline void GetState(GWObjects::ConnectionState &State) {
 | 
				
			||||||
			std::lock_guard G(ConnectionMutex_);
 | 
								if(!Dead_) {
 | 
				
			||||||
			State = State_;
 | 
									std::lock_guard G(ConnectionMutex_);
 | 
				
			||||||
 | 
									State = State_;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		inline bool HasGPS() { return hasGPS; }
 | 
							inline GWObjects::DeviceRestrictions GetRestrictions() {
 | 
				
			||||||
 | 
					 | 
				
			||||||
		inline void GetRestrictions(GWObjects::DeviceRestrictions &R) const {
 | 
					 | 
				
			||||||
			std::lock_guard G(ConnectionMutex_);
 | 
								std::lock_guard G(ConnectionMutex_);
 | 
				
			||||||
			R = Restrictions_;
 | 
								return Restrictions_;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		void Process_connect(Poco::JSON::Object::Ptr ParamsObj, const std::string &Serial);
 | 
							[[nodiscard]] inline bool HasGPS() const { return hasGPS_; }
 | 
				
			||||||
		void Process_state(Poco::JSON::Object::Ptr ParamsObj);
 | 
							[[nodiscard]] bool ValidatedDevice();
 | 
				
			||||||
		void Process_healthcheck(Poco::JSON::Object::Ptr ParamsObj);
 | 
					 | 
				
			||||||
		void Process_log(Poco::JSON::Object::Ptr ParamsObj);
 | 
					 | 
				
			||||||
		void Process_crashlog(Poco::JSON::Object::Ptr ParamsObj);
 | 
					 | 
				
			||||||
		void Process_ping(Poco::JSON::Object::Ptr ParamsObj);
 | 
					 | 
				
			||||||
		void Process_cfgpending(Poco::JSON::Object::Ptr ParamsObj);
 | 
					 | 
				
			||||||
		void Process_recovery(Poco::JSON::Object::Ptr ParamsObj);
 | 
					 | 
				
			||||||
		void Process_deviceupdate(Poco::JSON::Object::Ptr ParamsObj, std::string &Serial);
 | 
					 | 
				
			||||||
		void Process_telemetry(Poco::JSON::Object::Ptr ParamsObj);
 | 
					 | 
				
			||||||
		void Process_venuebroadcast(Poco::JSON::Object::Ptr ParamsObj);
 | 
					 | 
				
			||||||
		void Process_event(Poco::JSON::Object::Ptr ParamsObj);
 | 
					 | 
				
			||||||
		void Process_wifiscan(Poco::JSON::Object::Ptr ParamsObj);
 | 
					 | 
				
			||||||
		void Process_alarm(Poco::JSON::Object::Ptr ParamsObj);
 | 
					 | 
				
			||||||
		void Process_rebootLog(Poco::JSON::Object::Ptr ParamsObj);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		bool ValidatedDevice();
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		inline bool GetTelemetryParameters(bool &Reporting, uint64_t &Interval,
 | 
							inline bool GetTelemetryParameters(bool &Reporting, uint64_t &Interval,
 | 
				
			||||||
										   uint64_t &WebSocketTimer, uint64_t &KafkaTimer,
 | 
															   uint64_t &WebSocketTimer, uint64_t &KafkaTimer,
 | 
				
			||||||
@@ -153,18 +105,14 @@ namespace OpenWifi {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
		friend class AP_WS_Server;
 | 
							friend class AP_WS_Server;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		inline GWObjects::DeviceRestrictions Restrictions() const {
 | 
							void Start();
 | 
				
			||||||
			std::lock_guard G(ConnectionMutex_);
 | 
					 | 
				
			||||||
			return Restrictions_;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		inline bool MustBeSecureRtty() const { return RttyMustBeSecure_; }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	  private:
 | 
						  private:
 | 
				
			||||||
		mutable std::mutex ConnectionMutex_;
 | 
							mutable std::recursive_mutex ConnectionMutex_;
 | 
				
			||||||
		std::mutex TelemetryMutex_;
 | 
							std::mutex TelemetryMutex_;
 | 
				
			||||||
		Poco::Logger &Logger_;
 | 
							Poco::Logger &Logger_;
 | 
				
			||||||
		Poco::Net::SocketReactor &Reactor_;
 | 
							std::shared_ptr<Poco::Net::SocketReactor> 	Reactor_;
 | 
				
			||||||
 | 
							std::shared_ptr<LockedDbSession> 	DbSession_;
 | 
				
			||||||
		std::unique_ptr<Poco::Net::WebSocket> WS_;
 | 
							std::unique_ptr<Poco::Net::WebSocket> WS_;
 | 
				
			||||||
		std::string SerialNumber_;
 | 
							std::string SerialNumber_;
 | 
				
			||||||
		uint64_t SerialNumberInt_ = 0;
 | 
							uint64_t SerialNumberInt_ = 0;
 | 
				
			||||||
@@ -175,34 +123,56 @@ namespace OpenWifi {
 | 
				
			|||||||
		uint64_t Errors_ = 0;
 | 
							uint64_t Errors_ = 0;
 | 
				
			||||||
		Poco::Net::IPAddress PeerAddress_;
 | 
							Poco::Net::IPAddress PeerAddress_;
 | 
				
			||||||
		volatile bool TelemetryReporting_ = false;
 | 
							volatile bool TelemetryReporting_ = false;
 | 
				
			||||||
		volatile uint64_t TelemetryWebSocketRefCount_ = 0;
 | 
							std::atomic_uint64_t TelemetryWebSocketRefCount_ = 0;
 | 
				
			||||||
		volatile uint64_t TelemetryKafkaRefCount_ = 0;
 | 
							std::atomic_uint64_t TelemetryKafkaRefCount_ = 0;
 | 
				
			||||||
		volatile uint64_t TelemetryWebSocketTimer_ = 0;
 | 
							std::atomic_uint64_t TelemetryWebSocketTimer_ = 0;
 | 
				
			||||||
		volatile uint64_t TelemetryKafkaTimer_ = 0;
 | 
							std::atomic_uint64_t TelemetryKafkaTimer_ = 0;
 | 
				
			||||||
		volatile uint64_t TelemetryInterval_ = 0;
 | 
							std::atomic_uint64_t TelemetryInterval_ = 0;
 | 
				
			||||||
		volatile uint64_t TelemetryWebSocketPackets_ = 0;
 | 
							std::atomic_uint64_t TelemetryWebSocketPackets_ = 0;
 | 
				
			||||||
		volatile uint64_t TelemetryKafkaPackets_ = 0;
 | 
							std::atomic_uint64_t TelemetryKafkaPackets_ = 0;
 | 
				
			||||||
		GWObjects::ConnectionState State_;
 | 
							GWObjects::ConnectionState State_;
 | 
				
			||||||
		std::string RawLastStats_;
 | 
							Utils::CompressedString RawLastStats_;
 | 
				
			||||||
		GWObjects::HealthCheck RawLastHealthcheck_;
 | 
							GWObjects::HealthCheck RawLastHealthcheck_;
 | 
				
			||||||
		std::chrono::time_point<std::chrono::high_resolution_clock> ConnectionStart_ =
 | 
							std::chrono::time_point<std::chrono::high_resolution_clock> ConnectionStart_ =
 | 
				
			||||||
			std::chrono::high_resolution_clock::now();
 | 
								std::chrono::high_resolution_clock::now();
 | 
				
			||||||
		std::chrono::duration<double, std::milli> ConnectionCompletionTime_{0.0};
 | 
							std::chrono::duration<double, std::milli> ConnectionCompletionTime_{0.0};
 | 
				
			||||||
		std::atomic_flag Dead_ = false;
 | 
							std::atomic<bool> 	Dead_ = false;
 | 
				
			||||||
		std::atomic_bool DeviceValidated_ = false;
 | 
							std::atomic_bool DeviceValidated_ = false;
 | 
				
			||||||
		std::atomic_bool Valid_ = false;
 | 
					 | 
				
			||||||
		OpenWifi::GWObjects::DeviceRestrictions Restrictions_;
 | 
							OpenWifi::GWObjects::DeviceRestrictions Restrictions_;
 | 
				
			||||||
		bool 			RttyMustBeSecure_ = false;
 | 
							bool 			RTTYMustBeSecure_ = false;
 | 
				
			||||||
 | 
							bool hasGPS_=false;
 | 
				
			||||||
 | 
							std::double_t 	memory_used_=0.0, cpu_load_ = 0.0, temperature_ = 0.0;
 | 
				
			||||||
 | 
							std::uint64_t 	uuid_=0;
 | 
				
			||||||
 | 
							bool	Simulated_=false;
 | 
				
			||||||
 | 
							std::atomic_uint64_t 	LastContact_=0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		static inline std::atomic_uint64_t ConcurrentStartingDevices_ = 0;
 | 
							static inline std::atomic_uint64_t ConcurrentStartingDevices_ = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		bool StartTelemetry(uint64_t RPCID, const std::vector<std::string> &TelemetryTypes);
 | 
							bool StartTelemetry(uint64_t RPCID, const std::vector<std::string> &TelemetryTypes);
 | 
				
			||||||
		bool StopTelemetry(uint64_t RPCID);
 | 
							bool StopTelemetry(uint64_t RPCID);
 | 
				
			||||||
		void UpdateCounts();
 | 
							void UpdateCounts();
 | 
				
			||||||
		bool hasGPS=false;
 | 
							static void DeviceDisconnectionCleanup(const std::string &SerialNumber, std::uint64_t uuid);
 | 
				
			||||||
		std::double_t 	memory_used_=0.0, cpu_load_ = 0.0, temperature_ = 0.0;
 | 
							void SetLastStats(const std::string &LastStats);
 | 
				
			||||||
		std::uint64_t 	uuid_=0;
 | 
							void Process_connect(Poco::JSON::Object::Ptr ParamsObj, const std::string &Serial);
 | 
				
			||||||
		bool	Simulated_=false;
 | 
							void Process_state(Poco::JSON::Object::Ptr ParamsObj);
 | 
				
			||||||
 | 
							void Process_healthcheck(Poco::JSON::Object::Ptr ParamsObj);
 | 
				
			||||||
 | 
							void Process_log(Poco::JSON::Object::Ptr ParamsObj);
 | 
				
			||||||
 | 
							void Process_crashlog(Poco::JSON::Object::Ptr ParamsObj);
 | 
				
			||||||
 | 
							void Process_ping(Poco::JSON::Object::Ptr ParamsObj);
 | 
				
			||||||
 | 
							void Process_cfgpending(Poco::JSON::Object::Ptr ParamsObj);
 | 
				
			||||||
 | 
							void Process_recovery(Poco::JSON::Object::Ptr ParamsObj);
 | 
				
			||||||
 | 
							void Process_deviceupdate(Poco::JSON::Object::Ptr ParamsObj, std::string &Serial);
 | 
				
			||||||
 | 
							void Process_telemetry(Poco::JSON::Object::Ptr ParamsObj);
 | 
				
			||||||
 | 
							void Process_venuebroadcast(Poco::JSON::Object::Ptr ParamsObj);
 | 
				
			||||||
 | 
							void Process_event(Poco::JSON::Object::Ptr ParamsObj);
 | 
				
			||||||
 | 
							void Process_wifiscan(Poco::JSON::Object::Ptr ParamsObj);
 | 
				
			||||||
 | 
							void Process_alarm(Poco::JSON::Object::Ptr ParamsObj);
 | 
				
			||||||
 | 
							void Process_rebootLog(Poco::JSON::Object::Ptr ParamsObj);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							inline void SetLastHealthCheck(const GWObjects::HealthCheck &H) {
 | 
				
			||||||
 | 
								RawLastHealthcheck_ = H;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
} // namespace OpenWifi
 | 
					} // namespace OpenWifi
 | 
				
			||||||
							
								
								
									
										111
									
								
								src/AP_WS_LookForUpgrade.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										111
									
								
								src/AP_WS_LookForUpgrade.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,111 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					#include <AP_WS_Connection.h>
 | 
				
			||||||
 | 
					#include "ConfigurationCache.h"
 | 
				
			||||||
 | 
					#include "UI_GW_WebSocketNotifications.h"
 | 
				
			||||||
 | 
					#include "CommandManager.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace OpenWifi {
 | 
				
			||||||
 | 
						bool AP_WS_Connection::LookForUpgrade(Poco::Data::Session &Session, const uint64_t UUID, uint64_t &UpgradedUUID) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							//	A UUID of zero means ignore updates for that connection.
 | 
				
			||||||
 | 
							if (UUID == 0)
 | 
				
			||||||
 | 
								return false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							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)) {
 | 
				
			||||||
 | 
								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;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// 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;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -71,9 +71,8 @@ namespace OpenWifi {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
			CommandManager()->ClearQueue(SerialNumberInt_);
 | 
								CommandManager()->ClearQueue(SerialNumberInt_);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			AP_WS_Server()->SetSessionDetails(State_.sessionId, SerialNumberInt_);
 | 
								AP_WS_Server()->StartSession(State_.sessionId, SerialNumberInt_);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			std::lock_guard Lock(ConnectionMutex_);
 | 
					 | 
				
			||||||
			Config::Capabilities Caps(Capabilities);
 | 
								Config::Capabilities Caps(Capabilities);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			Compatible_ = Caps.Compatible();
 | 
								Compatible_ = Caps.Compatible();
 | 
				
			||||||
@@ -84,6 +83,8 @@ namespace OpenWifi {
 | 
				
			|||||||
			State_.Address = Utils::FormatIPv6(WS_->peerAddress().toString());
 | 
								State_.Address = Utils::FormatIPv6(WS_->peerAddress().toString());
 | 
				
			||||||
			CId_ = SerialNumber_ + "@" + CId_;
 | 
								CId_ = SerialNumber_ + "@" + CId_;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								auto Platform = Poco::toLower(Caps.Platform());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if(ParamsObj->has("reason")) {
 | 
								if(ParamsObj->has("reason")) {
 | 
				
			||||||
				State_.connectReason = ParamsObj->get("reason").toString();
 | 
									State_.connectReason = ParamsObj->get("reason").toString();
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
@@ -100,36 +101,24 @@ namespace OpenWifi {
 | 
				
			|||||||
				Restrictions_.from_json(RestrictionObject);
 | 
									Restrictions_.from_json(RestrictionObject);
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if (Capabilities->has("developer")) {
 | 
								if (Capabilities->has("developer") && !Capabilities->isNull("developer")) {
 | 
				
			||||||
				Restrictions_.developer = Capabilities->getValue<bool>("developer");
 | 
									Restrictions_.developer = Capabilities->getValue<bool>("developer");
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if(Capabilities->has("secure-rtty")) {
 | 
								if(Capabilities->has("secure-rtty")) {
 | 
				
			||||||
				RttyMustBeSecure_ = Capabilities->getValue<bool>("secure-rtty");
 | 
									RTTYMustBeSecure_ = Capabilities->getValue<bool>("secure-rtty");
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			State_.locale = FindCountryFromIP()->Get(IP);
 | 
								State_.locale = FindCountryFromIP()->Get(IP);
 | 
				
			||||||
			GWObjects::Device DeviceInfo;
 | 
								GWObjects::Device DeviceInfo;
 | 
				
			||||||
			auto DeviceExists = StorageService()->GetDevice(SerialNumber_, DeviceInfo);
 | 
								std::lock_guard DbSessionLock(DbSession_->Mutex());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								auto DeviceExists = StorageService()->GetDevice(DbSession_->Session(), SerialNumber_, DeviceInfo);
 | 
				
			||||||
			if (Daemon()->AutoProvisioning() && !DeviceExists) {
 | 
								if (Daemon()->AutoProvisioning() && !DeviceExists) {
 | 
				
			||||||
				//	check the firmware version. if this is too old, we cannot let that device connect yet, we must
 | 
									//	check the firmware version. if this is too old, we cannot let that device connect yet, we must
 | 
				
			||||||
				//	force a firmware upgrade
 | 
									//	force a firmware upgrade
 | 
				
			||||||
				GWObjects::DefaultFirmware	MinimumFirmware;
 | 
									GWObjects::DefaultFirmware	MinimumFirmware;
 | 
				
			||||||
				if(FirmwareRevisionCache()->DeviceMustUpgrade(Compatible_, Firmware, MinimumFirmware)) {
 | 
									if(FirmwareRevisionCache()->DeviceMustUpgrade(Compatible_, Firmware, MinimumFirmware)) {
 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
					{    "jsonrpc" : "2.0" ,
 | 
					 | 
				
			||||||
						 "method" : "upgrade" ,
 | 
					 | 
				
			||||||
						 "params" : {
 | 
					 | 
				
			||||||
								"serial" : <serial number> ,
 | 
					 | 
				
			||||||
								"when"  : Optional - <UTC time when to upgrade the firmware, 0 mean immediate, this is a suggestion>,
 | 
					 | 
				
			||||||
								"uri"   : <URI to download the firmware>,
 | 
					 | 
				
			||||||
								"FWsignature" : <string representation of the signature for the FW> (optional)
 | 
					 | 
				
			||||||
						 },
 | 
					 | 
				
			||||||
						 "id" : <some number>
 | 
					 | 
				
			||||||
					}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
					Poco::JSON::Object	UpgradeCommand, Params;
 | 
										Poco::JSON::Object	UpgradeCommand, Params;
 | 
				
			||||||
					UpgradeCommand.set(uCentralProtocol::JSONRPC,uCentralProtocol::JSONRPC_VERSION);
 | 
										UpgradeCommand.set(uCentralProtocol::JSONRPC,uCentralProtocol::JSONRPC_VERSION);
 | 
				
			||||||
					UpgradeCommand.set(uCentralProtocol::METHOD,uCentralProtocol::UPGRADE);
 | 
										UpgradeCommand.set(uCentralProtocol::METHOD,uCentralProtocol::UPGRADE);
 | 
				
			||||||
@@ -157,7 +146,7 @@ namespace OpenWifi {
 | 
				
			|||||||
					}
 | 
										}
 | 
				
			||||||
					return;
 | 
										return;
 | 
				
			||||||
				} else {
 | 
									} else {
 | 
				
			||||||
					StorageService()->CreateDefaultDevice(
 | 
										StorageService()->CreateDefaultDevice( DbSession_->Session(),
 | 
				
			||||||
						SerialNumber_, Caps, Firmware, PeerAddress_,
 | 
											SerialNumber_, Caps, Firmware, PeerAddress_,
 | 
				
			||||||
						State_.VerifiedCertificate == GWObjects::SIMULATED);
 | 
											State_.VerifiedCertificate == GWObjects::SIMULATED);
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
@@ -166,7 +155,7 @@ namespace OpenWifi {
 | 
				
			|||||||
				poco_warning(Logger(),fmt::format("Device {} is a {} from {} and cannot be provisioned.",SerialNumber_,Compatible_, CId_));
 | 
									poco_warning(Logger(),fmt::format("Device {} is a {} from {} and cannot be provisioned.",SerialNumber_,Compatible_, CId_));
 | 
				
			||||||
				return EndConnection();
 | 
									return EndConnection();
 | 
				
			||||||
			} else if (DeviceExists) {
 | 
								} else if (DeviceExists) {
 | 
				
			||||||
				StorageService()->UpdateDeviceCapabilities(SerialNumber_, Caps);
 | 
									StorageService()->UpdateDeviceCapabilities(DbSession_->Session(), SerialNumber_, Caps);
 | 
				
			||||||
				int Updated{0};
 | 
									int Updated{0};
 | 
				
			||||||
				if (!Firmware.empty()) {
 | 
									if (!Firmware.empty()) {
 | 
				
			||||||
					if (Firmware != DeviceInfo.Firmware) {
 | 
										if (Firmware != DeviceInfo.Firmware) {
 | 
				
			||||||
@@ -217,8 +206,13 @@ namespace OpenWifi {
 | 
				
			|||||||
					++Updated;
 | 
										++Updated;
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				if (Compatible_ != DeviceInfo.DeviceType) {
 | 
									if (Compatible_ != DeviceInfo.Compatible) {
 | 
				
			||||||
					DeviceInfo.DeviceType = Compatible_;
 | 
										DeviceInfo.Compatible = Compatible_;
 | 
				
			||||||
 | 
										++Updated;
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									if (Platform != DeviceInfo.DeviceType) {
 | 
				
			||||||
 | 
										DeviceInfo.DeviceType = Platform;
 | 
				
			||||||
					++Updated;
 | 
										++Updated;
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -238,12 +232,13 @@ namespace OpenWifi {
 | 
				
			|||||||
				}
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				if (Updated) {
 | 
									if (Updated) {
 | 
				
			||||||
					StorageService()->UpdateDevice(DeviceInfo);
 | 
										StorageService()->UpdateDevice(DbSession_->Session(), DeviceInfo);
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				if(!Simulated_) {
 | 
								if(!Simulated_) {
 | 
				
			||||||
					uint64_t UpgradedUUID = 0;
 | 
									uint64_t UpgradedUUID = 0;
 | 
				
			||||||
					LookForUpgrade(UUID, UpgradedUUID);
 | 
									if (LookForUpgrade(DbSession_->Session(), UUID, UpgradedUUID)) {
 | 
				
			||||||
					State_.UUID = UpgradedUUID;
 | 
										State_.UUID = UpgradedUUID;
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -29,7 +29,7 @@ namespace OpenWifi {
 | 
				
			|||||||
										   .Recorded = Utils::Now(),
 | 
															   .Recorded = Utils::Now(),
 | 
				
			||||||
										   .LogType = 1,
 | 
															   .LogType = 1,
 | 
				
			||||||
										   .UUID = ParamsObj->get(uCentralProtocol::UUID)};
 | 
															   .UUID = ParamsObj->get(uCentralProtocol::UUID)};
 | 
				
			||||||
			StorageService()->AddLog(DeviceLog);
 | 
								StorageService()->AddLog(*DbSession_, DeviceLog);
 | 
				
			||||||
			DeviceLogKafkaEvent	E(DeviceLog);
 | 
								DeviceLogKafkaEvent	E(DeviceLog);
 | 
				
			||||||
		} else {
 | 
							} else {
 | 
				
			||||||
			poco_warning(Logger_, fmt::format("LOG({}): Missing parameters.", CId_));
 | 
								poco_warning(Logger_, fmt::format("LOG({}): Missing parameters.", CId_));
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -21,7 +21,7 @@ namespace OpenWifi {
 | 
				
			|||||||
		if (ParamsObj->has("currentPassword")) {
 | 
							if (ParamsObj->has("currentPassword")) {
 | 
				
			||||||
			auto Password = ParamsObj->get("currentPassword").toString();
 | 
								auto Password = ParamsObj->get("currentPassword").toString();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			StorageService()->SetDevicePassword(Serial, Password);
 | 
								StorageService()->SetDevicePassword(*DbSession_,Serial, Password);
 | 
				
			||||||
			poco_trace(
 | 
								poco_trace(
 | 
				
			||||||
				Logger_,
 | 
									Logger_,
 | 
				
			||||||
				fmt::format("DEVICE-UPDATE({}): Device is updating its login password.", Serial));
 | 
									fmt::format("DEVICE-UPDATE({}): Device is updating its login password.", Serial));
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -3,6 +3,7 @@
 | 
				
			|||||||
//
 | 
					//
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "AP_WS_Connection.h"
 | 
					#include "AP_WS_Connection.h"
 | 
				
			||||||
 | 
					#include "AP_WS_Server.h"
 | 
				
			||||||
#include "StorageService.h"
 | 
					#include "StorageService.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "fmt/format.h"
 | 
					#include "fmt/format.h"
 | 
				
			||||||
@@ -25,6 +26,7 @@ namespace OpenWifi {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
			uint64_t UUID = ParamsObj->get(uCentralProtocol::UUID);
 | 
								uint64_t UUID = ParamsObj->get(uCentralProtocol::UUID);
 | 
				
			||||||
			auto Sanity = ParamsObj->get(uCentralProtocol::SANITY);
 | 
								auto Sanity = ParamsObj->get(uCentralProtocol::SANITY);
 | 
				
			||||||
 | 
								State_.sanity = Sanity;
 | 
				
			||||||
			auto CheckData = ParamsObj->get(uCentralProtocol::DATA).toString();
 | 
								auto CheckData = ParamsObj->get(uCentralProtocol::DATA).toString();
 | 
				
			||||||
			if (CheckData.empty())
 | 
								if (CheckData.empty())
 | 
				
			||||||
				CheckData = uCentralProtocol::EMPTY_JSON_DOC;
 | 
									CheckData = uCentralProtocol::EMPTY_JSON_DOC;
 | 
				
			||||||
@@ -48,14 +50,14 @@ namespace OpenWifi {
 | 
				
			|||||||
			Check.Data = CheckData;
 | 
								Check.Data = CheckData;
 | 
				
			||||||
			Check.Sanity = Sanity;
 | 
								Check.Sanity = Sanity;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			StorageService()->AddHealthCheckData(Check);
 | 
								StorageService()->AddHealthCheckData(*DbSession_, Check);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if (!request_uuid.empty()) {
 | 
								if (!request_uuid.empty()) {
 | 
				
			||||||
				StorageService()->SetCommandResult(request_uuid, CheckData);
 | 
									StorageService()->SetCommandResult(request_uuid, CheckData);
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			SetLastHealthCheck(Check);
 | 
								SetLastHealthCheck(Check);
 | 
				
			||||||
			if (KafkaManager()->Enabled()) {
 | 
								if (KafkaManager()->Enabled() && !AP_WS_Server()->KafkaDisableHealthChecks()) {
 | 
				
			||||||
				KafkaManager()->PostMessage(KafkaTopics::HEALTHCHECK, SerialNumber_, *ParamsObj);
 | 
									KafkaManager()->PostMessage(KafkaTopics::HEALTHCHECK, SerialNumber_, *ParamsObj);
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		} else {
 | 
							} else {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -36,7 +36,7 @@ namespace OpenWifi {
 | 
				
			|||||||
										   .Recorded = (uint64_t)time(nullptr),
 | 
															   .Recorded = (uint64_t)time(nullptr),
 | 
				
			||||||
										   .LogType = 0,
 | 
															   .LogType = 0,
 | 
				
			||||||
										   .UUID = State_.UUID};
 | 
															   .UUID = State_.UUID};
 | 
				
			||||||
			StorageService()->AddLog(DeviceLog);
 | 
								StorageService()->AddLog(*DbSession_, DeviceLog);
 | 
				
			||||||
			DeviceLogKafkaEvent	E(DeviceLog);
 | 
								DeviceLogKafkaEvent	E(DeviceLog);
 | 
				
			||||||
		} else {
 | 
							} else {
 | 
				
			||||||
			poco_warning(Logger_, fmt::format("LOG({}): Missing parameters.", CId_));
 | 
								poco_warning(Logger_, fmt::format("LOG({}): Missing parameters.", CId_));
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -35,7 +35,7 @@ namespace OpenWifi {
 | 
				
			|||||||
										   .Recorded = ParamsObj->get(uCentralProtocol::DATE),
 | 
															   .Recorded = ParamsObj->get(uCentralProtocol::DATE),
 | 
				
			||||||
										   .LogType = 2,
 | 
															   .LogType = 2,
 | 
				
			||||||
										   .UUID = ParamsObj->get(uCentralProtocol::UUID)};
 | 
															   .UUID = ParamsObj->get(uCentralProtocol::UUID)};
 | 
				
			||||||
			StorageService()->AddLog(DeviceLog);
 | 
								StorageService()->AddLog(*DbSession_, DeviceLog);
 | 
				
			||||||
			DeviceLogKafkaEvent	E(DeviceLog);
 | 
								DeviceLogKafkaEvent	E(DeviceLog);
 | 
				
			||||||
		} else {
 | 
							} else {
 | 
				
			||||||
			poco_warning(Logger_, fmt::format("REBOOT-LOG({}): Missing parameters.", CId_));
 | 
								poco_warning(Logger_, fmt::format("REBOOT-LOG({}): Missing parameters.", CId_));
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -35,7 +35,7 @@ namespace OpenWifi {
 | 
				
			|||||||
										   .LogType = 1,
 | 
															   .LogType = 1,
 | 
				
			||||||
										   .UUID = 0};
 | 
															   .UUID = 0};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			StorageService()->AddLog(DeviceLog);
 | 
								StorageService()->AddLog(*DbSession_, DeviceLog);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if (ParamsObj->get(uCentralProtocol::REBOOT).toString() == "true") {
 | 
								if (ParamsObj->get(uCentralProtocol::REBOOT).toString() == "true") {
 | 
				
			||||||
				GWObjects::CommandDetails Cmd;
 | 
									GWObjects::CommandDetails Cmd;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -3,6 +3,7 @@
 | 
				
			|||||||
//
 | 
					//
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "AP_WS_Connection.h"
 | 
					#include "AP_WS_Connection.h"
 | 
				
			||||||
 | 
					#include "AP_WS_Server.h"
 | 
				
			||||||
#include "StateUtils.h"
 | 
					#include "StateUtils.h"
 | 
				
			||||||
#include "StorageService.h"
 | 
					#include "StorageService.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -39,25 +40,27 @@ namespace OpenWifi {
 | 
				
			|||||||
												UUID, request_uuid));
 | 
																	UUID, request_uuid));
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								std::lock_guard	Guard(DbSession_->Mutex());
 | 
				
			||||||
			if(!Simulated_) {
 | 
								if(!Simulated_) {
 | 
				
			||||||
				uint64_t UpgradedUUID;
 | 
									uint64_t UpgradedUUID;
 | 
				
			||||||
				LookForUpgrade(UUID, UpgradedUUID);
 | 
									LookForUpgrade(DbSession_->Session(), UUID, UpgradedUUID);
 | 
				
			||||||
				State_.UUID = UpgradedUUID;
 | 
									State_.UUID = UpgradedUUID;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			SetLastStats(StateStr);
 | 
								SetLastStats(StateStr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			GWObjects::Statistics Stats{
 | 
								GWObjects::Statistics Stats{
 | 
				
			||||||
				.SerialNumber = SerialNumber_, .UUID = UUID, .Data = StateStr};
 | 
									.SerialNumber = SerialNumber_, .UUID = UUID, .Data = StateStr};
 | 
				
			||||||
			Stats.Recorded = Utils::Now();
 | 
								Stats.Recorded = Utils::Now();
 | 
				
			||||||
			StorageService()->AddStatisticsData(Stats);
 | 
								StorageService()->AddStatisticsData(DbSession_->Session(),Stats);
 | 
				
			||||||
			if (!request_uuid.empty()) {
 | 
								if (!request_uuid.empty()) {
 | 
				
			||||||
				StorageService()->SetCommandResult(request_uuid, StateStr);
 | 
									StorageService()->SetCommandResult(request_uuid, StateStr);
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			StateUtils::ComputeAssociations(StateObj, State_.Associations_2G,
 | 
								StateUtils::ComputeAssociations(StateObj, State_.Associations_2G,
 | 
				
			||||||
											State_.Associations_5G, State_.Associations_6G);
 | 
																State_.Associations_5G, State_.Associations_6G, State_.uptime);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if (KafkaManager()->Enabled()) {
 | 
								if (KafkaManager()->Enabled() && !AP_WS_Server()->KafkaDisableState()) {
 | 
				
			||||||
				KafkaManager()->PostMessage(KafkaTopics::STATE, SerialNumber_, *ParamsObj);
 | 
									KafkaManager()->PostMessage(KafkaTopics::STATE, SerialNumber_, *ParamsObj);
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -35,8 +35,7 @@ namespace OpenWifi {
 | 
				
			|||||||
				}
 | 
									}
 | 
				
			||||||
				if (TelemetryWebSocketRefCount_) {
 | 
									if (TelemetryWebSocketRefCount_) {
 | 
				
			||||||
					if (now < TelemetryWebSocketTimer_) {
 | 
										if (now < TelemetryWebSocketTimer_) {
 | 
				
			||||||
						// std::cout << SerialNumber_ << ": Updating WebSocket telemetry" <<
 | 
					
 | 
				
			||||||
						// std::endl;
 | 
					 | 
				
			||||||
						TelemetryWebSocketPackets_++;
 | 
											TelemetryWebSocketPackets_++;
 | 
				
			||||||
						State_.websocketPackets = TelemetryWebSocketPackets_;
 | 
											State_.websocketPackets = TelemetryWebSocketPackets_;
 | 
				
			||||||
						TelemetryStream()->NotifyEndPoint(SerialNumberInt_, KafkaPayload);
 | 
											TelemetryStream()->NotifyEndPoint(SerialNumberInt_, KafkaPayload);
 | 
				
			||||||
@@ -46,7 +45,6 @@ namespace OpenWifi {
 | 
				
			|||||||
				}
 | 
									}
 | 
				
			||||||
				if (TelemetryKafkaRefCount_) {
 | 
									if (TelemetryKafkaRefCount_) {
 | 
				
			||||||
					if (KafkaManager()->Enabled() && now < TelemetryKafkaTimer_) {
 | 
										if (KafkaManager()->Enabled() && now < TelemetryKafkaTimer_) {
 | 
				
			||||||
						// std::cout << SerialNumber_ << ": Updating Kafka telemetry" << std::endl;
 | 
					 | 
				
			||||||
						TelemetryKafkaPackets_++;
 | 
											TelemetryKafkaPackets_++;
 | 
				
			||||||
						State_.kafkaPackets = TelemetryKafkaPackets_;
 | 
											State_.kafkaPackets = TelemetryKafkaPackets_;
 | 
				
			||||||
						KafkaManager()->PostMessage(KafkaTopics::DEVICE_TELEMETRY, SerialNumber_,
 | 
											KafkaManager()->PostMessage(KafkaTopics::DEVICE_TELEMETRY, SerialNumber_,
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,62 +0,0 @@
 | 
				
			|||||||
//
 | 
					 | 
				
			||||||
// Created by stephane bourque on 2022-02-03.
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#pragma once
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include <mutex>
 | 
					 | 
				
			||||||
#include <string>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include "Poco/Environment.h"
 | 
					 | 
				
			||||||
#include "Poco/Net/SocketAcceptor.h"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include "framework/utils.h"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
namespace OpenWifi {
 | 
					 | 
				
			||||||
	class AP_WS_ReactorThreadPool {
 | 
					 | 
				
			||||||
	  public:
 | 
					 | 
				
			||||||
		explicit AP_WS_ReactorThreadPool() {
 | 
					 | 
				
			||||||
			NumberOfThreads_ = Poco::Environment::processorCount() * 4;
 | 
					 | 
				
			||||||
			if (NumberOfThreads_ == 0)
 | 
					 | 
				
			||||||
				NumberOfThreads_ = 4;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		~AP_WS_ReactorThreadPool() { Stop(); }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		void Start() {
 | 
					 | 
				
			||||||
			for (uint64_t i = 0; i < NumberOfThreads_; ++i) {
 | 
					 | 
				
			||||||
				auto NewReactor = std::make_unique<Poco::Net::SocketReactor>();
 | 
					 | 
				
			||||||
				auto NewThread = std::make_unique<Poco::Thread>();
 | 
					 | 
				
			||||||
				NewThread->start(*NewReactor);
 | 
					 | 
				
			||||||
				std::string ThreadName{"ap:react:" + std::to_string(i)};
 | 
					 | 
				
			||||||
				Utils::SetThreadName(*NewThread, ThreadName.c_str());
 | 
					 | 
				
			||||||
				Reactors_.emplace_back(std::move(NewReactor));
 | 
					 | 
				
			||||||
				Threads_.emplace_back(std::move(NewThread));
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		void Stop() {
 | 
					 | 
				
			||||||
			for (auto &i : Reactors_)
 | 
					 | 
				
			||||||
				i->stop();
 | 
					 | 
				
			||||||
			for (auto &i : Threads_) {
 | 
					 | 
				
			||||||
				i->join();
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			Reactors_.clear();
 | 
					 | 
				
			||||||
			Threads_.clear();
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		Poco::Net::SocketReactor &NextReactor() {
 | 
					 | 
				
			||||||
			std::lock_guard Lock(Mutex_);
 | 
					 | 
				
			||||||
			NextReactor_++;
 | 
					 | 
				
			||||||
			NextReactor_ %= NumberOfThreads_;
 | 
					 | 
				
			||||||
			return *Reactors_[NextReactor_];
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	  private:
 | 
					 | 
				
			||||||
		std::mutex Mutex_;
 | 
					 | 
				
			||||||
		uint64_t NumberOfThreads_;
 | 
					 | 
				
			||||||
		uint64_t NextReactor_ = 0;
 | 
					 | 
				
			||||||
		std::vector<std::unique_ptr<Poco::Net::SocketReactor>> Reactors_;
 | 
					 | 
				
			||||||
		std::vector<std::unique_ptr<Poco::Thread>> Threads_;
 | 
					 | 
				
			||||||
	};
 | 
					 | 
				
			||||||
} // namespace OpenWifi
 | 
					 | 
				
			||||||
							
								
								
									
										77
									
								
								src/AP_WS_Reactor_Pool.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										77
									
								
								src/AP_WS_Reactor_Pool.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,77 @@
 | 
				
			|||||||
 | 
					//
 | 
				
			||||||
 | 
					// Created by stephane bourque on 2022-02-03.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#pragma once
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <mutex>
 | 
				
			||||||
 | 
					#include <string>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <framework/utils.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <Poco/Environment.h>
 | 
				
			||||||
 | 
					#include <Poco/Net/SocketAcceptor.h>
 | 
				
			||||||
 | 
					#include <Poco/Data/SessionPool.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <StorageService.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace OpenWifi {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						class AP_WS_ReactorThreadPool {
 | 
				
			||||||
 | 
						  public:
 | 
				
			||||||
 | 
							explicit AP_WS_ReactorThreadPool(Poco::Logger &Logger) : Logger_(Logger) {
 | 
				
			||||||
 | 
								NumberOfThreads_ = Poco::Environment::processorCount() * 4;
 | 
				
			||||||
 | 
								if (NumberOfThreads_ == 0)
 | 
				
			||||||
 | 
									NumberOfThreads_ = 8;
 | 
				
			||||||
 | 
								NumberOfThreads_ = std::min(NumberOfThreads_, (std::uint64_t) 128);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							~AP_WS_ReactorThreadPool() { Stop(); }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							void Start() {
 | 
				
			||||||
 | 
								Reactors_.reserve(NumberOfThreads_);
 | 
				
			||||||
 | 
								DbSessions_.reserve(NumberOfThreads_);
 | 
				
			||||||
 | 
								Threads_.reserve(NumberOfThreads_);
 | 
				
			||||||
 | 
								Logger_.information(fmt::format("WebSocket Processor: starting {} threads.", NumberOfThreads_));
 | 
				
			||||||
 | 
								for (uint64_t i = 0; i < NumberOfThreads_; ++i) {
 | 
				
			||||||
 | 
									auto NewReactor = std::make_shared<Poco::Net::SocketReactor>();
 | 
				
			||||||
 | 
									auto NewThread = std::make_unique<Poco::Thread>();
 | 
				
			||||||
 | 
									NewThread->start(*NewReactor);
 | 
				
			||||||
 | 
									std::string ThreadName{"ap:react:" + std::to_string(i)};
 | 
				
			||||||
 | 
									Utils::SetThreadName(*NewThread, ThreadName.c_str());
 | 
				
			||||||
 | 
									Reactors_.emplace_back(std::move(NewReactor));
 | 
				
			||||||
 | 
									Threads_.emplace_back(std::move(NewThread));
 | 
				
			||||||
 | 
									DbSessions_.emplace_back(std::make_shared<LockedDbSession>());
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								Logger_.information(fmt::format("WebSocket Processor: {} threads started.", NumberOfThreads_));
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							void Stop() {
 | 
				
			||||||
 | 
								for (auto &i : Reactors_)
 | 
				
			||||||
 | 
									i->stop();
 | 
				
			||||||
 | 
								for (auto &i : Threads_) {
 | 
				
			||||||
 | 
									i->join();
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								Reactors_.clear();
 | 
				
			||||||
 | 
								Threads_.clear();
 | 
				
			||||||
 | 
								DbSessions_.clear();
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							auto NextReactor() {
 | 
				
			||||||
 | 
								std::lock_guard Lock(Mutex_);
 | 
				
			||||||
 | 
								NextReactor_++;
 | 
				
			||||||
 | 
								NextReactor_ %= NumberOfThreads_;
 | 
				
			||||||
 | 
								return std::make_pair(Reactors_[NextReactor_], DbSessions_[NextReactor_]);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						  private:
 | 
				
			||||||
 | 
							std::mutex Mutex_;
 | 
				
			||||||
 | 
							uint64_t NumberOfThreads_;
 | 
				
			||||||
 | 
							uint64_t NextReactor_ = 0;
 | 
				
			||||||
 | 
							std::vector<std::shared_ptr<Poco::Net::SocketReactor>> 	Reactors_;
 | 
				
			||||||
 | 
							std::vector<std::unique_ptr<Poco::Thread>> 				Threads_;
 | 
				
			||||||
 | 
							std::vector<std::shared_ptr<LockedDbSession>>			DbSessions_;
 | 
				
			||||||
 | 
							Poco::Logger &Logger_;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
					} // namespace OpenWifi
 | 
				
			||||||
@@ -6,32 +6,66 @@
 | 
				
			|||||||
//	Arilia Wireless Inc.
 | 
					//	Arilia Wireless Inc.
 | 
				
			||||||
//
 | 
					//
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "Poco/Net/Context.h"
 | 
					#include <Poco/Net/Context.h>
 | 
				
			||||||
#include "Poco/Net/HTTPHeaderStream.h"
 | 
					#include <Poco/Net/HTTPHeaderStream.h>
 | 
				
			||||||
#include "Poco/Net/HTTPServerRequest.h"
 | 
					#include <Poco/Net/HTTPServerRequest.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "AP_WS_Connection.h"
 | 
					#include <AP_WS_Connection.h>
 | 
				
			||||||
#include "AP_WS_Server.h"
 | 
					#include <AP_WS_Server.h>
 | 
				
			||||||
#include "ConfigurationCache.h"
 | 
					#include <ConfigurationCache.h>
 | 
				
			||||||
#include "TelemetryStream.h"
 | 
					#include <TelemetryStream.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "UI_GW_WebSocketNotifications.h"
 | 
					#include <fmt/format.h>
 | 
				
			||||||
#include "fmt/format.h"
 | 
					
 | 
				
			||||||
#include "framework/MicroServiceFuncs.h"
 | 
					#include <framework/MicroServiceFuncs.h>
 | 
				
			||||||
#include "framework/utils.h"
 | 
					#include <framework/utils.h>
 | 
				
			||||||
#include <framework/KafkaManager.h>
 | 
					#include <framework/KafkaManager.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <UI_GW_WebSocketNotifications.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace OpenWifi {
 | 
					namespace OpenWifi {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	void AP_WS_RequestHandler::handleRequest(Poco::Net::HTTPServerRequest &request,
 | 
						class AP_WS_RequestHandler : public Poco::Net::HTTPRequestHandler {
 | 
				
			||||||
											 Poco::Net::HTTPServerResponse &response) {
 | 
						  public:
 | 
				
			||||||
		try {
 | 
							explicit AP_WS_RequestHandler(Poco::Logger &L, std::uint64_t session_id) : Logger_(L),
 | 
				
			||||||
			AP_WS_Server()->AddConnection(
 | 
													   		session_id_(session_id) {
 | 
				
			||||||
				id_, std::make_shared<AP_WS_Connection>(request, response, id_, Logger_,
 | 
							 };
 | 
				
			||||||
														AP_WS_Server()->NextReactor()));
 | 
					
 | 
				
			||||||
		} catch (...) {
 | 
							void handleRequest(	Poco::Net::HTTPServerRequest &request,
 | 
				
			||||||
			poco_warning(Logger_, "Exception during WS creation");
 | 
											 	Poco::Net::HTTPServerResponse &response) override {
 | 
				
			||||||
 | 
								try {
 | 
				
			||||||
 | 
									auto NewConnection = std::make_shared<AP_WS_Connection>(request, response, session_id_, Logger_,
 | 
				
			||||||
 | 
																							AP_WS_Server()->NextReactor());
 | 
				
			||||||
 | 
									AP_WS_Server()->AddConnection(NewConnection);
 | 
				
			||||||
 | 
									NewConnection->Start();
 | 
				
			||||||
 | 
								} catch (...) {
 | 
				
			||||||
 | 
									poco_warning(Logger_, "Exception during WS creation");
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						  private:
 | 
				
			||||||
 | 
							Poco::Logger &Logger_;
 | 
				
			||||||
 | 
							std::uint64_t session_id_;
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						class AP_WS_RequestHandlerFactory : public Poco::Net::HTTPRequestHandlerFactory {
 | 
				
			||||||
 | 
						  public:
 | 
				
			||||||
 | 
							inline explicit AP_WS_RequestHandlerFactory(Poco::Logger &L) : Logger_(L) {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							inline Poco::Net::HTTPRequestHandler *
 | 
				
			||||||
 | 
							createRequestHandler(const Poco::Net::HTTPServerRequest &request) override {
 | 
				
			||||||
 | 
								if (request.find("Upgrade") != request.end() &&
 | 
				
			||||||
 | 
									Poco::icompare(request["Upgrade"], "websocket") == 0) {
 | 
				
			||||||
 | 
									Utils::SetThreadName("ws:conn-init");
 | 
				
			||||||
 | 
									session_id_++;
 | 
				
			||||||
 | 
									return new AP_WS_RequestHandler(Logger_, session_id_);
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
									return nullptr;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
						  private:
 | 
				
			||||||
 | 
							Poco::Logger &Logger_;
 | 
				
			||||||
 | 
							inline static std::atomic_uint64_t session_id_ = 0;
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	bool AP_WS_Server::ValidateCertificate(const std::string &ConnectionId,
 | 
						bool AP_WS_Server::ValidateCertificate(const std::string &ConnectionId,
 | 
				
			||||||
@@ -57,7 +91,7 @@ namespace OpenWifi {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
		SessionTimeOut_ = MicroServiceConfigGetInt("openwifi.session.timeout", 10*60);
 | 
							SessionTimeOut_ = MicroServiceConfigGetInt("openwifi.session.timeout", 10*60);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		Reactor_pool_ = std::make_unique<AP_WS_ReactorThreadPool>();
 | 
							Reactor_pool_ = std::make_unique<AP_WS_ReactorThreadPool>(Logger());
 | 
				
			||||||
		Reactor_pool_->Start();
 | 
							Reactor_pool_->Start();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		for (const auto &Svr : ConfigServersList_) {
 | 
							for (const auto &Svr : ConfigServersList_) {
 | 
				
			||||||
@@ -135,6 +169,9 @@ namespace OpenWifi {
 | 
				
			|||||||
					WebServerHttpParams);
 | 
										WebServerHttpParams);
 | 
				
			||||||
				WebServers_.push_back(std::move(NewWebServer));
 | 
									WebServers_.push_back(std::move(NewWebServer));
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								KafkaDisableState_ = MicroServiceConfigGetBool("openwifi.kafka.disablestate", false);
 | 
				
			||||||
 | 
								KafkaDisableHealthChecks_ = MicroServiceConfigGetBool("openwifi.kafka.disablehealthchecks", false);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		for (auto &server : WebServers_) {
 | 
							for (auto &server : WebServers_) {
 | 
				
			||||||
@@ -156,243 +193,420 @@ namespace OpenWifi {
 | 
				
			|||||||
			UseDefaultConfig_ = true;
 | 
								UseDefaultConfig_ = true;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		SimulatorId_ = MicroServiceConfigGetString("simulatorid", "");
 | 
							SimulatorId_ = Poco::toLower(MicroServiceConfigGetString("simulatorid", ""));
 | 
				
			||||||
		SimulatorEnabled_ = !SimulatorId_.empty();
 | 
							SimulatorEnabled_ = !SimulatorId_.empty();
 | 
				
			||||||
		Utils::SetThreadName(ReactorThread_, "dev:react:head");
 | 
							Utils::SetThreadName(ReactorThread_, "dev:react:head");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		GarbageCollectorCallback_ = std::make_unique<Poco::TimerCallback<AP_WS_Server>>(
 | 
					 | 
				
			||||||
			*this, &AP_WS_Server::onGarbageCollecting);
 | 
					 | 
				
			||||||
		Timer_.setStartInterval(10 * 1000);
 | 
					 | 
				
			||||||
		Timer_.setPeriodicInterval(10 * 1000); // every minute
 | 
					 | 
				
			||||||
		Timer_.start(*GarbageCollectorCallback_, MicroServiceTimerPool());
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		Running_ = true;
 | 
							Running_ = true;
 | 
				
			||||||
 | 
							GarbageCollector_.setName("ws:garbage");
 | 
				
			||||||
 | 
							GarbageCollector_.start(*this);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							std::thread CleanupThread([this](){ CleanupSessions(); });
 | 
				
			||||||
 | 
							CleanupThread.detach();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		return 0;
 | 
							return 0;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	void AP_WS_Server::onGarbageCollecting([[maybe_unused]] Poco::Timer &timer) {
 | 
						bool AP_WS_Server::Disconnect(uint64_t SerialNumber) {
 | 
				
			||||||
		static uint64_t last_log = Utils::Now(), last_zombie_run = 0;
 | 
							std::shared_ptr<AP_WS_Connection> Connection;
 | 
				
			||||||
		auto now = Utils::Now();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			{
 | 
								auto hashIndex = MACHash::Hash(SerialNumber);
 | 
				
			||||||
				std::lock_guard SessionLock(SessionMutex_);
 | 
								std::lock_guard DeviceLock(SerialNumbersMutex_[hashIndex]);
 | 
				
			||||||
				if (!Garbage_.empty()) {
 | 
								auto DeviceHint = SerialNumbers_[hashIndex].find(SerialNumber);
 | 
				
			||||||
					Garbage_.clear();
 | 
								if (DeviceHint == SerialNumbers_[hashIndex].end() || DeviceHint->second == nullptr) {
 | 
				
			||||||
				}
 | 
									return false;
 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			uint64_t total_connected_time = 0;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			if(now-last_zombie_run > 20) {
 | 
					 | 
				
			||||||
				poco_information(Logger(), fmt::format("Garbage collecting..."));
 | 
					 | 
				
			||||||
				std::vector<std::uint64_t> SessionsToRemove;
 | 
					 | 
				
			||||||
				NumberOfConnectedDevices_ = 0;
 | 
					 | 
				
			||||||
				NumberOfConnectingDevices_ = 0;
 | 
					 | 
				
			||||||
				AverageDeviceConnectionTime_ = 0;
 | 
					 | 
				
			||||||
				last_zombie_run = now;
 | 
					 | 
				
			||||||
				for(int hashIndex=0;hashIndex<256;hashIndex++) {
 | 
					 | 
				
			||||||
					std::lock_guard Lock(SerialNumbersMutex_[hashIndex]);
 | 
					 | 
				
			||||||
					auto hint = SerialNumbers_[hashIndex].begin();
 | 
					 | 
				
			||||||
					while (hint != end(SerialNumbers_[hashIndex])) {
 | 
					 | 
				
			||||||
						if (hint->second.second == nullptr) {
 | 
					 | 
				
			||||||
							hint = SerialNumbers_[hashIndex].erase(hint);
 | 
					 | 
				
			||||||
						} else if ((now - hint->second.second->State_.LastContact) >
 | 
					 | 
				
			||||||
								   SessionTimeOut_) {
 | 
					 | 
				
			||||||
							hint->second.second->EndConnection(false);
 | 
					 | 
				
			||||||
							poco_information(
 | 
					 | 
				
			||||||
								Logger(),
 | 
					 | 
				
			||||||
								fmt::format(
 | 
					 | 
				
			||||||
									"{}: Session seems idle. Controller disconnecting device.",
 | 
					 | 
				
			||||||
									hint->second.second->SerialNumber_));
 | 
					 | 
				
			||||||
							SessionsToRemove.emplace_back(hint->second.first);
 | 
					 | 
				
			||||||
							Garbage_.push_back(hint->second.second);
 | 
					 | 
				
			||||||
							hint = SerialNumbers_[hashIndex].erase(hint);
 | 
					 | 
				
			||||||
						} else if (hint->second.second->State_.Connected) {
 | 
					 | 
				
			||||||
							NumberOfConnectedDevices_++;
 | 
					 | 
				
			||||||
							total_connected_time += (now - hint->second.second->State_.started);
 | 
					 | 
				
			||||||
							hint++;
 | 
					 | 
				
			||||||
						} else {
 | 
					 | 
				
			||||||
							NumberOfConnectingDevices_++;
 | 
					 | 
				
			||||||
							hint++;
 | 
					 | 
				
			||||||
						}
 | 
					 | 
				
			||||||
					}
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				if(SessionsToRemove.empty()) {
 | 
					 | 
				
			||||||
					poco_information(Logger(), fmt::format("Removing {} sessions.", SessionsToRemove.size()));
 | 
					 | 
				
			||||||
					std::lock_guard Lock(SessionMutex_);
 | 
					 | 
				
			||||||
					for (const auto &Session : SessionsToRemove) {
 | 
					 | 
				
			||||||
						Sessions_.erase(Session);
 | 
					 | 
				
			||||||
					}
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				AverageDeviceConnectionTime_ =
 | 
					 | 
				
			||||||
				NumberOfConnectedDevices_ > 0 ? total_connected_time / NumberOfConnectedDevices_
 | 
					 | 
				
			||||||
											  : 0;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				poco_information(Logger(), fmt::format("Garbage collecting done..."));
 | 
					 | 
				
			||||||
			} else {
 | 
					 | 
				
			||||||
				std::lock_guard SessionLock(SessionMutex_);
 | 
					 | 
				
			||||||
				NumberOfConnectedDevices_ = Sessions_.size();
 | 
					 | 
				
			||||||
				AverageDeviceConnectionTime_ += 10;
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			if ((now - last_log) > 120) {
 | 
					 | 
				
			||||||
				last_log = now;
 | 
					 | 
				
			||||||
				poco_information(Logger(),
 | 
					 | 
				
			||||||
								 fmt::format("Active AP connections: {} Connecting: {} Average connection time: {} seconds",
 | 
					 | 
				
			||||||
											 NumberOfConnectedDevices_, NumberOfConnectingDevices_,
 | 
					 | 
				
			||||||
											 AverageDeviceConnectionTime_));
 | 
					 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
								Connection = DeviceHint->second;
 | 
				
			||||||
 | 
								SerialNumbers_[hashIndex].erase(DeviceHint);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		GWWebSocketNotifications::NumberOfConnection_t Notification;
 | 
							{
 | 
				
			||||||
		Notification.content.numberOfConnectingDevices = NumberOfConnectingDevices_;
 | 
								auto H = SessionHash::Hash(Connection->State_.sessionId);
 | 
				
			||||||
		Notification.content.numberOfDevices = NumberOfConnectedDevices_;
 | 
								std::lock_guard SessionLock(SessionMutex_[H]);
 | 
				
			||||||
		Notification.content.averageConnectedTime = AverageDeviceConnectionTime_;
 | 
								Sessions_[H].erase(Connection->State_.sessionId);
 | 
				
			||||||
		GetTotalDataStatistics(Notification.content.tx,Notification.content.rx);
 | 
							}
 | 
				
			||||||
		GWWebSocketNotifications::NumberOfConnections(Notification);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		Poco::JSON::Object	KafkaNotification;
 | 
							return true;
 | 
				
			||||||
		Notification.to_json(KafkaNotification);
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		Poco::JSON::Object FullEvent;
 | 
						void AP_WS_Server::CleanupSessions() {
 | 
				
			||||||
		FullEvent.set("type", "load-update");
 | 
					 | 
				
			||||||
		FullEvent.set("timestamp", now);
 | 
					 | 
				
			||||||
		FullEvent.set("payload", KafkaNotification);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		KafkaManager()->PostMessage(KafkaTopics::DEVICE_EVENT_QUEUE, "system", FullEvent);
 | 
							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,
 | 
				
			||||||
 | 
									 last_garbage_run = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							Poco::Logger &LocalLogger = Poco::Logger::create(
 | 
				
			||||||
 | 
								"WS-Session-Janitor", Poco::Logger::root().getChannel(), Poco::Logger::root().getLevel());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							while(Running_) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if(!Poco::Thread::trySleep(30000)) {
 | 
				
			||||||
 | 
									break;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								LocalLogger.information(fmt::format("Garbage collecting starting run."	));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								uint64_t total_connected_time = 0, now = Utils::Now();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if(now-last_zombie_run > 60) {
 | 
				
			||||||
 | 
									try {
 | 
				
			||||||
 | 
										poco_information(LocalLogger,
 | 
				
			||||||
 | 
														 fmt::format("Garbage collecting zombies... (step 1)"));
 | 
				
			||||||
 | 
										NumberOfConnectingDevices_ = 0;
 | 
				
			||||||
 | 
										AverageDeviceConnectionTime_ = 0;
 | 
				
			||||||
 | 
										int waits = 0;
 | 
				
			||||||
 | 
										for (int hashIndex = 0; hashIndex < MACHash::HashMax(); hashIndex++) {
 | 
				
			||||||
 | 
											last_zombie_run = now;
 | 
				
			||||||
 | 
											waits = 0;
 | 
				
			||||||
 | 
											while (true) {
 | 
				
			||||||
 | 
												if (SerialNumbersMutex_[hashIndex].try_lock()) {
 | 
				
			||||||
 | 
													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);
 | 
				
			||||||
 | 
														} else {
 | 
				
			||||||
 | 
															auto Device = hint->second;
 | 
				
			||||||
 | 
															auto RightNow = Utils::Now();
 | 
				
			||||||
 | 
															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);
 | 
				
			||||||
 | 
																AddCleanupSession(Device->State_.sessionId, Device->SerialNumberInt_);
 | 
				
			||||||
 | 
																++hint;
 | 
				
			||||||
 | 
															} else {
 | 
				
			||||||
 | 
																if (Device->State_.Connected) {
 | 
				
			||||||
 | 
																	total_connected_time +=
 | 
				
			||||||
 | 
																		(RightNow - Device->State_.started);
 | 
				
			||||||
 | 
																}
 | 
				
			||||||
 | 
																++hint;
 | 
				
			||||||
 | 
															}
 | 
				
			||||||
 | 
														}
 | 
				
			||||||
 | 
													}
 | 
				
			||||||
 | 
													SerialNumbersMutex_[hashIndex].unlock();
 | 
				
			||||||
 | 
													break;
 | 
				
			||||||
 | 
												} else if (waits < 5) {
 | 
				
			||||||
 | 
													waits++;
 | 
				
			||||||
 | 
													Poco::Thread::trySleep(10);
 | 
				
			||||||
 | 
												} else {
 | 
				
			||||||
 | 
													break;
 | 
				
			||||||
 | 
												}
 | 
				
			||||||
 | 
											}
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
										poco_information(LocalLogger, fmt::format("Garbage collecting zombies... (step 2)"));
 | 
				
			||||||
 | 
										LeftOverSessions_ = 0;
 | 
				
			||||||
 | 
										for (int i = 0; i < SessionHash::HashMax(); i++) {
 | 
				
			||||||
 | 
											waits = 0;
 | 
				
			||||||
 | 
											while (true) {
 | 
				
			||||||
 | 
												if (SessionMutex_[i].try_lock()) {
 | 
				
			||||||
 | 
													waits = 0;
 | 
				
			||||||
 | 
													auto hint = Sessions_[i].begin();
 | 
				
			||||||
 | 
													auto RightNow = Utils::Now();
 | 
				
			||||||
 | 
													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_) {
 | 
				
			||||||
 | 
															poco_information(
 | 
				
			||||||
 | 
																LocalLogger,
 | 
				
			||||||
 | 
																fmt::format("{}: Session seems idle. Controller disconnecting device.",
 | 
				
			||||||
 | 
																			hint->second->SerialNumber_));
 | 
				
			||||||
 | 
															AddCleanupSession(hint->second->State_.sessionId, hint->second->SerialNumberInt_);
 | 
				
			||||||
 | 
															++hint;
 | 
				
			||||||
 | 
															// hint = Sessions_[i].erase(hint);
 | 
				
			||||||
 | 
														} else {
 | 
				
			||||||
 | 
															++LeftOverSessions_;
 | 
				
			||||||
 | 
															++hint;
 | 
				
			||||||
 | 
														}
 | 
				
			||||||
 | 
													}
 | 
				
			||||||
 | 
													SessionMutex_[i].unlock();
 | 
				
			||||||
 | 
													break;
 | 
				
			||||||
 | 
												} else if (waits < 5) {
 | 
				
			||||||
 | 
													Poco::Thread::trySleep(10);
 | 
				
			||||||
 | 
													waits++;
 | 
				
			||||||
 | 
												} else {
 | 
				
			||||||
 | 
													break;
 | 
				
			||||||
 | 
												}
 | 
				
			||||||
 | 
											}
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
										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()));
 | 
				
			||||||
 | 
									} catch (const std::exception &E) {
 | 
				
			||||||
 | 
										poco_error(LocalLogger, fmt::format("std::exception: Garbage collecting zombies failed: {}", E.what()));
 | 
				
			||||||
 | 
									} catch (...) {
 | 
				
			||||||
 | 
										poco_error(LocalLogger, fmt::format("exception:Garbage collecting zombies failed: {}", "unknown"));
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if(NumberOfConnectedDevices_) {
 | 
				
			||||||
 | 
									if (last_garbage_run > 0) {
 | 
				
			||||||
 | 
										AverageDeviceConnectionTime_ += (now - last_garbage_run);
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								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"));
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							LocalLogger.information(fmt::format("Garbage collector done for the day."	));
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	void AP_WS_Server::Stop() {
 | 
						void AP_WS_Server::Stop() {
 | 
				
			||||||
		poco_information(Logger(), "Stopping...");
 | 
							poco_information(Logger(), "Stopping...");
 | 
				
			||||||
		Running_ = false;
 | 
							Running_ = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		Timer_.stop();
 | 
							GarbageCollector_.wakeUp();
 | 
				
			||||||
 | 
							GarbageCollector_.join();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		for (auto &server : WebServers_) {
 | 
							for (auto &server : WebServers_) {
 | 
				
			||||||
			server->stopAll();
 | 
								server->stopAll();
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		Reactor_pool_->Stop();
 | 
							Reactor_pool_->Stop();
 | 
				
			||||||
		Reactor_.stop();
 | 
							Reactor_.stop();
 | 
				
			||||||
		ReactorThread_.join();
 | 
							ReactorThread_.join();
 | 
				
			||||||
		poco_information(Logger(), "Stopped...");
 | 
							poco_information(Logger(), "Stopped...");
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	bool AP_WS_Server::GetStatistics(uint64_t SerialNumber, std::string &Statistics) const {
 | 
						bool AP_WS_Server::GetHealthDevices(std::uint64_t lowLimit, std::uint64_t  highLimit, std::vector<std::string> & SerialNumbers) {
 | 
				
			||||||
 | 
							SerialNumbers.clear();
 | 
				
			||||||
		auto hashIndex = Utils::CalculateMacAddressHash(SerialNumber);
 | 
							for(int i=0;i<SessionHash::HashMax();i++) {
 | 
				
			||||||
		std::lock_guard Lock(SerialNumbersMutex_[hashIndex]);
 | 
								std::lock_guard Lock(SessionMutex_[i]);
 | 
				
			||||||
		auto Device = SerialNumbers_[hashIndex].find(SerialNumber);
 | 
								for (const auto &connection : Sessions_[i]) {
 | 
				
			||||||
		if (Device == SerialNumbers_[hashIndex].end() || Device->second.second == nullptr) {
 | 
									if (connection.second->RawLastHealthcheck_.Sanity >= lowLimit &&
 | 
				
			||||||
			return false;
 | 
										connection.second->RawLastHealthcheck_.Sanity <= highLimit) {
 | 
				
			||||||
 | 
										SerialNumbers.push_back(connection.second->SerialNumber_);
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		Device->second.second->GetLastStats(Statistics);
 | 
							return true;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						bool AP_WS_Server::GetStatistics(uint64_t SerialNumber, std::string &Statistics) const {
 | 
				
			||||||
 | 
							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;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							Connection->GetLastStats(Statistics);
 | 
				
			||||||
		return true;
 | 
							return true;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	bool AP_WS_Server::GetState(uint64_t SerialNumber, GWObjects::ConnectionState &State) const {
 | 
						bool AP_WS_Server::GetState(uint64_t SerialNumber, GWObjects::ConnectionState &State) const {
 | 
				
			||||||
		auto hashIndex = Utils::CalculateMacAddressHash(SerialNumber);
 | 
							std::shared_ptr<AP_WS_Connection> Connection;
 | 
				
			||||||
		std::lock_guard Lock(SerialNumbersMutex_[hashIndex]);
 | 
							{
 | 
				
			||||||
		auto Device = SerialNumbers_[hashIndex].find(SerialNumber);
 | 
								auto hashIndex = MACHash::Hash(SerialNumber);
 | 
				
			||||||
		if (Device == SerialNumbers_[hashIndex].end() || Device->second.second == nullptr) {
 | 
								std::lock_guard DeviceLock(SerialNumbersMutex_[hashIndex]);
 | 
				
			||||||
			return false;
 | 
								auto DeviceHint = SerialNumbers_[hashIndex].find(SerialNumber);
 | 
				
			||||||
 | 
								if (DeviceHint == SerialNumbers_[hashIndex].end() ||
 | 
				
			||||||
 | 
									DeviceHint->second == nullptr) {
 | 
				
			||||||
 | 
									return false;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								Connection = DeviceHint->second;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		Device->second.second->GetState(State);
 | 
							Connection->GetState(State);
 | 
				
			||||||
		return true;
 | 
							return true;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	bool AP_WS_Server::GetHealthcheck(uint64_t SerialNumber,
 | 
						bool AP_WS_Server::GetHealthcheck(uint64_t SerialNumber,
 | 
				
			||||||
									  GWObjects::HealthCheck &CheckData) const {
 | 
														  GWObjects::HealthCheck &CheckData) const {
 | 
				
			||||||
 | 
							std::shared_ptr<AP_WS_Connection> Connection;
 | 
				
			||||||
		auto hashIndex = Utils::CalculateMacAddressHash(SerialNumber);
 | 
							{
 | 
				
			||||||
		std::lock_guard Lock(SerialNumbersMutex_[hashIndex]);
 | 
								auto hashIndex = MACHash::Hash(SerialNumber);
 | 
				
			||||||
		auto Device = SerialNumbers_[hashIndex].find(SerialNumber);
 | 
								std::lock_guard DeviceLock(SerialNumbersMutex_[hashIndex]);
 | 
				
			||||||
		if (Device == SerialNumbers_[hashIndex].end() || Device->second.second == nullptr) {
 | 
								auto Device = SerialNumbers_[hashIndex].find(SerialNumber);
 | 
				
			||||||
			return false;
 | 
								if (Device == SerialNumbers_[hashIndex].end() || Device->second == nullptr) {
 | 
				
			||||||
 | 
									return false;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								Connection = Device->second;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		Device->second.second->GetLastHealthCheck(CheckData);
 | 
							Connection->GetLastHealthCheck(CheckData);
 | 
				
			||||||
		return true;
 | 
							return true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	void AP_WS_Server::SetSessionDetails(uint64_t connection_id, uint64_t SerialNumber) {
 | 
						void AP_WS_Server::StartSession(uint64_t session_id, uint64_t SerialNumber) {
 | 
				
			||||||
		std::lock_guard SessionLock(SessionMutex_);
 | 
							auto sessionHash = SessionHash::Hash(session_id);
 | 
				
			||||||
		auto Conn = Sessions_.find(connection_id);
 | 
							std::shared_ptr<AP_WS_Connection> Connection;
 | 
				
			||||||
		if (Conn == end(Sessions_))
 | 
							{
 | 
				
			||||||
			return;
 | 
								std::lock_guard SessionLock(SessionMutex_[sessionHash]);
 | 
				
			||||||
 | 
								auto SessionHint = Sessions_[sessionHash].find(session_id);
 | 
				
			||||||
		auto hashIndex = Utils::CalculateMacAddressHash(SerialNumber);
 | 
								if (SessionHint == end(Sessions_[sessionHash])) {
 | 
				
			||||||
		std::lock_guard Lock(SerialNumbersMutex_[hashIndex]);
 | 
									return;
 | 
				
			||||||
		auto CurrentSerialNumber = SerialNumbers_[hashIndex].find(SerialNumber);
 | 
								}
 | 
				
			||||||
		if ((CurrentSerialNumber == SerialNumbers_[hashIndex].end()) ||
 | 
								Connection = SessionHint->second;
 | 
				
			||||||
			(CurrentSerialNumber->second.first < connection_id)) {
 | 
								Sessions_[sessionHash].erase(SessionHint);
 | 
				
			||||||
			SerialNumbers_[hashIndex][SerialNumber] = std::make_pair(connection_id, Conn->second);
 | 
					 | 
				
			||||||
			return;
 | 
					 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							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) {
 | 
						bool AP_WS_Server::EndSession(uint64_t session_id, uint64_t SerialNumber) {
 | 
				
			||||||
		std::lock_guard SessionLock(SessionMutex_);
 | 
							{
 | 
				
			||||||
		auto Session = Sessions_.find(session_id);
 | 
								poco_trace(Logger(), fmt::format("Ending session 1: {} for device: {}", session_id, Utils::IntToSerialNumber(SerialNumber)));
 | 
				
			||||||
		if (Session == end(Sessions_))
 | 
								auto sessionHash = SessionHash::Hash(session_id);
 | 
				
			||||||
			return false;
 | 
								std::lock_guard SessionLock(SessionMutex_[sessionHash]);
 | 
				
			||||||
 | 
								Sessions_[sessionHash].erase(session_id);
 | 
				
			||||||
		Garbage_.push_back(Session->second);
 | 
								poco_trace(Logger(), fmt::format("Ended session 1: {} for device: {}", session_id, Utils::IntToSerialNumber(SerialNumber)));
 | 
				
			||||||
 | 
					 | 
				
			||||||
		auto hashIndex = Utils::CalculateMacAddressHash(SerialNumber);
 | 
					 | 
				
			||||||
		std::lock_guard Lock(SerialNumbersMutex_[hashIndex]);
 | 
					 | 
				
			||||||
		auto Device = SerialNumbers_[hashIndex].find(SerialNumber);
 | 
					 | 
				
			||||||
		if (Device == end(SerialNumbers_[hashIndex])) {
 | 
					 | 
				
			||||||
			Sessions_.erase(Session);
 | 
					 | 
				
			||||||
			return false;
 | 
					 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (Device->second.first == session_id) {
 | 
							{
 | 
				
			||||||
			Sessions_.erase(Session);
 | 
								auto hashIndex = MACHash::Hash(SerialNumber);
 | 
				
			||||||
			SerialNumbers_[hashIndex].erase(Device);
 | 
								poco_trace(Logger(), fmt::format("Ending session 2.0: {} for device: {} hi:{}", session_id, Utils::IntToSerialNumber(SerialNumber), hashIndex));
 | 
				
			||||||
			return true;
 | 
								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;
 | 
				
			||||||
		Sessions_.erase(Session);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		return false;
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	bool AP_WS_Server::Connected(uint64_t SerialNumber,
 | 
						bool AP_WS_Server::Connected(uint64_t SerialNumber,
 | 
				
			||||||
								 GWObjects::DeviceRestrictions &Restrictions) const {
 | 
													 GWObjects::DeviceRestrictions &Restrictions) const {
 | 
				
			||||||
		auto hashIndex = Utils::CalculateMacAddressHash(SerialNumber);
 | 
							std::shared_ptr<AP_WS_Connection> Connection;
 | 
				
			||||||
		std::lock_guard Lock(SerialNumbersMutex_[hashIndex]);
 | 
							{
 | 
				
			||||||
		auto Device = SerialNumbers_[hashIndex].find(SerialNumber);
 | 
								auto hashIndex = MACHash::Hash(SerialNumber);
 | 
				
			||||||
		if (Device == end(SerialNumbers_[hashIndex]) || Device->second.second == nullptr) {
 | 
								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;
 | 
								return false;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		Device->second.second->GetRestrictions(Restrictions);
 | 
							Restrictions = Connection->GetRestrictions();
 | 
				
			||||||
		return Device->second.second->State_.Connected;
 | 
							return Connection->State_.Connected;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	bool AP_WS_Server::Connected(uint64_t SerialNumber) const {
 | 
						bool AP_WS_Server::Connected(uint64_t SerialNumber) const {
 | 
				
			||||||
		auto hashIndex = Utils::CalculateMacAddressHash(SerialNumber);
 | 
							std::shared_ptr<AP_WS_Connection> Connection;
 | 
				
			||||||
		std::lock_guard Lock(SerialNumbersMutex_[hashIndex]);
 | 
							{
 | 
				
			||||||
		auto Device = SerialNumbers_[hashIndex].find(SerialNumber);
 | 
								auto hashIndex = MACHash::Hash(SerialNumber);
 | 
				
			||||||
		if (Device == end(SerialNumbers_[hashIndex]) || Device->second.second == nullptr) {
 | 
								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;
 | 
								return false;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		return Device->second.second->State_.Connected;
 | 
							return Connection->State_.Connected;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	bool AP_WS_Server::SendFrame(uint64_t SerialNumber, const std::string &Payload) const {
 | 
						bool AP_WS_Server::SendFrame(uint64_t SerialNumber, const std::string &Payload) const {
 | 
				
			||||||
		auto hashIndex = Utils::CalculateMacAddressHash(SerialNumber);
 | 
							auto hashIndex = MACHash::Hash(SerialNumber);
 | 
				
			||||||
		std::lock_guard Lock(SerialNumbersMutex_[hashIndex]);
 | 
					
 | 
				
			||||||
		auto Device = SerialNumbers_[hashIndex].find(SerialNumber);
 | 
							std::shared_ptr<AP_WS_Connection> Connection;
 | 
				
			||||||
		if (Device == end(SerialNumbers_[hashIndex]) || Device->second.second == nullptr) {
 | 
							{
 | 
				
			||||||
 | 
								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;
 | 
								return false;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		try {
 | 
							try {
 | 
				
			||||||
			return Device->second.second->Send(Payload);
 | 
								return Connection->Send(Payload);
 | 
				
			||||||
		} catch (...) {
 | 
							} catch (...) {
 | 
				
			||||||
			poco_debug(Logger(), fmt::format(": SendFrame: Could not send data to device '{}'",
 | 
								poco_debug(Logger(), fmt::format(": SendFrame: Could not send data to device '{}'",
 | 
				
			||||||
											 Utils::IntToSerialNumber(SerialNumber)));
 | 
																 Utils::IntToSerialNumber(SerialNumber)));
 | 
				
			||||||
@@ -401,48 +615,64 @@ namespace OpenWifi {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	void AP_WS_Server::StopWebSocketTelemetry(uint64_t RPCID, uint64_t SerialNumber) {
 | 
						void AP_WS_Server::StopWebSocketTelemetry(uint64_t RPCID, uint64_t SerialNumber) {
 | 
				
			||||||
		auto hashIndex = Utils::CalculateMacAddressHash(SerialNumber);
 | 
							std::shared_ptr<AP_WS_Connection> Connection;
 | 
				
			||||||
		std::lock_guard Lock(SerialNumbersMutex_[hashIndex]);
 | 
							{
 | 
				
			||||||
		auto Device = SerialNumbers_[hashIndex].find(SerialNumber);
 | 
								auto hashIndex = MACHash::Hash(SerialNumber);
 | 
				
			||||||
		if (Device == end(SerialNumbers_[hashIndex]) || Device->second.second == nullptr) {
 | 
								std::lock_guard DeviceLock(SerialNumbersMutex_[hashIndex]);
 | 
				
			||||||
			return;
 | 
								auto Device = SerialNumbers_[hashIndex].find(SerialNumber);
 | 
				
			||||||
 | 
								if (Device == end(SerialNumbers_[hashIndex]) || Device->second == nullptr) {
 | 
				
			||||||
 | 
									return;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								Connection = Device->second;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		Device->second.second->StopWebSocketTelemetry(RPCID);
 | 
							Connection->StopWebSocketTelemetry(RPCID);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	void
 | 
						void
 | 
				
			||||||
	AP_WS_Server::SetWebSocketTelemetryReporting(uint64_t RPCID, uint64_t SerialNumber,
 | 
						AP_WS_Server::SetWebSocketTelemetryReporting(uint64_t RPCID, uint64_t SerialNumber,
 | 
				
			||||||
												 uint64_t Interval, uint64_t Lifetime,
 | 
																	 uint64_t Interval, uint64_t Lifetime,
 | 
				
			||||||
												 const std::vector<std::string> &TelemetryTypes) {
 | 
																	 const std::vector<std::string> &TelemetryTypes) {
 | 
				
			||||||
		auto hashIndex = Utils::CalculateMacAddressHash(SerialNumber);
 | 
							std::shared_ptr<AP_WS_Connection> Connection;
 | 
				
			||||||
		std::lock_guard Lock(SerialNumbersMutex_[hashIndex]);
 | 
							{
 | 
				
			||||||
		auto Device = SerialNumbers_[hashIndex].find(SerialNumber);
 | 
								auto hashIndex = MACHash::Hash(SerialNumber);
 | 
				
			||||||
		if (Device == end(SerialNumbers_[hashIndex]) || Device->second.second == nullptr) {
 | 
								std::lock_guard DeviceLock(SerialNumbersMutex_[hashIndex]);
 | 
				
			||||||
			return;
 | 
								auto DeviceHint = SerialNumbers_[hashIndex].find(SerialNumber);
 | 
				
			||||||
 | 
								if (DeviceHint == end(SerialNumbers_[hashIndex]) || DeviceHint->second == nullptr) {
 | 
				
			||||||
 | 
									return;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								Connection = DeviceHint->second;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		Device->second.second->SetWebSocketTelemetryReporting(RPCID, Interval, Lifetime, TelemetryTypes);
 | 
							Connection->SetWebSocketTelemetryReporting(RPCID, Interval, Lifetime, TelemetryTypes);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	void AP_WS_Server::SetKafkaTelemetryReporting(uint64_t RPCID, uint64_t SerialNumber,
 | 
						void AP_WS_Server::SetKafkaTelemetryReporting(uint64_t RPCID, uint64_t SerialNumber,
 | 
				
			||||||
												  uint64_t Interval, uint64_t Lifetime,
 | 
																	  uint64_t Interval, uint64_t Lifetime,
 | 
				
			||||||
												  const std::vector<std::string> &TelemetryTypes) {
 | 
																	  const std::vector<std::string> &TelemetryTypes) {
 | 
				
			||||||
		auto hashIndex = Utils::CalculateMacAddressHash(SerialNumber);
 | 
							std::shared_ptr<AP_WS_Connection> Connection;
 | 
				
			||||||
		std::lock_guard Lock(SerialNumbersMutex_[hashIndex]);
 | 
							{
 | 
				
			||||||
		auto Device = SerialNumbers_[hashIndex].find(SerialNumber);
 | 
								auto hashIndex = MACHash::Hash(SerialNumber);
 | 
				
			||||||
		if (Device == end(SerialNumbers_[hashIndex]) || Device->second.second == nullptr) {
 | 
								std::lock_guard DeviceLock(SerialNumbersMutex_[hashIndex]);
 | 
				
			||||||
			return;
 | 
								auto DeviceHint = SerialNumbers_[hashIndex].find(SerialNumber);
 | 
				
			||||||
 | 
								if (DeviceHint == end(SerialNumbers_[hashIndex]) || DeviceHint->second == nullptr) {
 | 
				
			||||||
 | 
									return;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								Connection = DeviceHint->second;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		Device->second.second->SetKafkaTelemetryReporting(RPCID, Interval, Lifetime, TelemetryTypes);
 | 
							Connection->SetKafkaTelemetryReporting(RPCID, Interval, Lifetime, TelemetryTypes);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	void AP_WS_Server::StopKafkaTelemetry(uint64_t RPCID, uint64_t SerialNumber) {
 | 
						void AP_WS_Server::StopKafkaTelemetry(uint64_t RPCID, uint64_t SerialNumber) {
 | 
				
			||||||
		auto hashIndex = Utils::CalculateMacAddressHash(SerialNumber);
 | 
							std::shared_ptr<AP_WS_Connection> Connection;
 | 
				
			||||||
		std::lock_guard Lock(SerialNumbersMutex_[hashIndex]);
 | 
							{
 | 
				
			||||||
		auto Device = SerialNumbers_[hashIndex].find(SerialNumber);
 | 
								auto hashIndex = MACHash::Hash(SerialNumber);
 | 
				
			||||||
		if (Device == end(SerialNumbers_[hashIndex]) || Device->second.second == nullptr) {
 | 
								std::lock_guard DevicesLock(SerialNumbersMutex_[hashIndex]);
 | 
				
			||||||
			return;
 | 
								auto DeviceHint = SerialNumbers_[hashIndex].find(SerialNumber);
 | 
				
			||||||
 | 
								if (DeviceHint == end(SerialNumbers_[hashIndex]) || DeviceHint->second == nullptr) {
 | 
				
			||||||
 | 
									return;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								Connection = DeviceHint->second;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		Device->second.second->StopKafkaTelemetry(RPCID);
 | 
							Connection->StopKafkaTelemetry(RPCID);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	void AP_WS_Server::GetTelemetryParameters(
 | 
						void AP_WS_Server::GetTelemetryParameters(
 | 
				
			||||||
@@ -451,14 +681,18 @@ namespace OpenWifi {
 | 
				
			|||||||
		uint64_t &TelemetryWebSocketCount, uint64_t &TelemetryKafkaCount,
 | 
							uint64_t &TelemetryWebSocketCount, uint64_t &TelemetryKafkaCount,
 | 
				
			||||||
		uint64_t &TelemetryWebSocketPackets, uint64_t &TelemetryKafkaPackets) {
 | 
							uint64_t &TelemetryWebSocketPackets, uint64_t &TelemetryKafkaPackets) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		auto hashIndex = Utils::CalculateMacAddressHash(SerialNumber);
 | 
							std::shared_ptr<AP_WS_Connection> Connection;
 | 
				
			||||||
		std::lock_guard Lock(SerialNumbersMutex_[hashIndex]);
 | 
							{
 | 
				
			||||||
		auto Device = SerialNumbers_[hashIndex].find(SerialNumber);
 | 
								auto hashIndex = MACHash::Hash(SerialNumber);
 | 
				
			||||||
		if (Device == end(SerialNumbers_[hashIndex]) || Device->second.second == nullptr) {
 | 
								std::lock_guard DevicesLock(SerialNumbersMutex_[hashIndex]);
 | 
				
			||||||
			return;
 | 
								auto DeviceHint = SerialNumbers_[hashIndex].find(SerialNumber);
 | 
				
			||||||
 | 
								if (DeviceHint == end(SerialNumbers_[hashIndex]) || DeviceHint->second == nullptr) {
 | 
				
			||||||
 | 
									return;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								Connection = DeviceHint->second;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		Device->second.second->GetTelemetryParameters(TelemetryRunning, TelemetryInterval,
 | 
							Connection->GetTelemetryParameters(TelemetryRunning, TelemetryInterval,
 | 
				
			||||||
										  TelemetryWebSocketTimer, TelemetryKafkaTimer,
 | 
															  TelemetryWebSocketTimer, TelemetryKafkaTimer,
 | 
				
			||||||
										  TelemetryWebSocketCount, TelemetryKafkaCount,
 | 
															  TelemetryWebSocketCount, TelemetryKafkaCount,
 | 
				
			||||||
										  TelemetryWebSocketPackets, TelemetryKafkaPackets);
 | 
															  TelemetryWebSocketPackets, TelemetryKafkaPackets);
 | 
				
			||||||
@@ -467,16 +701,24 @@ namespace OpenWifi {
 | 
				
			|||||||
	bool AP_WS_Server::SendRadiusAccountingData(const std::string &SerialNumber,
 | 
						bool AP_WS_Server::SendRadiusAccountingData(const std::string &SerialNumber,
 | 
				
			||||||
												const unsigned char *buffer, std::size_t size) {
 | 
																	const unsigned char *buffer, std::size_t size) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		auto IntSerialNumber = Utils::SerialNumberToInt(SerialNumber);
 | 
							std::shared_ptr<AP_WS_Connection> Connection;
 | 
				
			||||||
		auto hashIndex = Utils::CalculateMacAddressHash(IntSerialNumber);
 | 
							{
 | 
				
			||||||
		std::lock_guard Lock(SerialNumbersMutex_[hashIndex]);
 | 
								auto IntSerialNumber = Utils::SerialNumberToInt(SerialNumber);
 | 
				
			||||||
		auto Device = SerialNumbers_[hashIndex].find(IntSerialNumber);
 | 
								auto hashIndex = MACHash::Hash(IntSerialNumber);
 | 
				
			||||||
		if (Device == end(SerialNumbers_[hashIndex]) || Device->second.second == nullptr) {
 | 
								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(Connection->Dead_) {
 | 
				
			||||||
			return false;
 | 
								return false;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		try {
 | 
							try {
 | 
				
			||||||
			return Device->second.second->SendRadiusAccountingData(buffer, size);
 | 
								return Connection->SendRadiusAccountingData(buffer, size);
 | 
				
			||||||
		} catch (...) {
 | 
							} catch (...) {
 | 
				
			||||||
			poco_debug(
 | 
								poco_debug(
 | 
				
			||||||
				Logger(),
 | 
									Logger(),
 | 
				
			||||||
@@ -488,16 +730,24 @@ namespace OpenWifi {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	bool AP_WS_Server::SendRadiusAuthenticationData(const std::string &SerialNumber,
 | 
						bool AP_WS_Server::SendRadiusAuthenticationData(const std::string &SerialNumber,
 | 
				
			||||||
													const unsigned char *buffer, std::size_t size) {
 | 
																		const unsigned char *buffer, std::size_t size) {
 | 
				
			||||||
		auto IntSerialNumber = Utils::SerialNumberToInt(SerialNumber);
 | 
							std::shared_ptr<AP_WS_Connection> Connection;
 | 
				
			||||||
		auto hashIndex = Utils::CalculateMacAddressHash(IntSerialNumber);
 | 
							{
 | 
				
			||||||
		std::lock_guard Lock(SerialNumbersMutex_[hashIndex]);
 | 
								auto IntSerialNumber = Utils::SerialNumberToInt(SerialNumber);
 | 
				
			||||||
		auto Device = SerialNumbers_[hashIndex].find(IntSerialNumber);
 | 
								auto hashIndex = MACHash::Hash(IntSerialNumber);
 | 
				
			||||||
		if (Device == end(SerialNumbers_[hashIndex]) || Device->second.second == nullptr) {
 | 
								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(Connection->Dead_) {
 | 
				
			||||||
			return false;
 | 
								return false;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		try {
 | 
							try {
 | 
				
			||||||
			return Device->second.second->SendRadiusAuthenticationData(buffer, size);
 | 
								return Connection->SendRadiusAuthenticationData(buffer, size);
 | 
				
			||||||
		} catch (...) {
 | 
							} catch (...) {
 | 
				
			||||||
			poco_debug(
 | 
								poco_debug(
 | 
				
			||||||
				Logger(),
 | 
									Logger(),
 | 
				
			||||||
@@ -509,16 +759,23 @@ namespace OpenWifi {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	bool AP_WS_Server::SendRadiusCoAData(const std::string &SerialNumber,
 | 
						bool AP_WS_Server::SendRadiusCoAData(const std::string &SerialNumber,
 | 
				
			||||||
										 const unsigned char *buffer, std::size_t size) {
 | 
															 const unsigned char *buffer, std::size_t size) {
 | 
				
			||||||
		auto IntSerialNumber = Utils::SerialNumberToInt(SerialNumber);
 | 
							std::shared_ptr<AP_WS_Connection> Connection;
 | 
				
			||||||
		auto hashIndex = Utils::CalculateMacAddressHash(IntSerialNumber);
 | 
							{
 | 
				
			||||||
		std::lock_guard Lock(SerialNumbersMutex_[hashIndex]);
 | 
								auto IntSerialNumber = Utils::SerialNumberToInt(SerialNumber);
 | 
				
			||||||
		auto Device = SerialNumbers_[hashIndex].find(IntSerialNumber);
 | 
								auto hashIndex = MACHash::Hash(IntSerialNumber);
 | 
				
			||||||
		if (Device == end(SerialNumbers_[hashIndex]) || Device->second.second == nullptr) {
 | 
								std::lock_guard DeviceLock(SerialNumbersMutex_[hashIndex]);
 | 
				
			||||||
			return false;
 | 
								auto DeviceHint = SerialNumbers_[hashIndex].find(IntSerialNumber);
 | 
				
			||||||
 | 
								if (DeviceHint == end(SerialNumbers_[hashIndex]) || DeviceHint->second == nullptr) {
 | 
				
			||||||
 | 
									return false;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								Connection = DeviceHint->second;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if(Connection->Dead_) {
 | 
				
			||||||
 | 
								return false;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
		try {
 | 
							try {
 | 
				
			||||||
			return Device->second.second->SendRadiusCoAData(buffer, size);
 | 
								return Connection->SendRadiusCoAData(buffer, size);
 | 
				
			||||||
		} catch (...) {
 | 
							} catch (...) {
 | 
				
			||||||
			poco_debug(Logger(),
 | 
								poco_debug(Logger(),
 | 
				
			||||||
					   fmt::format(": SendRadiusCoAData: Could not send data to device '{}'",
 | 
										   fmt::format(": SendRadiusCoAData: Could not send data to device '{}'",
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -24,46 +24,51 @@
 | 
				
			|||||||
#include "Poco/Timer.h"
 | 
					#include "Poco/Timer.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "AP_WS_Connection.h"
 | 
					#include "AP_WS_Connection.h"
 | 
				
			||||||
#include "AP_WS_ReactorPool.h"
 | 
					#include "AP_WS_Reactor_Pool.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "framework/SubSystemServer.h"
 | 
					#include "framework/SubSystemServer.h"
 | 
				
			||||||
#include "framework/utils.h"
 | 
					#include "framework/utils.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace OpenWifi {
 | 
					namespace OpenWifi {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	class AP_WS_RequestHandler : public Poco::Net::HTTPRequestHandler {
 | 
						constexpr uint MACHashMax = 256;
 | 
				
			||||||
 | 
						constexpr uint MACHashMask = MACHashMax-1;
 | 
				
			||||||
 | 
						class MACHash {
 | 
				
			||||||
	  public:
 | 
						  public:
 | 
				
			||||||
		explicit AP_WS_RequestHandler(Poco::Logger &L, uint64_t id) : Logger_(L), id_(id){};
 | 
							[[nodiscard]] static inline uint16_t Hash(std::uint64_t value) {
 | 
				
			||||||
 | 
								uint8_t hash = 0, i=6;
 | 
				
			||||||
		void handleRequest(Poco::Net::HTTPServerRequest &request,
 | 
								while(i) {
 | 
				
			||||||
						   Poco::Net::HTTPServerResponse &response) override;
 | 
									hash ^= (value & MACHashMask) + 1;
 | 
				
			||||||
 | 
									value >>= 8;
 | 
				
			||||||
	  private:
 | 
									--i;
 | 
				
			||||||
		Poco::Logger &Logger_;
 | 
					 | 
				
			||||||
		uint64_t id_ = 0;
 | 
					 | 
				
			||||||
	};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	class AP_WS_RequestHandlerFactory : public Poco::Net::HTTPRequestHandlerFactory {
 | 
					 | 
				
			||||||
	  public:
 | 
					 | 
				
			||||||
		inline explicit AP_WS_RequestHandlerFactory(Poco::Logger &L) : Logger_(L) {}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		inline Poco::Net::HTTPRequestHandler *
 | 
					 | 
				
			||||||
		createRequestHandler(const Poco::Net::HTTPServerRequest &request) override {
 | 
					 | 
				
			||||||
			if (request.find("Upgrade") != request.end() &&
 | 
					 | 
				
			||||||
				Poco::icompare(request["Upgrade"], "websocket") == 0) {
 | 
					 | 
				
			||||||
				Utils::SetThreadName("ws:conn-init");
 | 
					 | 
				
			||||||
				return new AP_WS_RequestHandler(Logger_, id_++);
 | 
					 | 
				
			||||||
			} else {
 | 
					 | 
				
			||||||
				return nullptr;
 | 
					 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
								return hash;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	  private:
 | 
							[[nodiscard]] static inline uint16_t Hash(const std::string & value) {
 | 
				
			||||||
		Poco::Logger &Logger_;
 | 
								return Hash(Utils::MACToInt(value));
 | 
				
			||||||
		inline static uint64_t id_ = 1;
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							[[nodiscard]] static inline uint16_t HashMax() {
 | 
				
			||||||
 | 
								return MACHashMax;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	class AP_WS_Server : public SubSystemServer {
 | 
						constexpr uint SessionHashMax = 256;
 | 
				
			||||||
 | 
						constexpr uint SessionHashMask = SessionHashMax-1;
 | 
				
			||||||
 | 
						class SessionHash {
 | 
				
			||||||
 | 
						  public:
 | 
				
			||||||
 | 
							[[nodiscard]] static inline uint16_t Hash(std::uint64_t value) {
 | 
				
			||||||
 | 
								return (value & SessionHashMask);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							[[nodiscard]] static inline uint16_t HashMax() {
 | 
				
			||||||
 | 
								return SessionHashMax;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						class AP_WS_Server : public SubSystemServer, public Poco::Runnable {
 | 
				
			||||||
	  public:
 | 
						  public:
 | 
				
			||||||
		static auto instance() {
 | 
							static auto instance() {
 | 
				
			||||||
			static auto instance_ = new AP_WS_Server;
 | 
								static auto instance_ = new AP_WS_Server;
 | 
				
			||||||
@@ -77,48 +82,50 @@ namespace OpenWifi {
 | 
				
			|||||||
								 const Poco::Crypto::X509Certificate &Certificate);
 | 
													 const Poco::Crypto::X509Certificate &Certificate);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		inline bool IsSimSerialNumber(const std::string &SerialNumber) const {
 | 
							inline bool IsSimSerialNumber(const std::string &SerialNumber) const {
 | 
				
			||||||
			return IsSim(Poco::toLower(SerialNumber)) &&
 | 
								return IsSim(SerialNumber) &&
 | 
				
			||||||
				   Poco::toLower(SerialNumber) == Poco::toLower(SimulatorId_);
 | 
									   SerialNumber == SimulatorId_;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		inline static bool IsSim(const std::string &SerialNumber) {
 | 
							inline static bool IsSim(const std::string &SerialNumber) {
 | 
				
			||||||
			return SerialNumber.substr(0, 6) == "53494d";
 | 
								return SerialNumber.substr(0, 6) == "53494d";
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		inline bool IsSimEnabled() const { return SimulatorEnabled_; }
 | 
							void run() override;		//	Garbage collector thread.
 | 
				
			||||||
 | 
							[[nodiscard]] inline bool IsSimEnabled() const { return SimulatorEnabled_; }
 | 
				
			||||||
		inline bool AllowSerialNumberMismatch() const { return AllowSerialNumberMismatch_; }
 | 
							[[nodiscard]] inline bool AllowSerialNumberMismatch() const { return AllowSerialNumberMismatch_; }
 | 
				
			||||||
 | 
							[[nodiscard]] inline uint64_t MismatchDepth() const { return MismatchDepth_; }
 | 
				
			||||||
		inline uint64_t MismatchDepth() const { return MismatchDepth_; }
 | 
							[[nodiscard]] inline bool UseProvisioning() const { return LookAtProvisioning_; }
 | 
				
			||||||
 | 
							[[nodiscard]] inline bool UseDefaults() const { return UseDefaultConfig_; }
 | 
				
			||||||
		inline bool UseProvisioning() const { return LookAtProvisioning_; }
 | 
							[[nodiscard]] inline bool Running() const { return Running_; }
 | 
				
			||||||
		inline bool UseDefaults() const { return UseDefaultConfig_; }
 | 
							[[nodiscard]] inline std::pair<std::shared_ptr<Poco::Net::SocketReactor>, std::shared_ptr<LockedDbSession>> NextReactor() {
 | 
				
			||||||
 | 
					 | 
				
			||||||
		[[nodiscard]] inline Poco::Net::SocketReactor &NextReactor() {
 | 
					 | 
				
			||||||
			return Reactor_pool_->NextReactor();
 | 
								return Reactor_pool_->NextReactor();
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		[[nodiscard]] inline bool Running() const { return Running_; }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		inline void AddConnection(uint64_t session_id,
 | 
							inline void AddConnection(std::shared_ptr<AP_WS_Connection> Connection) {
 | 
				
			||||||
								  std::shared_ptr<AP_WS_Connection> Connection) {
 | 
								std::uint64_t sessionHash = SessionHash::Hash(Connection->State_.sessionId);
 | 
				
			||||||
			std::lock_guard Lock(SessionMutex_);
 | 
								std::lock_guard SessionLock(SessionMutex_[sessionHash]);
 | 
				
			||||||
			Sessions_[session_id] = std::move(Connection);
 | 
								if(Sessions_[sessionHash].find(Connection->State_.sessionId)==end(Sessions_[sessionHash])) {
 | 
				
			||||||
 | 
									Sessions_[sessionHash][Connection->State_.sessionId] = std::move(Connection);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		inline bool DeviceRequiresSecureRtty(uint64_t serialNumber) const {
 | 
							[[nodiscard]] inline bool DeviceRequiresSecureRTTY(uint64_t serialNumber) const {
 | 
				
			||||||
			auto hashIndex = Utils::CalculateMacAddressHash(serialNumber);
 | 
								std::shared_ptr<AP_WS_Connection> Connection;
 | 
				
			||||||
			std::lock_guard	G(SerialNumbersMutex_[hashIndex]);
 | 
								{
 | 
				
			||||||
 | 
									auto hashIndex = MACHash::Hash(serialNumber);
 | 
				
			||||||
			auto Connection = SerialNumbers_[hashIndex].find(serialNumber);
 | 
									std::lock_guard DeviceLock(SerialNumbersMutex_[hashIndex]);
 | 
				
			||||||
			if (Connection==end(SerialNumbers_[hashIndex]) || Connection->second.second==nullptr)
 | 
									auto DeviceHint = SerialNumbers_[hashIndex].find(serialNumber);
 | 
				
			||||||
				return false;
 | 
									if (DeviceHint == end(SerialNumbers_[hashIndex]) || DeviceHint->second == nullptr)
 | 
				
			||||||
			return Connection->second.second->RttyMustBeSecure_;
 | 
										return false;
 | 
				
			||||||
 | 
									Connection = DeviceHint->second;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								return Connection->RTTYMustBeSecure_;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		inline bool GetStatistics(const std::string &SerialNumber, std::string &Statistics) const {
 | 
							inline bool GetStatistics(const std::string &SerialNumber, std::string &Statistics) const {
 | 
				
			||||||
			return GetStatistics(Utils::SerialNumberToInt(SerialNumber), Statistics);
 | 
								return GetStatistics(Utils::SerialNumberToInt(SerialNumber), Statistics);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		bool GetStatistics(uint64_t SerialNumber, std::string &Statistics) const;
 | 
							[[nodiscard]] bool GetStatistics(uint64_t SerialNumber, std::string &Statistics) const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		inline bool GetState(const std::string &SerialNumber,
 | 
							inline bool GetState(const std::string &SerialNumber,
 | 
				
			||||||
							 GWObjects::ConnectionState &State) const {
 | 
												 GWObjects::ConnectionState &State) const {
 | 
				
			||||||
@@ -134,13 +141,8 @@ namespace OpenWifi {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
		bool Connected(uint64_t SerialNumber, GWObjects::DeviceRestrictions &Restrictions) const;
 | 
							bool Connected(uint64_t SerialNumber, GWObjects::DeviceRestrictions &Restrictions) const;
 | 
				
			||||||
		bool Connected(uint64_t SerialNumber) const;
 | 
							bool Connected(uint64_t SerialNumber) const;
 | 
				
			||||||
 | 
							bool Disconnect(uint64_t SerialNumber);
 | 
				
			||||||
		inline bool SendFrame(const std::string &SerialNumber, const std::string &Payload) const {
 | 
					 | 
				
			||||||
			return SendFrame(Utils::SerialNumberToInt(SerialNumber), Payload);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		bool SendFrame(uint64_t SerialNumber, const std::string &Payload) const;
 | 
							bool SendFrame(uint64_t SerialNumber, const std::string &Payload) const;
 | 
				
			||||||
 | 
					 | 
				
			||||||
		bool SendRadiusAuthenticationData(const std::string &SerialNumber,
 | 
							bool SendRadiusAuthenticationData(const std::string &SerialNumber,
 | 
				
			||||||
										  const unsigned char *buffer, std::size_t size);
 | 
															  const unsigned char *buffer, std::size_t size);
 | 
				
			||||||
		bool SendRadiusAccountingData(const std::string &SerialNumber, const unsigned char *buffer,
 | 
							bool SendRadiusAccountingData(const std::string &SerialNumber, const unsigned char *buffer,
 | 
				
			||||||
@@ -148,9 +150,8 @@ namespace OpenWifi {
 | 
				
			|||||||
		bool SendRadiusCoAData(const std::string &SerialNumber, const unsigned char *buffer,
 | 
							bool SendRadiusCoAData(const std::string &SerialNumber, const unsigned char *buffer,
 | 
				
			||||||
							   std::size_t size);
 | 
												   std::size_t size);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		void SetSessionDetails(uint64_t connection_id, uint64_t SerialNumber);
 | 
							void StartSession(uint64_t session_id, uint64_t SerialNumber);
 | 
				
			||||||
		bool EndSession(uint64_t connection_id, uint64_t serial_number);
 | 
							bool EndSession(uint64_t session_id, uint64_t SerialNumber);
 | 
				
			||||||
		bool EndSessionUnSafe(uint64_t session_id, uint64_t serial_number);
 | 
					 | 
				
			||||||
		void SetWebSocketTelemetryReporting(uint64_t RPCID, uint64_t SerialNumber,
 | 
							void SetWebSocketTelemetryReporting(uint64_t RPCID, uint64_t SerialNumber,
 | 
				
			||||||
											uint64_t Interval, uint64_t Lifetime,
 | 
																uint64_t Interval, uint64_t Lifetime,
 | 
				
			||||||
											const std::vector<std::string> &TelemetryTypes);
 | 
																const std::vector<std::string> &TelemetryTypes);
 | 
				
			||||||
@@ -167,7 +168,9 @@ namespace OpenWifi {
 | 
				
			|||||||
									uint64_t &TelemetryWebSocketPackets,
 | 
														uint64_t &TelemetryWebSocketPackets,
 | 
				
			||||||
									uint64_t &TelemetryKafkaPackets);
 | 
														uint64_t &TelemetryKafkaPackets);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		void onGarbageCollecting(Poco::Timer &timer);
 | 
							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);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		inline void AverageDeviceStatistics(uint64_t &Connections, uint64_t &AverageConnectionTime,
 | 
							inline void AverageDeviceStatistics(uint64_t &Connections, uint64_t &AverageConnectionTime,
 | 
				
			||||||
											uint64_t &NumberOfConnectingDevices) const {
 | 
																uint64_t &NumberOfConnectingDevices) const {
 | 
				
			||||||
@@ -176,94 +179,80 @@ namespace OpenWifi {
 | 
				
			|||||||
			NumberOfConnectingDevices = NumberOfConnectingDevices_;
 | 
								NumberOfConnectingDevices = NumberOfConnectingDevices_;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							inline bool SendFrame(const std::string &SerialNumber, const std::string &Payload) const {
 | 
				
			||||||
 | 
								return SendFrame(Utils::SerialNumberToInt(SerialNumber), Payload);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		inline void AddRX(std::uint64_t bytes) {
 | 
							inline void AddRX(std::uint64_t bytes) {
 | 
				
			||||||
			std::lock_guard		G(StatsMutex_);
 | 
					 | 
				
			||||||
			RX_ += bytes;
 | 
								RX_ += bytes;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		inline void AddTX(std::uint64_t bytes) {
 | 
							inline void AddTX(std::uint64_t bytes) {
 | 
				
			||||||
			std::lock_guard		G(StatsMutex_);
 | 
					 | 
				
			||||||
			TX_ += bytes;
 | 
								TX_ += bytes;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		inline void GetTotalDataStatistics(std::uint64_t &TX, std::uint64_t &RX) const {
 | 
							inline void GetTotalDataStatistics(std::uint64_t &TX, std::uint64_t &RX) const {
 | 
				
			||||||
			std::lock_guard		G(StatsMutex_);
 | 
					 | 
				
			||||||
			TX = TX_;
 | 
								TX = TX_;
 | 
				
			||||||
			RX = RX_;
 | 
								RX = RX_;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		//	TOD: move to hash based map.
 | 
							bool KafkaDisableState() const { return KafkaDisableState_; }
 | 
				
			||||||
		inline bool GetHealthDevices(std::uint64_t lowLimit, std::uint64_t  highLimit, std::vector<std::string> & SerialNumbers) {
 | 
							bool KafkaDisableHealthChecks() const { return KafkaDisableHealthChecks_; }
 | 
				
			||||||
			std::lock_guard Lock(SessionMutex_);
 | 
					
 | 
				
			||||||
			for(const auto &connection:Sessions_) {
 | 
							inline void IncrementConnectionCount() {
 | 
				
			||||||
				if(	connection.second->RawLastHealthcheck_.Sanity>=lowLimit 	&&
 | 
								++NumberOfConnectedDevices_;
 | 
				
			||||||
					connection.second->RawLastHealthcheck_.Sanity<=highLimit) {
 | 
					 | 
				
			||||||
					SerialNumbers.push_back(connection.second->SerialNumber_);
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			return true;
 | 
					 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		inline bool ExtendedAttributes(const std::string &serialNumber,
 | 
							inline void DecrementConnectionCount() {
 | 
				
			||||||
			bool & hasGPS,
 | 
								--NumberOfConnectedDevices_;
 | 
				
			||||||
			std::uint64_t &Sanity,
 | 
					 | 
				
			||||||
			std::double_t &MemoryUsed,
 | 
					 | 
				
			||||||
			std::double_t &Load,
 | 
					 | 
				
			||||||
			std::double_t &Temperature
 | 
					 | 
				
			||||||
			) {
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			auto serialNumberInt = Utils::SerialNumberToInt(serialNumber);
 | 
					 | 
				
			||||||
			auto hashIndex = Utils::CalculateMacAddressHash(serialNumberInt);
 | 
					 | 
				
			||||||
			std::lock_guard	G(SerialNumbersMutex_[hashIndex]);
 | 
					 | 
				
			||||||
			auto session_hint = SerialNumbers_[hashIndex].find(Utils::SerialNumberToInt(serialNumber));
 | 
					 | 
				
			||||||
			if(session_hint==end(SerialNumbers_[hashIndex])) {
 | 
					 | 
				
			||||||
				return false;
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			hasGPS = session_hint->second.second->hasGPS;
 | 
					 | 
				
			||||||
			Sanity = session_hint->second.second->RawLastHealthcheck_.Sanity;
 | 
					 | 
				
			||||||
			MemoryUsed = session_hint->second.second->memory_used_;
 | 
					 | 
				
			||||||
			Load = session_hint->second.second->cpu_load_;
 | 
					 | 
				
			||||||
			Temperature = session_hint->second.second->temperature_;
 | 
					 | 
				
			||||||
			return true;
 | 
					 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							inline void AddCleanupSession(uint64_t session_id, uint64_t SerialNumber) {
 | 
				
			||||||
 | 
								std::lock_guard G(CleanupMutex_);
 | 
				
			||||||
 | 
								CleanupSessions_.emplace_back(session_id, SerialNumber);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							void CleanupSessions();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	  private:
 | 
						  private:
 | 
				
			||||||
		mutable std::mutex 			SessionMutex_;
 | 
							std::array<std::mutex,SessionHashMax> 			SessionMutex_;
 | 
				
			||||||
		mutable std::mutex			StatsMutex_;
 | 
							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::mutex,MACHashMax>		SerialNumbersMutex_;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		std::unique_ptr<Poco::Crypto::X509Certificate> IssuerCert_;
 | 
							std::unique_ptr<Poco::Crypto::X509Certificate> IssuerCert_;
 | 
				
			||||||
		std::list<std::unique_ptr<Poco::Net::HTTPServer>> WebServers_;
 | 
							std::list<std::unique_ptr<Poco::Net::HTTPServer>> WebServers_;
 | 
				
			||||||
 | 
							Poco::ThreadPool DeviceConnectionPool_{"ws:dev-pool", 4, 256};
 | 
				
			||||||
		Poco::Net::SocketReactor Reactor_;
 | 
							Poco::Net::SocketReactor Reactor_;
 | 
				
			||||||
		Poco::Thread ReactorThread_;
 | 
							Poco::Thread ReactorThread_;
 | 
				
			||||||
		std::string SimulatorId_;
 | 
							std::string SimulatorId_;
 | 
				
			||||||
		Poco::ThreadPool DeviceConnectionPool_{"ws:dev-pool", 2, 64};
 | 
					 | 
				
			||||||
		bool LookAtProvisioning_ = false;
 | 
							bool LookAtProvisioning_ = false;
 | 
				
			||||||
		bool UseDefaultConfig_ = true;
 | 
							bool UseDefaultConfig_ = true;
 | 
				
			||||||
		bool SimulatorEnabled_ = false;
 | 
							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::unique_ptr<AP_WS_ReactorThreadPool> Reactor_pool_;
 | 
				
			||||||
		std::atomic_bool Running_ = false;
 | 
							std::atomic_bool Running_ = false;
 | 
				
			||||||
		std::map<std::uint64_t, std::shared_ptr<AP_WS_Connection>> Sessions_;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		using SerialNumberMap = std::map<uint64_t /* serial number */, std::pair<uint64_t /* session id*/,
 | 
							std::uint64_t 			MismatchDepth_ = 2;
 | 
				
			||||||
									 std::shared_ptr<AP_WS_Connection>>>;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		std::array<SerialNumberMap,256>			SerialNumbers_;
 | 
							std::atomic_uint64_t 	NumberOfConnectedDevices_ = 0;
 | 
				
			||||||
		mutable std::array<std::mutex,256>		SerialNumbersMutex_;
 | 
							std::atomic_uint64_t 	AverageDeviceConnectionTime_ = 0;
 | 
				
			||||||
 | 
					 | 
				
			||||||
		std::atomic_bool AllowSerialNumberMismatch_ = true;
 | 
					 | 
				
			||||||
		std::atomic_uint64_t MismatchDepth_ = 2;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		std::uint64_t 			NumberOfConnectedDevices_ = 0;
 | 
					 | 
				
			||||||
		std::uint64_t 			AverageDeviceConnectionTime_ = 0;
 | 
					 | 
				
			||||||
		std::uint64_t 			NumberOfConnectingDevices_ = 0;
 | 
							std::uint64_t 			NumberOfConnectingDevices_ = 0;
 | 
				
			||||||
		std::uint64_t 			SessionTimeOut_ = 10*60;
 | 
							std::uint64_t 			SessionTimeOut_ = 10*60;
 | 
				
			||||||
 | 
							std::uint64_t 			LeftOverSessions_ = 0;
 | 
				
			||||||
		std::atomic_uint64_t 	TX_=0,RX_=0;
 | 
							std::atomic_uint64_t 	TX_=0,RX_=0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		std::vector<std::shared_ptr<AP_WS_Connection>> Garbage_;
 | 
							std::atomic_bool 		KafkaDisableState_=false,
 | 
				
			||||||
 | 
											 		KafkaDisableHealthChecks_=false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		std::unique_ptr<Poco::TimerCallback<AP_WS_Server>> GarbageCollectorCallback_;
 | 
							Poco::Thread 			GarbageCollector_;
 | 
				
			||||||
		Poco::Timer Timer_;
 | 
					 | 
				
			||||||
		Poco::Thread GarbageCollector_;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		AP_WS_Server() noexcept
 | 
							AP_WS_Server() noexcept
 | 
				
			||||||
			: SubSystemServer("WebSocketServer", "WS-SVR", "ucentral.websocket") {}
 | 
								: SubSystemServer("WebSocketServer", "WS-SVR", "ucentral.websocket") {}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -10,6 +10,7 @@
 | 
				
			|||||||
#include <string>
 | 
					#include <string>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "framework/MicroServiceFuncs.h"
 | 
					#include "framework/MicroServiceFuncs.h"
 | 
				
			||||||
 | 
					#include "framework/ow_constants.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "CentralConfig.h"
 | 
					#include "CentralConfig.h"
 | 
				
			||||||
#include "nlohmann/json.hpp"
 | 
					#include "nlohmann/json.hpp"
 | 
				
			||||||
@@ -34,7 +35,7 @@ namespace OpenWifi {
 | 
				
			|||||||
			std::lock_guard G(Mutex_);
 | 
								std::lock_guard G(Mutex_);
 | 
				
			||||||
			if (!PlatformsLoaded_)
 | 
								if (!PlatformsLoaded_)
 | 
				
			||||||
				LoadPlatforms();
 | 
									LoadPlatforms();
 | 
				
			||||||
			auto P = Poco::toUpper(Caps.Platform());
 | 
								auto P = Poco::toLower(Caps.Platform());
 | 
				
			||||||
			auto Hint = Platforms_.find(Caps.Compatible());
 | 
								auto Hint = Platforms_.find(Caps.Compatible());
 | 
				
			||||||
			if (Hint == Platforms_.end()) {
 | 
								if (Hint == Platforms_.end()) {
 | 
				
			||||||
				Platforms_.insert(std::make_pair(Caps.Compatible(), P));
 | 
									Platforms_.insert(std::make_pair(Caps.Compatible(), P));
 | 
				
			||||||
@@ -68,7 +69,7 @@ namespace OpenWifi {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
			auto Hint = Platforms_.find(DeviceType);
 | 
								auto Hint = Platforms_.find(DeviceType);
 | 
				
			||||||
			if (Hint == Platforms_.end())
 | 
								if (Hint == Platforms_.end())
 | 
				
			||||||
				return "AP";
 | 
									return Platforms::AP;
 | 
				
			||||||
			return Hint->second;
 | 
								return Hint->second;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -110,7 +111,7 @@ namespace OpenWifi {
 | 
				
			|||||||
				i >> cache;
 | 
									i >> cache;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				for (const auto &[Type, Platform] : cache.items()) {
 | 
									for (const auto &[Type, Platform] : cache.items()) {
 | 
				
			||||||
					Platforms_[Type] = Platform;
 | 
										Platforms_[Type] = Poco::toLower(to_string(Platform));
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			} catch (...) {
 | 
								} catch (...) {
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -204,6 +204,17 @@ namespace OpenWifi::Config {
 | 
				
			|||||||
		return false;
 | 
							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() {
 | 
						bool Config::Valid() {
 | 
				
			||||||
		try {
 | 
							try {
 | 
				
			||||||
			Poco::JSON::Parser Parser;
 | 
								Poco::JSON::Parser Parser;
 | 
				
			||||||
@@ -254,7 +265,11 @@ namespace OpenWifi::Config {
 | 
				
			|||||||
				Model_ = Caps->get("model").toString();
 | 
									Model_ = Caps->get("model").toString();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if (Caps->has("platform"))
 | 
								if (Caps->has("platform"))
 | 
				
			||||||
				Platform_ = Caps->get("platform").toString();
 | 
									Platform_ = Poco::toLower(Caps->get("platform").toString());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if(Compatible_.empty()) {
 | 
				
			||||||
 | 
									Compatible_ = Model_;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			std::ostringstream OS;
 | 
								std::ostringstream OS;
 | 
				
			||||||
			Caps->stringify(OS);
 | 
								Caps->stringify(OS);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -23,6 +23,7 @@ namespace OpenWifi::Config {
 | 
				
			|||||||
		[[nodiscard]] std::string get() { return Config_; };
 | 
							[[nodiscard]] std::string get() { return Config_; };
 | 
				
			||||||
		[[nodiscard]] std::string Default();
 | 
							[[nodiscard]] std::string Default();
 | 
				
			||||||
		[[nodiscard]] Poco::JSON::Object::Ptr to_json();
 | 
							[[nodiscard]] Poco::JSON::Object::Ptr to_json();
 | 
				
			||||||
 | 
							[[nodiscard]] std::uint64_t UUID();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	  private:
 | 
						  private:
 | 
				
			||||||
		void Init();
 | 
							void Init();
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -45,11 +45,9 @@ namespace OpenWifi {
 | 
				
			|||||||
							std::lock_guard Lock(LocalMutex_);
 | 
												std::lock_guard Lock(LocalMutex_);
 | 
				
			||||||
							auto RPC = OutStandingRequests_.find(ID);
 | 
												auto RPC = OutStandingRequests_.find(ID);
 | 
				
			||||||
							if (RPC == OutStandingRequests_.end()) {
 | 
												if (RPC == OutStandingRequests_.end()) {
 | 
				
			||||||
								//								std::cout << __LINE__ << std::endl;
 | 
					 | 
				
			||||||
								poco_debug(Logger(), fmt::format("({}): RPC {} cannot be found.",
 | 
													poco_debug(Logger(), fmt::format("({}): RPC {} cannot be found.",
 | 
				
			||||||
																 SerialNumberStr, ID));
 | 
																					 SerialNumberStr, ID));
 | 
				
			||||||
							} else if (RPC->second.SerialNumber != Resp->SerialNumber_) {
 | 
												} else if (RPC->second.SerialNumber != Resp->SerialNumber_) {
 | 
				
			||||||
								//								std::cout << __LINE__ << std::endl;
 | 
					 | 
				
			||||||
								poco_debug(
 | 
													poco_debug(
 | 
				
			||||||
									Logger(),
 | 
														Logger(),
 | 
				
			||||||
									fmt::format("({}): RPC {} serial number mismatch {}!={}.",
 | 
														fmt::format("({}): RPC {} serial number mismatch {}!={}.",
 | 
				
			||||||
@@ -60,7 +58,6 @@ namespace OpenWifi {
 | 
				
			|||||||
								std::chrono::duration<double, std::milli> rpc_execution_time =
 | 
													std::chrono::duration<double, std::milli> rpc_execution_time =
 | 
				
			||||||
									std::chrono::high_resolution_clock::now() -
 | 
														std::chrono::high_resolution_clock::now() -
 | 
				
			||||||
									RPC->second.submitted;
 | 
														RPC->second.submitted;
 | 
				
			||||||
								//								std::cout << __LINE__ << std::endl;
 | 
					 | 
				
			||||||
								poco_debug(Logger(),
 | 
													poco_debug(Logger(),
 | 
				
			||||||
										   fmt::format("({}): Received RPC answer {}. Command={}",
 | 
															   fmt::format("({}): Received RPC answer {}. Command={}",
 | 
				
			||||||
													   SerialNumberStr, ID,
 | 
																		   SerialNumberStr, ID,
 | 
				
			||||||
@@ -140,7 +137,6 @@ namespace OpenWifi {
 | 
				
			|||||||
				}
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		} else {
 | 
							} else {
 | 
				
			||||||
			//				std::cout << __LINE__ << std::endl;
 | 
					 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		Command.State = 0;
 | 
							Command.State = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -163,7 +159,6 @@ namespace OpenWifi {
 | 
				
			|||||||
		if (Command.rpc_entry) {
 | 
							if (Command.rpc_entry) {
 | 
				
			||||||
			TmpRpcEntry = Command.rpc_entry;
 | 
								TmpRpcEntry = Command.rpc_entry;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		//		std::cout << __LINE__ << "  State=" << Command.State << std::endl;
 | 
					 | 
				
			||||||
		if (Command.State == 2) {
 | 
							if (Command.State == 2) {
 | 
				
			||||||
			//	 look at the payload to see if we should continue or not...
 | 
								//	 look at the payload to see if we should continue or not...
 | 
				
			||||||
			if (Payload->has("result")) {
 | 
								if (Payload->has("result")) {
 | 
				
			||||||
@@ -173,12 +168,10 @@ namespace OpenWifi {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
					std::uint64_t Error = Status->get("error");
 | 
										std::uint64_t Error = Status->get("error");
 | 
				
			||||||
					if (Error == 0) {
 | 
										if (Error == 0) {
 | 
				
			||||||
						//						std::cout << __LINE__ << std::endl;
 | 
					 | 
				
			||||||
						StorageService()->CommandCompleted(Command.UUID, Payload,
 | 
											StorageService()->CommandCompleted(Command.UUID, Payload,
 | 
				
			||||||
														   rpc_execution_time, true);
 | 
																			   rpc_execution_time, true);
 | 
				
			||||||
						Command.State = 1;
 | 
											Command.State = 1;
 | 
				
			||||||
					} else {
 | 
										} else {
 | 
				
			||||||
						//						std::cout << __LINE__ << std::endl;
 | 
					 | 
				
			||||||
						StorageService()->CommandCompleted(Command.UUID, Payload,
 | 
											StorageService()->CommandCompleted(Command.UUID, Payload,
 | 
				
			||||||
														   rpc_execution_time, true);
 | 
																			   rpc_execution_time, true);
 | 
				
			||||||
						std::string ErrorTxt = Status->get("result");
 | 
											std::string ErrorTxt = Status->get("result");
 | 
				
			||||||
@@ -186,14 +179,11 @@ namespace OpenWifi {
 | 
				
			|||||||
						Command.State = 0;
 | 
											Command.State = 0;
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
				} else {
 | 
									} else {
 | 
				
			||||||
					//					std::cout << __LINE__ << std::endl;
 | 
					 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			} else {
 | 
								} else {
 | 
				
			||||||
				//				std::cout << __LINE__ << std::endl;
 | 
					 | 
				
			||||||
				Command.State = 0;
 | 
									Command.State = 0;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		} else if (Command.State == 1) {
 | 
							} else if (Command.State == 1) {
 | 
				
			||||||
			//			std::cout << "Completing script 2 phase commit." << std::endl;
 | 
					 | 
				
			||||||
			StorageService()->CommandCompleted(Command.UUID, Payload, rpc_execution_time, true);
 | 
								StorageService()->CommandCompleted(Command.UUID, Payload, rpc_execution_time, true);
 | 
				
			||||||
			if (Command.Deferred) {
 | 
								if (Command.Deferred) {
 | 
				
			||||||
				Reply = false;
 | 
									Reply = false;
 | 
				
			||||||
@@ -202,7 +192,6 @@ namespace OpenWifi {
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (Command.State == 0) {
 | 
							if (Command.State == 0) {
 | 
				
			||||||
			//			std::cout << __LINE__ << "  State=" << Command.State << std::endl;
 | 
					 | 
				
			||||||
			OutStandingRequests_.erase(Command.Id);
 | 
								OutStandingRequests_.erase(Command.Id);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		if (Reply && TmpRpcEntry != nullptr)
 | 
							if (Reply && TmpRpcEntry != nullptr)
 | 
				
			||||||
@@ -262,8 +251,6 @@ namespace OpenWifi {
 | 
				
			|||||||
		for (auto request = OutStandingRequests_.begin(); request != OutStandingRequests_.end();) {
 | 
							for (auto request = OutStandingRequests_.begin(); request != OutStandingRequests_.end();) {
 | 
				
			||||||
			std::chrono::duration<double, std::milli> delta = now - request->second.submitted;
 | 
								std::chrono::duration<double, std::milli> delta = now - request->second.submitted;
 | 
				
			||||||
			if (delta > 10min) {
 | 
								if (delta > 10min) {
 | 
				
			||||||
				//				std::cout << __LINE__ << "  -->> " << request->second.Id <<
 | 
					 | 
				
			||||||
				// std::endl;
 | 
					 | 
				
			||||||
				MyLogger.debug(fmt::format("{}: Command={} for {} Timed out.", request->second.UUID,
 | 
									MyLogger.debug(fmt::format("{}: Command={} for {} Timed out.", request->second.UUID,
 | 
				
			||||||
										   APCommands::to_string(request->second.Command),
 | 
															   APCommands::to_string(request->second.Command),
 | 
				
			||||||
										   Utils::IntToSerialNumber(request->second.SerialNumber)));
 | 
															   Utils::IntToSerialNumber(request->second.SerialNumber)));
 | 
				
			||||||
@@ -275,8 +262,6 @@ namespace OpenWifi {
 | 
				
			|||||||
				StorageService()->SetCommandTimedOut(request->second.UUID);
 | 
									StorageService()->SetCommandTimedOut(request->second.UUID);
 | 
				
			||||||
				request = OutStandingRequests_.erase(request);
 | 
									request = OutStandingRequests_.erase(request);
 | 
				
			||||||
			} else {
 | 
								} else {
 | 
				
			||||||
				//				std::cout << __LINE__ << "  -->> " << request->second.Id <<
 | 
					 | 
				
			||||||
				// std::endl;
 | 
					 | 
				
			||||||
				++request;
 | 
									++request;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -11,12 +11,12 @@
 | 
				
			|||||||
namespace OpenWifi {
 | 
					namespace OpenWifi {
 | 
				
			||||||
	class ConfigurationCache {
 | 
						class ConfigurationCache {
 | 
				
			||||||
	  public:
 | 
						  public:
 | 
				
			||||||
		static ConfigurationCache &instance() {
 | 
							static auto instance() {
 | 
				
			||||||
			static ConfigurationCache instance;
 | 
								static auto instance = new ConfigurationCache;
 | 
				
			||||||
			return instance;
 | 
								return instance;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		inline uint64_t CurrentConfig(uint64_t SerialNumber) {
 | 
							inline uint64_t GetCurrentConfig(std::uint64_t SerialNumber) {
 | 
				
			||||||
			std::lock_guard G(Mutex_);
 | 
								std::lock_guard G(Mutex_);
 | 
				
			||||||
			const auto Hint = Cache_.find(SerialNumber);
 | 
								const auto Hint = Cache_.find(SerialNumber);
 | 
				
			||||||
			if (Hint == end(Cache_))
 | 
								if (Hint == end(Cache_))
 | 
				
			||||||
@@ -24,25 +24,25 @@ namespace OpenWifi {
 | 
				
			|||||||
			return Hint->second;
 | 
								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_);
 | 
								std::lock_guard G(Mutex_);
 | 
				
			||||||
			Cache_[SerialNumber] = Id;
 | 
								Cache_[SerialNumber] = Id;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	  private:
 | 
						  private:
 | 
				
			||||||
		std::recursive_mutex Mutex_;
 | 
							std::mutex Mutex_;
 | 
				
			||||||
		std::map<uint64_t, uint64_t> Cache_;
 | 
							std::map<uint64_t, uint64_t> Cache_;
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	inline uint64_t GetCurrentConfigurationID(uint64_t SerialNumber) {
 | 
						inline auto GetCurrentConfigurationID(std::uint64_t SerialNumber) {
 | 
				
			||||||
		return ConfigurationCache::instance().CurrentConfig(SerialNumber);
 | 
							return ConfigurationCache::instance()->GetCurrentConfig(SerialNumber);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	inline void SetCurrentConfigurationID(const std::string &SerialNumber, uint64_t ID) {
 | 
						inline void SetCurrentConfigurationID(const std::string &SerialNumber, std::uint64_t ID) {
 | 
				
			||||||
		return ConfigurationCache::instance().Add(Utils::SerialNumberToInt(SerialNumber), ID);
 | 
							return ConfigurationCache::instance()->SetCurrentConfig(Utils::SerialNumberToInt(SerialNumber), ID);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	inline void SetCurrentConfigurationID(uint64_t SerialNumber, uint64_t ID) {
 | 
						inline void SetCurrentConfigurationID(uint64_t SerialNumber, std::uint64_t ID) {
 | 
				
			||||||
		return ConfigurationCache::instance().Add(SerialNumber, ID);
 | 
							return ConfigurationCache::instance()->SetCurrentConfig(SerialNumber, ID);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
} // namespace OpenWifi
 | 
					} // namespace OpenWifi
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -49,7 +49,7 @@ namespace OpenWifi {
 | 
				
			|||||||
				SignatureManager(), AP_WS_Server(),
 | 
									SignatureManager(), AP_WS_Server(),
 | 
				
			||||||
				RegulatoryInfo(),
 | 
									RegulatoryInfo(),
 | 
				
			||||||
				RADIUSSessionTracker(),
 | 
									RADIUSSessionTracker(),
 | 
				
			||||||
				AP_WS_ConfigAutoUpgrader(),
 | 
								 	AP_WS_ConfigAutoUpgradeAgent(),
 | 
				
			||||||
				FirmwareRevisionCache()
 | 
									FirmwareRevisionCache()
 | 
				
			||||||
			});
 | 
								});
 | 
				
			||||||
		return &instance;
 | 
							return &instance;
 | 
				
			||||||
@@ -78,7 +78,7 @@ namespace OpenWifi {
 | 
				
			|||||||
			if (Id == DeviceType)
 | 
								if (Id == DeviceType)
 | 
				
			||||||
				return Type;
 | 
									return Type;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		return "AP";
 | 
							return Platforms::AP;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	void DaemonPostInitialization(Poco::Util::Application &self) {
 | 
						void DaemonPostInitialization(Poco::Util::Application &self) {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -21,7 +21,6 @@ namespace OpenWifi {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	void DeviceDashboard::Generate(GWObjects::Dashboard &D, Poco::Logger &Logger) {
 | 
						void DeviceDashboard::Generate(GWObjects::Dashboard &D, Poco::Logger &Logger) {
 | 
				
			||||||
		if (GeneratingDashboard_.load()) {
 | 
							if (GeneratingDashboard_.load()) {
 | 
				
			||||||
			// std::cout << "Trying to generate dashboard but already being generated" << std::endl;
 | 
					 | 
				
			||||||
			while (GeneratingDashboard_.load()) {
 | 
								while (GeneratingDashboard_.load()) {
 | 
				
			||||||
				Poco::Thread::trySleep(100);
 | 
									Poco::Thread::trySleep(100);
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
@@ -31,7 +30,6 @@ namespace OpenWifi {
 | 
				
			|||||||
			GeneratingDashboard_ = true;
 | 
								GeneratingDashboard_ = true;
 | 
				
			||||||
			ValidDashboard_ = false;
 | 
								ValidDashboard_ = false;
 | 
				
			||||||
			try {
 | 
								try {
 | 
				
			||||||
				// std::cout << "Generating dashboard." << std::endl;
 | 
					 | 
				
			||||||
				poco_information(Logger, "DASHBOARD: Generating a new dashboard.");
 | 
									poco_information(Logger, "DASHBOARD: Generating a new dashboard.");
 | 
				
			||||||
				GWObjects::Dashboard NewData;
 | 
									GWObjects::Dashboard NewData;
 | 
				
			||||||
				StorageService()->AnalyzeCommands(NewData.commands);
 | 
									StorageService()->AnalyzeCommands(NewData.commands);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -8,12 +8,12 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#pragma once
 | 
					#pragma once
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "Poco/Net/HTTPRequestHandler.h"
 | 
					#include <Poco/Net/HTTPRequestHandler.h>
 | 
				
			||||||
#include "Poco/Net/HTTPRequestHandlerFactory.h"
 | 
					#include <Poco/Net/HTTPRequestHandlerFactory.h>
 | 
				
			||||||
#include "Poco/Net/HTTPServer.h"
 | 
					#include <Poco/Net/HTTPServer.h>
 | 
				
			||||||
#include "Poco/Net/HTTPServerRequest.h"
 | 
					#include <Poco/Net/HTTPServerRequest.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "framework/SubSystemServer.h"
 | 
					#include <framework/SubSystemServer.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace OpenWifi {
 | 
					namespace OpenWifi {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -50,12 +50,22 @@ namespace OpenWifi {
 | 
				
			|||||||
	class DeviceConfigurationChangeKafkaEvent : public GWKafkaEvents {
 | 
						class DeviceConfigurationChangeKafkaEvent : public GWKafkaEvents {
 | 
				
			||||||
	  public:
 | 
						  public:
 | 
				
			||||||
		DeviceConfigurationChangeKafkaEvent(std::uint64_t serialNumber,
 | 
							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) {
 | 
								: GWKafkaEvents(serialNumber, "unit.configuration_change", timestamp), config_(config) {
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		~DeviceConfigurationChangeKafkaEvent() {
 | 
							~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();
 | 
								Send();
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1753,7 +1753,6 @@ namespace OpenWifi {
 | 
				
			|||||||
		nlohmann::json new_ie;
 | 
							nlohmann::json new_ie;
 | 
				
			||||||
		nlohmann::json content;
 | 
							nlohmann::json content;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// std::cout << BufferToHex(&data[0],data.size()) << std::endl;
 | 
					 | 
				
			||||||
		uint offset = 0;
 | 
							uint offset = 0;
 | 
				
			||||||
		auto sub_ie = data[offset++];
 | 
							auto sub_ie = data[offset++];
 | 
				
			||||||
		switch (sub_ie) {
 | 
							switch (sub_ie) {
 | 
				
			||||||
@@ -1788,7 +1787,6 @@ namespace OpenWifi {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
		try {
 | 
							try {
 | 
				
			||||||
			nlohmann::json D = nlohmann::json::parse(ofs.str());
 | 
								nlohmann::json D = nlohmann::json::parse(ofs.str());
 | 
				
			||||||
			// std::cout << "Start of parsing wifi" << std::endl;
 | 
					 | 
				
			||||||
			if (D.contains("status")) {
 | 
								if (D.contains("status")) {
 | 
				
			||||||
				auto Status = D["status"];
 | 
									auto Status = D["status"];
 | 
				
			||||||
				if (Status.contains("scan") && Status["scan"].is_array()) {
 | 
									if (Status.contains("scan") && Status["scan"].is_array()) {
 | 
				
			||||||
@@ -1803,8 +1801,6 @@ namespace OpenWifi {
 | 
				
			|||||||
									if (ie.contains("type") && ie.contains("data")) {
 | 
														if (ie.contains("type") && ie.contains("data")) {
 | 
				
			||||||
										uint64_t ie_type = ie["type"];
 | 
															uint64_t ie_type = ie["type"];
 | 
				
			||||||
										std::string ie_data = ie["data"];
 | 
															std::string ie_data = ie["data"];
 | 
				
			||||||
										// std::cout << "TYPE:" << ie_type << "  DATA:" << ie_data
 | 
					 | 
				
			||||||
										// << std::endl;
 | 
					 | 
				
			||||||
										auto data = Base64Decode2Vec(ie_data);
 | 
															auto data = Base64Decode2Vec(ie_data);
 | 
				
			||||||
										if (ie_type == ieee80211_eid::WLAN_EID_COUNTRY) {
 | 
															if (ie_type == ieee80211_eid::WLAN_EID_COUNTRY) {
 | 
				
			||||||
											new_ies.push_back(WFS_WLAN_EID_COUNTRY(data));
 | 
																new_ies.push_back(WFS_WLAN_EID_COUNTRY(data));
 | 
				
			||||||
@@ -1858,18 +1854,12 @@ namespace OpenWifi {
 | 
				
			|||||||
										} else if (ie_type == ieee80211_eid::WLAN_EID_EXTENSION) {
 | 
															} else if (ie_type == ieee80211_eid::WLAN_EID_EXTENSION) {
 | 
				
			||||||
											new_ies.push_back(WFS_WLAN_EID_EXTENSION(data));
 | 
																new_ies.push_back(WFS_WLAN_EID_EXTENSION(data));
 | 
				
			||||||
										} else {
 | 
															} else {
 | 
				
			||||||
											// std::cout
 | 
					 | 
				
			||||||
											//	<< "Skipping IE: no parsing available: " << ie_type
 | 
					 | 
				
			||||||
											//	<< std::endl;
 | 
					 | 
				
			||||||
											new_ies.push_back(ie);
 | 
																new_ies.push_back(ie);
 | 
				
			||||||
										}
 | 
															}
 | 
				
			||||||
									} else {
 | 
														} else {
 | 
				
			||||||
										// std::cout << "Skipping IE: no data and type" <<
 | 
					 | 
				
			||||||
										// std::endl;
 | 
					 | 
				
			||||||
										new_ies.push_back(ie);
 | 
															new_ies.push_back(ie);
 | 
				
			||||||
									}
 | 
														}
 | 
				
			||||||
								} catch (...) {
 | 
													} catch (...) {
 | 
				
			||||||
									// std::cout << "Skipping IE: exception" << std::endl;
 | 
					 | 
				
			||||||
									Logger.information(fmt::format("Error parsing IEs"));
 | 
														Logger.information(fmt::format("Error parsing IEs"));
 | 
				
			||||||
									new_ies.push_back(ie);
 | 
														new_ies.push_back(ie);
 | 
				
			||||||
								}
 | 
													}
 | 
				
			||||||
@@ -1877,7 +1867,6 @@ namespace OpenWifi {
 | 
				
			|||||||
							scan_entry["ies"] = new_ies;
 | 
												scan_entry["ies"] = new_ies;
 | 
				
			||||||
							ParsedScan.push_back(scan_entry);
 | 
												ParsedScan.push_back(scan_entry);
 | 
				
			||||||
						} else {
 | 
											} else {
 | 
				
			||||||
							// std::cout << "Skipping scan" << std::endl;
 | 
					 | 
				
			||||||
							ParsedScan.push_back(scan_entry);
 | 
												ParsedScan.push_back(scan_entry);
 | 
				
			||||||
						}
 | 
											}
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
@@ -1886,7 +1875,6 @@ namespace OpenWifi {
 | 
				
			|||||||
				}
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			Result << to_string(D);
 | 
								Result << to_string(D);
 | 
				
			||||||
			// std::cout << "End of parsing wifi" << std::endl;
 | 
					 | 
				
			||||||
			return true;
 | 
								return true;
 | 
				
			||||||
		} catch (const Poco::Exception &E) {
 | 
							} catch (const Poco::Exception &E) {
 | 
				
			||||||
			Logger.log(E);
 | 
								Logger.log(E);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -177,15 +177,6 @@ namespace OpenWifi {
 | 
				
			|||||||
		} else {
 | 
							} else {
 | 
				
			||||||
			session_hint->second->lastTransaction = Utils::Now();
 | 
								session_hint->second->lastTransaction = Utils::Now();
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
		if(ap_hint!=AccountingSessions_.end()) {
 | 
					 | 
				
			||||||
			std::cout << "Auth table:" << std::endl;
 | 
					 | 
				
			||||||
			for(const auto &session:ap_hint->second) {
 | 
					 | 
				
			||||||
				std::cout << Notification.SerialNumber_ << ":  Index: " << session.first << ": ID: " << session.second->accountingSessionId << "  MID:" << session.second->accountingMultiSessionId << std::endl;
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
*/
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	std::uint32_t GetUiInt32(const std::uint8_t *buf) {
 | 
						std::uint32_t GetUiInt32(const std::uint8_t *buf) {
 | 
				
			||||||
@@ -423,15 +414,15 @@ namespace OpenWifi {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	void RADIUSSessionTracker::DisconnectSession(const std::string &SerialNumber) {
 | 
						void RADIUSSessionTracker::DisconnectSession(const std::string &SerialNumber) {
 | 
				
			||||||
		poco_information(Logger(),fmt::format("{}: Disconnecting.", SerialNumber));
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		std::lock_guard		Guard(Mutex_);
 | 
							std::lock_guard		Guard(Mutex_);
 | 
				
			||||||
 | 
					 | 
				
			||||||
		auto hint = AccountingSessions_.find(SerialNumber);
 | 
							auto hint = AccountingSessions_.find(SerialNumber);
 | 
				
			||||||
		if(hint==end(AccountingSessions_)) {
 | 
							if(hint==end(AccountingSessions_)) {
 | 
				
			||||||
			return;
 | 
								return;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							poco_information(Logger(),fmt::format("{}: Disconnecting.", SerialNumber));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		//	we need to go through all sessions and send an accounting stop
 | 
							//	we need to go through all sessions and send an accounting stop
 | 
				
			||||||
		for(const auto &session:hint->second) {
 | 
							for(const auto &session:hint->second) {
 | 
				
			||||||
			poco_debug(Logger(), fmt::format("Stopping accounting for {}:{}", SerialNumber, session.first ));
 | 
								poco_debug(Logger(), fmt::format("Stopping accounting for {}:{}", SerialNumber, session.first ));
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -75,8 +75,10 @@ namespace OpenWifi {
 | 
				
			|||||||
				} else if ((Utils::Now() - LastKeepAlive) > Pool_.radsecKeepAlive) {
 | 
									} else if ((Utils::Now() - LastKeepAlive) > Pool_.radsecKeepAlive) {
 | 
				
			||||||
					RADIUS::RadiusOutputPacket P(Pool_.authConfig.servers[ServerIndex_].radsecSecret);
 | 
										RADIUS::RadiusOutputPacket P(Pool_.authConfig.servers[ServerIndex_].radsecSecret);
 | 
				
			||||||
					P.MakeStatusMessage(Pool_.authConfig.servers[ServerIndex_].name);
 | 
										P.MakeStatusMessage(Pool_.authConfig.servers[ServerIndex_].name);
 | 
				
			||||||
					poco_trace(Logger_, fmt::format("{}: Keep-Alive message.", Pool_.authConfig.servers[ServerIndex_].name));
 | 
										if(Type_!=GWObjects::RadiusEndpointType::generic) {
 | 
				
			||||||
					Socket_->sendBytes(P.Data(), P.Len());
 | 
											poco_trace(Logger_, fmt::format("{}: Keep-Alive message.", Pool_.authConfig.servers[ServerIndex_].name));
 | 
				
			||||||
 | 
											Socket_->sendBytes(P.Data(), P.Len());
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
					LastKeepAlive = Utils::Now();
 | 
										LastKeepAlive = Utils::Now();
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
				Poco::Thread::trySleep(2000);
 | 
									Poco::Thread::trySleep(2000);
 | 
				
			||||||
@@ -163,17 +165,16 @@ namespace OpenWifi {
 | 
				
			|||||||
									 fmt::format("Unknown packet: Type: {} (type={}) Length={}",
 | 
														 fmt::format("Unknown packet: Type: {} (type={}) Length={}",
 | 
				
			||||||
												 P.PacketType(), P.PacketTypeInt(), P.BufferLen()));
 | 
																	 P.PacketType(), P.PacketTypeInt(), P.BufferLen()));
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
 | 
										return;
 | 
				
			||||||
				} else {
 | 
									} else {
 | 
				
			||||||
					poco_warning(Logger_, "Invalid packet received. Resetting the connection.");
 | 
										poco_warning(Logger_, "Invalid packet received. Resetting the connection.");
 | 
				
			||||||
					Disconnect();
 | 
					 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			} catch (const Poco::Exception &E) {
 | 
								} catch (const Poco::Exception &E) {
 | 
				
			||||||
				Logger_.log(E);
 | 
									Logger_.log(E);
 | 
				
			||||||
				Disconnect();
 | 
					 | 
				
			||||||
			} catch (...) {
 | 
								} catch (...) {
 | 
				
			||||||
				Disconnect();
 | 
					 | 
				
			||||||
				poco_warning(Logger_, "Exception occurred. Resetting the connection.");
 | 
									poco_warning(Logger_, "Exception occurred. Resetting the connection.");
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
								Disconnect();
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		inline void
 | 
							inline void
 | 
				
			||||||
@@ -324,7 +325,7 @@ namespace OpenWifi {
 | 
				
			|||||||
				ofs << OpenRoamingRootCert;
 | 
									ofs << OpenRoamingRootCert;
 | 
				
			||||||
				ofs.close();
 | 
									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, ""));
 | 
										new Poco::Net::Context(Poco::Net::Context::TLS_CLIENT_USE, ""));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				if (Pool_.acctConfig.servers[ServerIndex_].allowSelfSigned) {
 | 
									if (Pool_.acctConfig.servers[ServerIndex_].allowSelfSigned) {
 | 
				
			||||||
@@ -430,7 +431,7 @@ namespace OpenWifi {
 | 
				
			|||||||
					DecodeFile(CaCertFiles_[CaCertFiles_.size() - 1]->path(), cert);
 | 
										DecodeFile(CaCertFiles_[CaCertFiles_.size() - 1]->path(), cert);
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				Poco::Net::Context::Ptr SecureContext =
 | 
									auto SecureContext =
 | 
				
			||||||
					Poco::AutoPtr<Poco::Net::Context>(new Poco::Net::Context(
 | 
										Poco::AutoPtr<Poco::Net::Context>(new Poco::Net::Context(
 | 
				
			||||||
						Poco::Net::Context::TLS_CLIENT_USE, KeyFile_.path(), CertFile_.path(), ""));
 | 
											Poco::Net::Context::TLS_CLIENT_USE, KeyFile_.path(), CertFile_.path(), ""));
 | 
				
			||||||
				if (Pool_.acctConfig.servers[ServerIndex_].allowSelfSigned) {
 | 
									if (Pool_.acctConfig.servers[ServerIndex_].allowSelfSigned) {
 | 
				
			||||||
@@ -498,7 +499,9 @@ namespace OpenWifi {
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		inline bool Connect_Generic() {
 | 
							inline bool Connect_Generic() {
 | 
				
			||||||
			if (TryAgain_) {
 | 
								poco_information(Logger_, fmt::format("Connecting {}", Pool_.name));
 | 
				
			||||||
 | 
								if (TryAgain_ && !Connected_) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				std::lock_guard G(LocalMutex_);
 | 
									std::lock_guard G(LocalMutex_);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				Poco::Net::SocketAddress AuthSockAddrV4(
 | 
									Poco::Net::SocketAddress AuthSockAddrV4(
 | 
				
			||||||
@@ -520,26 +523,6 @@ namespace OpenWifi {
 | 
				
			|||||||
					MicroServiceConfigGetInt("radius.proxy.coa.port", DEFAULT_RADIUS_CoA_PORT));
 | 
										MicroServiceConfigGetInt("radius.proxy.coa.port", DEFAULT_RADIUS_CoA_PORT));
 | 
				
			||||||
				CoASocketV4_ = std::make_unique<Poco::Net::DatagramSocket>(CoASockAddrV4, true, true);
 | 
									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(
 | 
									Reactor_.addEventHandler(
 | 
				
			||||||
					*AuthenticationSocketV4_,
 | 
										*AuthenticationSocketV4_,
 | 
				
			||||||
					Poco::NObserver<RADIUS_Destination, Poco::Net::ReadableNotification>(
 | 
										Poco::NObserver<RADIUS_Destination, Poco::Net::ReadableNotification>(
 | 
				
			||||||
@@ -551,7 +534,27 @@ namespace OpenWifi {
 | 
				
			|||||||
				Reactor_.addEventHandler(
 | 
									Reactor_.addEventHandler(
 | 
				
			||||||
					*CoASocketV4_, Poco::NObserver<RADIUS_Destination, Poco::Net::ReadableNotification>(
 | 
										*CoASocketV4_, Poco::NObserver<RADIUS_Destination, Poco::Net::ReadableNotification>(
 | 
				
			||||||
									   *this, &RADIUS_Destination::OnCoASocketReadable));
 | 
														   *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(
 | 
									Reactor_.addEventHandler(
 | 
				
			||||||
					*AuthenticationSocketV6_,
 | 
										*AuthenticationSocketV6_,
 | 
				
			||||||
					Poco::NObserver<RADIUS_Destination, Poco::Net::ReadableNotification>(
 | 
										Poco::NObserver<RADIUS_Destination, Poco::Net::ReadableNotification>(
 | 
				
			||||||
@@ -565,6 +568,7 @@ namespace OpenWifi {
 | 
				
			|||||||
					*CoASocketV6_, Poco::NObserver<RADIUS_Destination, Poco::Net::ReadableNotification>(
 | 
										*CoASocketV6_, Poco::NObserver<RADIUS_Destination, Poco::Net::ReadableNotification>(
 | 
				
			||||||
									   *this, &RADIUS_Destination::OnCoASocketReadable));
 | 
														   *this, &RADIUS_Destination::OnCoASocketReadable));
 | 
				
			||||||
*/
 | 
					*/
 | 
				
			||||||
 | 
									Connected_ = true;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			return true;
 | 
								return true;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
@@ -590,6 +594,8 @@ namespace OpenWifi {
 | 
				
			|||||||
			if (Connected_) {
 | 
								if (Connected_) {
 | 
				
			||||||
				std::lock_guard G(LocalMutex_);
 | 
									std::lock_guard G(LocalMutex_);
 | 
				
			||||||
				if(Type_==GWObjects::RadiusEndpointType::generic) {
 | 
									if(Type_==GWObjects::RadiusEndpointType::generic) {
 | 
				
			||||||
 | 
										poco_information(Logger_, fmt::format("Disconnecting {} generic server. Releasing all UDP resources.", Pool_.name));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
					if(AuthenticationSocketV4_) {
 | 
										if(AuthenticationSocketV4_) {
 | 
				
			||||||
						Reactor_.removeEventHandler(
 | 
											Reactor_.removeEventHandler(
 | 
				
			||||||
							*AuthenticationSocketV4_,
 | 
												*AuthenticationSocketV4_,
 | 
				
			||||||
@@ -617,7 +623,8 @@ namespace OpenWifi {
 | 
				
			|||||||
						CoASocketV4_.reset();
 | 
											CoASocketV4_.reset();
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*					if(AuthenticationSocketV6_) {
 | 
					/*
 | 
				
			||||||
 | 
					 					if(AuthenticationSocketV6_) {
 | 
				
			||||||
						Reactor_.removeEventHandler(
 | 
											Reactor_.removeEventHandler(
 | 
				
			||||||
							*AuthenticationSocketV6_,
 | 
												*AuthenticationSocketV6_,
 | 
				
			||||||
							Poco::NObserver<RADIUS_Destination, Poco::Net::ReadableNotification>(
 | 
												Poco::NObserver<RADIUS_Destination, Poco::Net::ReadableNotification>(
 | 
				
			||||||
@@ -646,7 +653,6 @@ namespace OpenWifi {
 | 
				
			|||||||
*/
 | 
					*/
 | 
				
			||||||
				} else {
 | 
									} else {
 | 
				
			||||||
					if(Socket_!=nullptr) {
 | 
										if(Socket_!=nullptr) {
 | 
				
			||||||
						std::lock_guard G(LocalMutex_);
 | 
					 | 
				
			||||||
						Reactor_.removeEventHandler(
 | 
											Reactor_.removeEventHandler(
 | 
				
			||||||
							*Socket_, Poco::NObserver<RADIUS_Destination, Poco::Net::ReadableNotification>(
 | 
												*Socket_, Poco::NObserver<RADIUS_Destination, Poco::Net::ReadableNotification>(
 | 
				
			||||||
										  *this, &RADIUS_Destination::onData));
 | 
															  *this, &RADIUS_Destination::onData));
 | 
				
			||||||
@@ -660,9 +666,9 @@ namespace OpenWifi {
 | 
				
			|||||||
						Socket_->close();
 | 
											Socket_->close();
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
 | 
									Connected_ = false;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			Connected_ = false;
 | 
								poco_information(Logger_, fmt::format("Disconnecting {}", Pool_.name));
 | 
				
			||||||
			poco_information(Logger_, "Disconnecting.");
 | 
					 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		static void DecodeFile(const std::string &filename, const std::string &s) {
 | 
							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> 		AuthenticationSocketV4_;
 | 
				
			||||||
		std::unique_ptr<Poco::Net::DatagramSocket> 		CoASocketV4_;
 | 
							std::unique_ptr<Poco::Net::DatagramSocket> 		CoASocketV4_;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*		std::unique_ptr<Poco::Net::DatagramSocket> 		CoASocketV6_;
 | 
					/*
 | 
				
			||||||
 | 
					 		std::unique_ptr<Poco::Net::DatagramSocket> 		CoASocketV6_;
 | 
				
			||||||
		std::unique_ptr<Poco::Net::DatagramSocket> 		AccountingSocketV6_;
 | 
							std::unique_ptr<Poco::Net::DatagramSocket> 		AccountingSocketV6_;
 | 
				
			||||||
		std::unique_ptr<Poco::Net::DatagramSocket> 		AuthenticationSocketV6_;
 | 
							std::unique_ptr<Poco::Net::DatagramSocket> 		AuthenticationSocketV6_;
 | 
				
			||||||
*/
 | 
					*/
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -25,9 +25,23 @@ namespace OpenWifi::RESTAPI_RPC {
 | 
				
			|||||||
		if (StorageService()->AddCommand(Cmd.SerialNumber, Cmd, Status)) {
 | 
							if (StorageService()->AddCommand(Cmd.SerialNumber, Cmd, Status)) {
 | 
				
			||||||
			Poco::JSON::Object RetObj;
 | 
								Poco::JSON::Object RetObj;
 | 
				
			||||||
			Cmd.to_json(RetObj);
 | 
								Cmd.to_json(RetObj);
 | 
				
			||||||
			if (Handler != nullptr)
 | 
								if (Handler == nullptr) {
 | 
				
			||||||
				return Handler->ReturnObject(RetObj);
 | 
									// nothing to process/return
 | 
				
			||||||
			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)
 | 
							if (Handler != nullptr)
 | 
				
			||||||
			return Handler->ReturnStatus(Poco::Net::HTTPResponse::HTTP_INTERNAL_SERVER_ERROR);
 | 
								return Handler->ReturnStatus(Poco::Net::HTTPResponse::HTTP_INTERNAL_SERVER_ERROR);
 | 
				
			||||||
@@ -40,8 +54,8 @@ namespace OpenWifi::RESTAPI_RPC {
 | 
				
			|||||||
						std::chrono::milliseconds WaitTimeInMs, Poco::JSON::Object *ObjectToReturn,
 | 
											std::chrono::milliseconds WaitTimeInMs, Poco::JSON::Object *ObjectToReturn,
 | 
				
			||||||
						RESTAPIHandler *Handler, Poco::Logger &Logger, bool Deferred) {
 | 
											RESTAPIHandler *Handler, Poco::Logger &Logger, bool Deferred) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		Logger.information(fmt::format("{},{}: New {} command. User={} Serial={}. ", Cmd.UUID,
 | 
							Logger.information(fmt::format("{},{}: New {} command. User={} Serial={} Details={}. ", Cmd.UUID,
 | 
				
			||||||
									   RPCID, Cmd.Command, Cmd.SubmittedBy, Cmd.SerialNumber));
 | 
														   RPCID, Cmd.Command, Cmd.SubmittedBy, Cmd.SerialNumber, Cmd.Details));
 | 
				
			||||||
		Cmd.Submitted = Utils::Now();
 | 
							Cmd.Submitted = Utils::Now();
 | 
				
			||||||
		Cmd.Executed = 0;
 | 
							Cmd.Executed = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -167,6 +181,20 @@ namespace OpenWifi::RESTAPI_RPC {
 | 
				
			|||||||
				Cmd.AttachType = "";
 | 
									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) {
 | 
								if (Cmd.ErrorCode == 0 && Cmd.Command == uCentralProtocol::CONFIGURE) {
 | 
				
			||||||
				//	we need to post a kafka event for this.
 | 
									//	we need to post a kafka event for this.
 | 
				
			||||||
				if (Params.has(uCentralProtocol::CONFIG) && Params.isObject(uCentralProtocol::CONFIG)) {
 | 
									if (Params.has(uCentralProtocol::CONFIG) && Params.isObject(uCentralProtocol::CONFIG)) {
 | 
				
			||||||
@@ -175,6 +203,7 @@ namespace OpenWifi::RESTAPI_RPC {
 | 
				
			|||||||
					DeviceConfigurationChangeKafkaEvent KEvent(
 | 
										DeviceConfigurationChangeKafkaEvent KEvent(
 | 
				
			||||||
						Utils::SerialNumberToInt(Cmd.SerialNumber), Utils::Now(),
 | 
											Utils::SerialNumberToInt(Cmd.SerialNumber), Utils::Now(),
 | 
				
			||||||
						Config);
 | 
											Config);
 | 
				
			||||||
 | 
											
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -63,7 +63,7 @@ namespace OpenWifi {
 | 
				
			|||||||
		poco_debug(Logger(), fmt::format("BLACKLIST-POST: {}", D.serialNumber));
 | 
							poco_debug(Logger(), fmt::format("BLACKLIST-POST: {}", D.serialNumber));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		Poco::toLowerInPlace(D.serialNumber);
 | 
							Poco::toLowerInPlace(D.serialNumber);
 | 
				
			||||||
		if (StorageService()->IsBlackListed(D.serialNumber)) {
 | 
							if (StorageService()->IsBlackListed(Utils::MACToInt(D.serialNumber))) {
 | 
				
			||||||
			return BadRequest(RESTAPI::Errors::SerialNumberExists);
 | 
								return BadRequest(RESTAPI::Errors::SerialNumberExists);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -56,17 +56,27 @@ namespace OpenWifi {
 | 
				
			|||||||
			return BadRequest(RESTAPI::Errors::InvalidJSONDocument);
 | 
								return BadRequest(RESTAPI::Errors::InvalidJSONDocument);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (DefConfig.Models.empty()) {
 | 
							if (DefConfig.models.empty()) {
 | 
				
			||||||
			return BadRequest(RESTAPI::Errors::ModelIDListCannotBeEmpty);
 | 
								return BadRequest(RESTAPI::Errors::ModelIDListCannotBeEmpty);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		std::vector<std::string> Error;
 | 
							DefConfig.platform = DefConfig.platform.empty() ? Platforms::AP : DefConfig.platform;
 | 
				
			||||||
		if (!ValidateUCentralConfiguration(DefConfig.Configuration, Error,
 | 
							if(DefConfig.platform != Platforms::AP && DefConfig.platform != Platforms::SWITCH) {
 | 
				
			||||||
										   GetBoolParameter("strict", false))) {
 | 
								return BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
 | 
				
			||||||
			return BadRequest(RESTAPI::Errors::ConfigBlockInvalid);
 | 
					 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		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)) {
 | 
							if (StorageService()->CreateDefaultConfiguration(Name, DefConfig)) {
 | 
				
			||||||
			return OK();
 | 
								return OK();
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
@@ -88,19 +98,31 @@ namespace OpenWifi {
 | 
				
			|||||||
			return NotFound();
 | 
								return NotFound();
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (!NewConfig.Configuration.empty()) {
 | 
							if(Existing.platform.empty()) {
 | 
				
			||||||
			std::vector<std::string> Error;
 | 
								Existing.platform = Platforms::AP;
 | 
				
			||||||
			if (!ValidateUCentralConfiguration(NewConfig.Configuration, Error,
 | 
					 | 
				
			||||||
											   GetBoolParameter("strict", false))) {
 | 
					 | 
				
			||||||
				return BadRequest(RESTAPI::Errors::ConfigBlockInvalid);
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			Existing.Configuration = NewConfig.Configuration;
 | 
					 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		Existing.LastModified = Utils::Now();
 | 
							if(ParsedBody_->has("platform")) {
 | 
				
			||||||
		AssignIfPresent(Obj, "description", Existing.Description);
 | 
								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"))
 | 
							if (Obj->has("modelIds"))
 | 
				
			||||||
			Existing.Models = NewConfig.Models;
 | 
								Existing.models = NewConfig.models;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (StorageService()->UpdateDefaultConfiguration(Name, Existing)) {
 | 
							if (StorageService()->UpdateDefaultConfiguration(Name, Existing)) {
 | 
				
			||||||
			GWObjects::DefaultConfiguration ModifiedConfig;
 | 
								GWObjects::DefaultConfiguration ModifiedConfig;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -87,7 +87,7 @@ namespace OpenWifi {
 | 
				
			|||||||
			poco_debug(
 | 
								poco_debug(
 | 
				
			||||||
				Logger_,
 | 
									Logger_,
 | 
				
			||||||
				fmt::format(
 | 
									fmt::format(
 | 
				
			||||||
					"Command rtty TID={} can proceed. Identified as {} and RPCID as {}. thr_id={}",
 | 
										"Command RTTY TID={} can proceed. Identified as {} and RPCID as {}. thr_id={}",
 | 
				
			||||||
					TransactionId_, UUID, RPC, Poco::Thread::current()->id()));
 | 
										TransactionId_, UUID, RPC, Poco::Thread::current()->id()));
 | 
				
			||||||
			return Rtty(UUID, RPC, 60000ms, Restrictions);
 | 
								return Rtty(UUID, RPC, 60000ms, Restrictions);
 | 
				
			||||||
		};
 | 
							};
 | 
				
			||||||
@@ -166,7 +166,11 @@ namespace OpenWifi {
 | 
				
			|||||||
		{APCommands::Commands::rrm, false, true, &RESTAPI_device_commandHandler::RRM, 60000ms},
 | 
							{APCommands::Commands::rrm, false, true, &RESTAPI_device_commandHandler::RRM, 60000ms},
 | 
				
			||||||
		{APCommands::Commands::certupdate, false, true, &RESTAPI_device_commandHandler::CertUpdate, 60000ms},
 | 
							{APCommands::Commands::certupdate, false, true, &RESTAPI_device_commandHandler::CertUpdate, 60000ms},
 | 
				
			||||||
		{APCommands::Commands::transfer, false, true, &RESTAPI_device_commandHandler::Transfer, 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},
 | 
				
			||||||
 | 
							{APCommands::Commands::fixedconfig, false, true, &RESTAPI_device_commandHandler::FixedConfig, 120000ms},
 | 
				
			||||||
 | 
							{APCommands::Commands::cablediagnostics, false, true, &RESTAPI_device_commandHandler::CableDiagnostics, 120000ms},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	void RESTAPI_device_commandHandler::DoPost() {
 | 
						void RESTAPI_device_commandHandler::DoPost() {
 | 
				
			||||||
@@ -653,13 +657,18 @@ namespace OpenWifi {
 | 
				
			|||||||
				return BadRequest(RESTAPI::Errors::SerialNumberMismatch);
 | 
									return BadRequest(RESTAPI::Errors::SerialNumberMismatch);
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								GWObjects::Device DeviceInfo;
 | 
				
			||||||
 | 
								if (!StorageService()->GetDevice(SerialNumber_, DeviceInfo)) {
 | 
				
			||||||
 | 
									return NotFound();
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
			auto Configuration =
 | 
								auto Configuration =
 | 
				
			||||||
				GetS(RESTAPI::Protocol::CONFIGURATION, Obj, uCentralProtocol::EMPTY_JSON_DOC);
 | 
									GetS(RESTAPI::Protocol::CONFIGURATION, Obj, uCentralProtocol::EMPTY_JSON_DOC);
 | 
				
			||||||
			std::vector<std::string> Error;
 | 
								std::string Error;
 | 
				
			||||||
			if (!ValidateUCentralConfiguration(Configuration, Error,
 | 
								if (!ValidateUCentralConfiguration(ConfigurationValidator::GetType(DeviceInfo.DeviceType),
 | 
				
			||||||
 | 
																   Configuration, Error,
 | 
				
			||||||
											   GetBoolParameter("strict", false))) {
 | 
																   GetBoolParameter("strict", false))) {
 | 
				
			||||||
				CallCanceled("CONFIGURE", CMD_UUID, CMD_RPC, RESTAPI::Errors::ConfigBlockInvalid);
 | 
									CallCanceled("CONFIGURE", CMD_UUID, CMD_RPC, RESTAPI::Errors::ConfigBlockInvalid);
 | 
				
			||||||
				return BadRequest(RESTAPI::Errors::ConfigBlockInvalid);
 | 
									return BadRequest(RESTAPI::Errors::ConfigBlockInvalid, Error);
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			auto When = GetWhen(Obj);
 | 
								auto When = GetWhen(Obj);
 | 
				
			||||||
@@ -685,9 +694,32 @@ namespace OpenWifi {
 | 
				
			|||||||
				Params.stringify(ParamStream);
 | 
									Params.stringify(ParamStream);
 | 
				
			||||||
				Cmd.Details = ParamStream.str();
 | 
									Cmd.Details = ParamStream.str();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									// retrieve capabilities and encode/compress parameters, if required
 | 
				
			||||||
 | 
									Poco::JSON::Object ConfigParams = Params;
 | 
				
			||||||
 | 
									GWObjects::Capabilities Caps;
 | 
				
			||||||
 | 
									if (StorageService()->GetDeviceCapabilities(SerialNumber_, Caps)) {
 | 
				
			||||||
 | 
										Poco::JSON::Object CapsJson;
 | 
				
			||||||
 | 
										Caps.to_json(CapsJson);
 | 
				
			||||||
 | 
										auto DeviceCaps = CapsJson.getObject(uCentralProtocol::CAPABILITIES);
 | 
				
			||||||
 | 
										if (DeviceCaps->has("compress_cmd") && DeviceCaps->get("compress_cmd")) {
 | 
				
			||||||
 | 
											// compressed command capability present and it is set, compress parameters
 | 
				
			||||||
 | 
											Poco::JSON::Object CompressedParams;
 | 
				
			||||||
 | 
											std::string CompressedBase64Data;
 | 
				
			||||||
 | 
											std::uint64_t UncompressedDataLen = ParamStream.str().length();
 | 
				
			||||||
 | 
											if (Utils::CompressAndEncodeBase64(ParamStream.str(), CompressedBase64Data)) {
 | 
				
			||||||
 | 
												// set compressed, base 64 encoded data and length of uncompressed data
 | 
				
			||||||
 | 
												CompressedParams.set(uCentralProtocol::COMPRESS_64, CompressedBase64Data);
 | 
				
			||||||
 | 
												CompressedParams.set(uCentralProtocol::COMPRESS_SZ, UncompressedDataLen);
 | 
				
			||||||
 | 
												ConfigParams = CompressedParams;
 | 
				
			||||||
 | 
												Cmd.Details.append(" (compressed: " + CompressedBase64Data + ")");
 | 
				
			||||||
 | 
											}
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				// AP_WS_Server()->SetPendingUUID(SerialNumber_, NewUUID);
 | 
									// AP_WS_Server()->SetPendingUUID(SerialNumber_, NewUUID);
 | 
				
			||||||
				RESTAPI_RPC::WaitForCommand(CMD_RPC, APCommands::Commands::configure, true,
 | 
									RESTAPI_RPC::WaitForCommand(CMD_RPC, APCommands::Commands::configure, true,
 | 
				
			||||||
												   Cmd, Params, *Request, *Response, timeout,
 | 
																	   Cmd, ConfigParams, *Request, *Response, timeout,
 | 
				
			||||||
												   nullptr, this, Logger_);
 | 
																	   nullptr, this, Logger_);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				if(!Cmd.Executed) {
 | 
									if(!Cmd.Executed) {
 | 
				
			||||||
@@ -1169,7 +1201,7 @@ namespace OpenWifi {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
				if (RTTYS_server()->UseInternal()) {
 | 
									if (RTTYS_server()->UseInternal()) {
 | 
				
			||||||
					std::uint64_t SN = Utils::SerialNumberToInt(SerialNumber_);
 | 
										std::uint64_t SN = Utils::SerialNumberToInt(SerialNumber_);
 | 
				
			||||||
					bool mTLS = AP_WS_Server()->DeviceRequiresSecureRtty(SN);
 | 
										bool mTLS = AP_WS_Server()->DeviceRequiresSecureRTTY(SN);
 | 
				
			||||||
					auto Hash =  Utils::ComputeHash(UserInfo_.webtoken.refresh_token_, Utils::Now());
 | 
										auto Hash =  Utils::ComputeHash(UserInfo_.webtoken.refresh_token_, Utils::Now());
 | 
				
			||||||
					Rtty.Token = Hash.substr(0, RTTY_DEVICE_TOKEN_LENGTH);
 | 
										Rtty.Token = Hash.substr(0, RTTY_DEVICE_TOKEN_LENGTH);
 | 
				
			||||||
					if (!RTTYS_server()->CreateEndPoint(Rtty.ConnectionId, Rtty.Token, Requester(),
 | 
										if (!RTTYS_server()->CreateEndPoint(Rtty.ConnectionId, Rtty.Token, Requester(),
 | 
				
			||||||
@@ -1401,9 +1433,9 @@ namespace OpenWifi {
 | 
				
			|||||||
		Cmd.WaitingForFile = 0;
 | 
							Cmd.WaitingForFile = 0;
 | 
				
			||||||
		Cmd.Status= "completed";
 | 
							Cmd.Status= "completed";
 | 
				
			||||||
		if(CommandManager()->FireAndForget(SerialNumber_, uCentralProtocol::RRM, Params)) {
 | 
							if(CommandManager()->FireAndForget(SerialNumber_, uCentralProtocol::RRM, Params)) {
 | 
				
			||||||
 | 
								Cmd.Status= "completed";
 | 
				
			||||||
			StorageService()->AddCommand(SerialNumber_, Cmd,
 | 
								StorageService()->AddCommand(SerialNumber_, Cmd,
 | 
				
			||||||
										 Storage::CommandExecutionType::COMMAND_COMPLETED);
 | 
															 Storage::CommandExecutionType::COMMAND_COMPLETED);
 | 
				
			||||||
			Cmd.Status= "completed";
 | 
					 | 
				
			||||||
			return OK();
 | 
								return OK();
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		Cmd.Status= "failed";	//	should never happen
 | 
							Cmd.Status= "failed";	//	should never happen
 | 
				
			||||||
@@ -1501,4 +1533,117 @@ 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_);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						void RESTAPI_device_commandHandler::FixedConfig(
 | 
				
			||||||
 | 
							const std::string &CMD_UUID, uint64_t CMD_RPC, std::chrono::milliseconds timeout,
 | 
				
			||||||
 | 
							[[maybe_unused]] const GWObjects::DeviceRestrictions &Restrictions) {
 | 
				
			||||||
 | 
							poco_debug(Logger_, fmt::format("FIXEDCONFIG({},{}): TID={} user={} serial={}", CMD_UUID, CMD_RPC,
 | 
				
			||||||
 | 
															TransactionId_, Requester(), SerialNumber_));
 | 
				
			||||||
 | 
							if(IsDeviceSimulated(SerialNumber_)) {
 | 
				
			||||||
 | 
								CallCanceled("FIXEDCONFIG", CMD_UUID, CMD_RPC, RESTAPI::Errors::SimulatedDeviceNotSupported);
 | 
				
			||||||
 | 
								return BadRequest(RESTAPI::Errors::SimulatedDeviceNotSupported);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							GWObjects::FixedConfig fixed_config;
 | 
				
			||||||
 | 
							if(!fixed_config.from_json(ParsedBody_)) {
 | 
				
			||||||
 | 
								return BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							GWObjects::CommandDetails Cmd;
 | 
				
			||||||
 | 
							Cmd.SerialNumber = SerialNumber_;
 | 
				
			||||||
 | 
							Cmd.SubmittedBy = Requester();
 | 
				
			||||||
 | 
							Cmd.UUID = CMD_UUID;
 | 
				
			||||||
 | 
							Cmd.Command = uCentralProtocol::FIXEDCONFIG;
 | 
				
			||||||
 | 
							std::ostringstream os;
 | 
				
			||||||
 | 
							ParsedBody_->stringify(os);
 | 
				
			||||||
 | 
							Cmd.Details = os.str();
 | 
				
			||||||
 | 
							Cmd.RunAt = 0;
 | 
				
			||||||
 | 
							Cmd.ErrorCode = 0;
 | 
				
			||||||
 | 
							Cmd.WaitingForFile = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							return RESTAPI_RPC::WaitForCommand(CMD_RPC, APCommands::Commands::fixedconfig, false, Cmd,
 | 
				
			||||||
 | 
															   *ParsedBody_, *Request, *Response, timeout, nullptr, this,
 | 
				
			||||||
 | 
															   Logger_);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						void RESTAPI_device_commandHandler::CableDiagnostics(
 | 
				
			||||||
 | 
							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("CABLEDIAGNOSTICS", CMD_UUID, CMD_RPC, RESTAPI::Errors::ACCESS_DENIED);
 | 
				
			||||||
 | 
								return UnAuthorized(RESTAPI::Errors::ACCESS_DENIED);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							poco_debug(Logger_, fmt::format("CABLEDIAGNOSTICS({},{}): TID={} user={} serial={}", CMD_UUID,
 | 
				
			||||||
 | 
															CMD_RPC, TransactionId_, Requester(), SerialNumber_));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if(IsDeviceSimulated(SerialNumber_)) {
 | 
				
			||||||
 | 
								CallCanceled("CABLEDIAGNOSTICS", CMD_UUID, CMD_RPC, RESTAPI::Errors::SimulatedDeviceNotSupported);
 | 
				
			||||||
 | 
								return BadRequest(RESTAPI::Errors::SimulatedDeviceNotSupported);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							GWObjects::CableDiagnostics	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::CABLEDIAGNOSTICS;
 | 
				
			||||||
 | 
							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::cablediagnostics, false, Cmd,
 | 
				
			||||||
 | 
															   *ParsedBody_, *Request, *Response, timeout, nullptr, this,
 | 
				
			||||||
 | 
															   Logger_);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
} // namespace OpenWifi
 | 
					} // namespace OpenWifi
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -68,6 +68,12 @@ namespace OpenWifi {
 | 
				
			|||||||
					const GWObjects::DeviceRestrictions &R);
 | 
										const GWObjects::DeviceRestrictions &R);
 | 
				
			||||||
		void Transfer(const std::string &UUID, uint64_t RPC, std::chrono::milliseconds timeout,
 | 
							void Transfer(const std::string &UUID, uint64_t RPC, std::chrono::milliseconds timeout,
 | 
				
			||||||
					const GWObjects::DeviceRestrictions &R);
 | 
										const GWObjects::DeviceRestrictions &R);
 | 
				
			||||||
 | 
							void PowerCycle(const std::string &UUID, uint64_t RPC, std::chrono::milliseconds timeout,
 | 
				
			||||||
 | 
										  const GWObjects::DeviceRestrictions &R);
 | 
				
			||||||
 | 
							void FixedConfig(const std::string &UUID, uint64_t RPC, std::chrono::milliseconds timeout,
 | 
				
			||||||
 | 
										  const GWObjects::DeviceRestrictions &R);
 | 
				
			||||||
 | 
							void CableDiagnostics(const std::string &UUID, uint64_t RPC, std::chrono::milliseconds timeout,
 | 
				
			||||||
 | 
										  const GWObjects::DeviceRestrictions &R);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		static auto PathName() {
 | 
							static auto PathName() {
 | 
				
			||||||
			return std::list<std::string>{"/api/v1/device/{serialNumber}/{command}"};
 | 
								return std::list<std::string>{"/api/v1/device/{serialNumber}/{command}"};
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -17,6 +17,8 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#include "RESTAPI_device_helper.h"
 | 
					#include "RESTAPI_device_helper.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "AP_WS_Server.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace OpenWifi {
 | 
					namespace OpenWifi {
 | 
				
			||||||
	void RESTAPI_device_handler::DoGet() {
 | 
						void RESTAPI_device_handler::DoGet() {
 | 
				
			||||||
		std::string SerialNumber = GetBinding(RESTAPI::Protocol::SERIALNUMBER, "");
 | 
							std::string SerialNumber = GetBinding(RESTAPI::Protocol::SERIALNUMBER, "");
 | 
				
			||||||
@@ -80,6 +82,9 @@ namespace OpenWifi {
 | 
				
			|||||||
			return OK();
 | 
								return OK();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		} else if (StorageService()->DeleteDevice(SerialNumber)) {
 | 
							} else if (StorageService()->DeleteDevice(SerialNumber)) {
 | 
				
			||||||
 | 
								if(AP_WS_Server()->Connected(Utils::SerialNumberToInt(SerialNumber))) {
 | 
				
			||||||
 | 
									AP_WS_Server()->Disconnect(Utils::SerialNumberToInt(SerialNumber));
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
			return OK();
 | 
								return OK();
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -101,9 +106,10 @@ namespace OpenWifi {
 | 
				
			|||||||
			}
 | 
								}
 | 
				
			||||||
			auto Config = Obj->get("configuration").toString();
 | 
								auto Config = Obj->get("configuration").toString();
 | 
				
			||||||
			Poco::JSON::Object Answer;
 | 
								Poco::JSON::Object Answer;
 | 
				
			||||||
			std::vector<std::string> Error;
 | 
								std::string Error;
 | 
				
			||||||
 | 
								auto DeviceType = Poco::toLower(GetParameter("deviceType", Platforms::AP));
 | 
				
			||||||
			auto Res =
 | 
								auto Res =
 | 
				
			||||||
				ValidateUCentralConfiguration(Config, Error, GetBoolParameter("strict", false));
 | 
									ValidateUCentralConfiguration(ConfigurationValidator::GetType(DeviceType),Config, Error, GetBoolParameter("strict", false));
 | 
				
			||||||
			Answer.set("valid", Res);
 | 
								Answer.set("valid", Res);
 | 
				
			||||||
			if (!Error.empty())
 | 
								if (!Error.empty())
 | 
				
			||||||
				Answer.set("error", Error);
 | 
									Answer.set("error", Error);
 | 
				
			||||||
@@ -123,12 +129,13 @@ namespace OpenWifi {
 | 
				
			|||||||
			return BadRequest(RESTAPI::Errors::SerialNumberMismatch);
 | 
								return BadRequest(RESTAPI::Errors::SerialNumberMismatch);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		std::vector<std::string> Error;
 | 
							std::string Error;
 | 
				
			||||||
		if (Device.Configuration.empty() ||
 | 
							if (Device.Configuration.empty() ||
 | 
				
			||||||
			(!Device.Configuration.empty() &&
 | 
								(!Device.Configuration.empty() &&
 | 
				
			||||||
			 !ValidateUCentralConfiguration(Device.Configuration, Error,
 | 
								 !ValidateUCentralConfiguration(ConfigurationValidator::GetType(Device.DeviceType),
 | 
				
			||||||
 | 
																Device.Configuration, Error,
 | 
				
			||||||
											GetBoolParameter("strict", false)))) {
 | 
																GetBoolParameter("strict", false)))) {
 | 
				
			||||||
			return BadRequest(RESTAPI::Errors::ConfigBlockInvalid);
 | 
								return BadRequest(RESTAPI::Errors::ConfigBlockInvalid, Error);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		for (auto &i : Device.Notes) {
 | 
							for (auto &i : Device.Notes) {
 | 
				
			||||||
@@ -169,10 +176,11 @@ namespace OpenWifi {
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (!NewDevice.Configuration.empty()) {
 | 
							if (!NewDevice.Configuration.empty()) {
 | 
				
			||||||
			std::vector<std::string> Error;
 | 
								std::string Error;
 | 
				
			||||||
			if (!ValidateUCentralConfiguration(NewDevice.Configuration, Error,
 | 
								if (!ValidateUCentralConfiguration(ConfigurationValidator::GetType(Existing.DeviceType),
 | 
				
			||||||
 | 
																   NewDevice.Configuration, Error,
 | 
				
			||||||
											   GetBoolParameter("strict", false))) {
 | 
																   GetBoolParameter("strict", false))) {
 | 
				
			||||||
				return BadRequest(RESTAPI::Errors::ConfigBlockInvalid);
 | 
									return BadRequest(RESTAPI::Errors::ConfigBlockInvalid, Error);
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			Config::Config NewConfig(NewDevice.Configuration);
 | 
								Config::Config NewConfig(NewDevice.Configuration);
 | 
				
			||||||
			uint64_t NewConfigUUID = Utils::Now();
 | 
								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 serialOnly = GetBoolParameter(RESTAPI::Protocol::SERIALONLY, false);
 | 
				
			||||||
		auto deviceWithStatus = GetBoolParameter(RESTAPI::Protocol::DEVICEWITHSTATUS, false);
 | 
							auto deviceWithStatus = GetBoolParameter(RESTAPI::Protocol::DEVICEWITHSTATUS, false);
 | 
				
			||||||
		auto completeInfo = GetBoolParameter("completeInfo", 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;
 | 
							Poco::JSON::Object RetObj;
 | 
				
			||||||
		if (!QB_.Select.empty()) {
 | 
							if (!QB_.Select.empty()) {
 | 
				
			||||||
			Poco::JSON::Array Objects;
 | 
								Poco::JSON::Array Objects;
 | 
				
			||||||
			for (auto &i : SelectedRecords()) {
 | 
								for (auto &i : SelectedRecords()) {
 | 
				
			||||||
				auto SerialNumber = i;
 | 
									auto &SerialNumber = i;
 | 
				
			||||||
				if (!Utils::ValidSerialNumber(i))
 | 
									if (!Utils::ValidSerialNumber(i))
 | 
				
			||||||
					continue;
 | 
										continue;
 | 
				
			||||||
				GWObjects::Device D;
 | 
									GWObjects::Device D;
 | 
				
			||||||
@@ -116,14 +125,14 @@ namespace OpenWifi {
 | 
				
			|||||||
			else
 | 
								else
 | 
				
			||||||
				RetObj.set(RESTAPI::Protocol::DEVICES, Objects);
 | 
									RetObj.set(RESTAPI::Protocol::DEVICES, Objects);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		} else if (QB_.CountOnly == true) {
 | 
							} else if (QB_.CountOnly) {
 | 
				
			||||||
			uint64_t Count = 0;
 | 
								uint64_t Count = 0;
 | 
				
			||||||
			if (StorageService()->GetDeviceCount(Count)) {
 | 
								if (StorageService()->GetDeviceCount(Count, platform, includeProvisioned)) {
 | 
				
			||||||
				return ReturnCountOnly(Count);
 | 
									return ReturnCountOnly(Count);
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		} else if (serialOnly) {
 | 
							} else if (serialOnly) {
 | 
				
			||||||
			std::vector<std::string> SerialNumbers;
 | 
								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;
 | 
								Poco::JSON::Array Objects;
 | 
				
			||||||
			for (const auto &i : SerialNumbers) {
 | 
								for (const auto &i : SerialNumbers) {
 | 
				
			||||||
				Objects.add(i);
 | 
									Objects.add(i);
 | 
				
			||||||
@@ -141,7 +150,7 @@ namespace OpenWifi {
 | 
				
			|||||||
			RetObj.set("serialNumbers", Objects);
 | 
								RetObj.set("serialNumbers", Objects);
 | 
				
			||||||
		} else {
 | 
							} else {
 | 
				
			||||||
			std::vector<GWObjects::Device> Devices;
 | 
								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;
 | 
								Poco::JSON::Array Objects;
 | 
				
			||||||
			for (const auto &i : Devices) {
 | 
								for (const auto &i : Devices) {
 | 
				
			||||||
				Poco::JSON::Object Obj;
 | 
									Poco::JSON::Object Obj;
 | 
				
			||||||
@@ -175,10 +184,12 @@ namespace OpenWifi {
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if(GetBoolParameter("simulatedDevices",false)) {
 | 
							if(GetBoolParameter("simulatedDevices",false)) {
 | 
				
			||||||
			if(StorageService()->DeleteSimulatedDevice("")) {
 | 
								auto F = []() ->void {
 | 
				
			||||||
				return OK();
 | 
									StorageService()->DeleteSimulatedDevice("");
 | 
				
			||||||
			}
 | 
								};
 | 
				
			||||||
			return NotFound();
 | 
								std::thread T(F);
 | 
				
			||||||
 | 
								T.detach();
 | 
				
			||||||
 | 
								return OK();
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if(!QB_.Select.empty() && !Utils::ValidSerialNumbers(QB_.Select)) {
 | 
							if(!QB_.Select.empty() && !Utils::ValidSerialNumbers(QB_.Select)) {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -22,9 +22,15 @@ namespace OpenWifi {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
		std::string FileType;
 | 
							std::string FileType;
 | 
				
			||||||
		std::string FileContent;
 | 
							std::string FileContent;
 | 
				
			||||||
		if (!StorageService()->GetAttachedFileContent(UUID, SerialNumber, FileContent, FileType) || FileContent.empty()) {
 | 
							int WaitingForFile = 0;
 | 
				
			||||||
 | 
							if (!StorageService()->GetAttachedFileContent(UUID, SerialNumber, FileContent, FileType, WaitingForFile) && !WaitingForFile) {
 | 
				
			||||||
			return NotFound();
 | 
								return NotFound();
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
							else if (WaitingForFile) {
 | 
				
			||||||
 | 
								// waiting for file to be uploaded, return Accepted
 | 
				
			||||||
 | 
								return Accepted();
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (FileType == "pcap") {
 | 
							if (FileType == "pcap") {
 | 
				
			||||||
			SendFileContent(FileContent, "application/vnd.tcpdump.pcap", UUID + ".pcap");
 | 
								SendFileContent(FileContent, "application/vnd.tcpdump.pcap", UUID + ".pcap");
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -8,7 +8,7 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#pragma once
 | 
					#pragma once
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "framework/RESTAPI_Handler.h"
 | 
					#include <framework/RESTAPI_Handler.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace OpenWifi {
 | 
					namespace OpenWifi {
 | 
				
			||||||
	class RESTAPI_file : public RESTAPIHandler {
 | 
						class RESTAPI_file : public RESTAPIHandler {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -23,8 +23,8 @@ namespace OpenWifi {
 | 
				
			|||||||
	void RESTAPI_script_handler::DoDelete() {
 | 
						void RESTAPI_script_handler::DoDelete() {
 | 
				
			||||||
		std::string UUID = GetBinding("uuid", "");
 | 
							std::string UUID = GetBinding("uuid", "");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (UserInfo_.userinfo.userRole != SecurityObjects::ROOT) {
 | 
							if (!UserInfo_.userinfo.userPermissions[SecurityObjects::PM_SCRIPTS_GW][SecurityObjects::PT_DELETE]) {
 | 
				
			||||||
			return BadRequest(RESTAPI::Errors::ACCESS_DENIED);
 | 
								return UnAuthorized(RESTAPI::Errors::ACCESS_DENIED);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (UUID.empty()) {
 | 
							if (UUID.empty()) {
 | 
				
			||||||
@@ -40,8 +40,8 @@ namespace OpenWifi {
 | 
				
			|||||||
	void RESTAPI_script_handler::DoPost() {
 | 
						void RESTAPI_script_handler::DoPost() {
 | 
				
			||||||
		std::string UUID = GetBinding("uuid", "");
 | 
							std::string UUID = GetBinding("uuid", "");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (UserInfo_.userinfo.userRole != SecurityObjects::ROOT) {
 | 
							if (!UserInfo_.userinfo.userPermissions[SecurityObjects::PM_SCRIPTS_GW][SecurityObjects::PT_CREATE]) {
 | 
				
			||||||
			return BadRequest(RESTAPI::Errors::ACCESS_DENIED);
 | 
								return UnAuthorized(RESTAPI::Errors::ACCESS_DENIED);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (UUID.empty()) {
 | 
							if (UUID.empty()) {
 | 
				
			||||||
@@ -86,8 +86,8 @@ namespace OpenWifi {
 | 
				
			|||||||
	void RESTAPI_script_handler::DoPut() {
 | 
						void RESTAPI_script_handler::DoPut() {
 | 
				
			||||||
		std::string UUID = GetBinding("uuid", "");
 | 
							std::string UUID = GetBinding("uuid", "");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (UserInfo_.userinfo.userRole != SecurityObjects::ROOT) {
 | 
							if (!UserInfo_.userinfo.userPermissions[SecurityObjects::PM_SCRIPTS_GW][SecurityObjects::PT_UPDATE]) {
 | 
				
			||||||
			return BadRequest(RESTAPI::Errors::ACCESS_DENIED);
 | 
								return UnAuthorized(RESTAPI::Errors::ACCESS_DENIED);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (UUID.empty()) {
 | 
							if (UUID.empty()) {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -7,6 +7,7 @@
 | 
				
			|||||||
#include "RESTAPI_ProvObjects.h"
 | 
					#include "RESTAPI_ProvObjects.h"
 | 
				
			||||||
#include "framework/utils.h"
 | 
					#include "framework/utils.h"
 | 
				
			||||||
#include <vector>
 | 
					#include <vector>
 | 
				
			||||||
 | 
					#include "framework/ow_constants.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace OpenWifi {
 | 
					namespace OpenWifi {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -12,6 +12,7 @@
 | 
				
			|||||||
#include "Daemon.h"
 | 
					#include "Daemon.h"
 | 
				
			||||||
#ifdef TIP_GATEWAY_SERVICE
 | 
					#ifdef TIP_GATEWAY_SERVICE
 | 
				
			||||||
#include "AP_WS_Server.h"
 | 
					#include "AP_WS_Server.h"
 | 
				
			||||||
 | 
					#include "StorageService.h"
 | 
				
			||||||
#include "CapabilitiesCache.h"
 | 
					#include "CapabilitiesCache.h"
 | 
				
			||||||
#include "RADIUSSessionTracker.h"
 | 
					#include "RADIUSSessionTracker.h"
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
@@ -29,8 +30,8 @@ namespace OpenWifi::GWObjects {
 | 
				
			|||||||
	void Device::to_json(Poco::JSON::Object &Obj) const {
 | 
						void Device::to_json(Poco::JSON::Object &Obj) const {
 | 
				
			||||||
		field_to_json(Obj, "serialNumber", SerialNumber);
 | 
							field_to_json(Obj, "serialNumber", SerialNumber);
 | 
				
			||||||
#ifdef TIP_GATEWAY_SERVICE
 | 
					#ifdef TIP_GATEWAY_SERVICE
 | 
				
			||||||
		field_to_json(Obj, "deviceType", CapabilitiesCache::instance()->GetPlatform(Compatible));
 | 
							field_to_json(Obj, "deviceType", StorageService()->GetPlatform(SerialNumber));
 | 
				
			||||||
		field_to_json(Obj, "hasRADIUSSessions", RADIUSSessionTracker()->HasSessions(SerialNumber));
 | 
							field_to_json(Obj, "blackListed", StorageService()->IsBlackListed(Utils::MACToInt(SerialNumber)));
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
		field_to_json(Obj, "macAddress", MACAddress);
 | 
							field_to_json(Obj, "macAddress", MACAddress);
 | 
				
			||||||
		field_to_json(Obj, "manufacturer", Manufacturer);
 | 
							field_to_json(Obj, "manufacturer", Manufacturer);
 | 
				
			||||||
@@ -68,9 +69,14 @@ namespace OpenWifi::GWObjects {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#ifdef TIP_GATEWAY_SERVICE
 | 
					#ifdef TIP_GATEWAY_SERVICE
 | 
				
			||||||
		ConnectionState ConState;
 | 
							ConnectionState ConState;
 | 
				
			||||||
 | 
					#ifdef USE_MEDUSA_CLIENT
 | 
				
			||||||
		if (AP_WS_Server()->GetState(SerialNumber, ConState)) {
 | 
					        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);
 | 
								ConState.to_json(SerialNumber,Obj);
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
		} else {
 | 
							} else {
 | 
				
			||||||
			field_to_json(Obj, "ipAddress", "");
 | 
								field_to_json(Obj, "ipAddress", "");
 | 
				
			||||||
			field_to_json(Obj, "txBytes", (uint64_t)0);
 | 
								field_to_json(Obj, "txBytes", (uint64_t)0);
 | 
				
			||||||
@@ -166,14 +172,17 @@ namespace OpenWifi::GWObjects {
 | 
				
			|||||||
		field_to_json(Obj, "recorded", Recorded);
 | 
							field_to_json(Obj, "recorded", Recorded);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	void DefaultConfiguration::to_json(Poco::JSON::Object &Obj) const {
 | 
					    bool HealthCheck::from_json(const Poco::JSON::Object::Ptr &Obj) {
 | 
				
			||||||
		EmbedDocument("configuration", Obj, Configuration);
 | 
					        try {
 | 
				
			||||||
		field_to_json(Obj, "name", Name);
 | 
					            field_from_json(Obj, "UUID", UUID);
 | 
				
			||||||
		field_to_json(Obj, "modelIds", Models);
 | 
					            field_from_json(Obj, "sanity", Sanity);
 | 
				
			||||||
		field_to_json(Obj, "description", Description);
 | 
					            field_from_json(Obj, "recorded", Recorded);
 | 
				
			||||||
		field_to_json(Obj, "created", Created);
 | 
					            return true;
 | 
				
			||||||
		field_to_json(Obj, "lastModified", LastModified);
 | 
					        } catch(...) {
 | 
				
			||||||
	}
 | 
					
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return false;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	void DefaultFirmware::to_json(Poco::JSON::Object &Obj) const {
 | 
						void DefaultFirmware::to_json(Poco::JSON::Object &Obj) const {
 | 
				
			||||||
		field_to_json(Obj, "deviceType", deviceType);
 | 
							field_to_json(Obj, "deviceType", deviceType);
 | 
				
			||||||
@@ -222,12 +231,25 @@ namespace OpenWifi::GWObjects {
 | 
				
			|||||||
		field_to_json(Obj, "deferred", deferred);
 | 
							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) {
 | 
						bool DefaultConfiguration::from_json(const Poco::JSON::Object::Ptr &Obj) {
 | 
				
			||||||
		try {
 | 
							try {
 | 
				
			||||||
			field_from_json(Obj, "name", Name);
 | 
								field_from_json(Obj, "configuration", configuration);
 | 
				
			||||||
			field_from_json(Obj, "configuration", Configuration);
 | 
								field_from_json(Obj, "name", name);
 | 
				
			||||||
			field_from_json(Obj, "modelIds", Models);
 | 
								field_from_json(Obj, "modelIds", models);
 | 
				
			||||||
			field_from_json(Obj, "description", Description);
 | 
								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;
 | 
								return true;
 | 
				
			||||||
		} catch (const Poco::Exception &E) {
 | 
							} catch (const Poco::Exception &E) {
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
@@ -273,16 +295,14 @@ namespace OpenWifi::GWObjects {
 | 
				
			|||||||
		field_to_json(Obj, "started", started);
 | 
							field_to_json(Obj, "started", started);
 | 
				
			||||||
		field_to_json(Obj, "sessionId", sessionId);
 | 
							field_to_json(Obj, "sessionId", sessionId);
 | 
				
			||||||
		field_to_json(Obj, "connectionCompletionTime", connectionCompletionTime);
 | 
							field_to_json(Obj, "connectionCompletionTime", connectionCompletionTime);
 | 
				
			||||||
		field_to_json(Obj, "totalConnectionTime", Utils::Now() - started);
 | 
							field_to_json(Obj, "totalConnectionTime", started ? Utils::Now() - started : 0);
 | 
				
			||||||
		field_to_json(Obj, "certificateExpiryDate", certificateExpiryDate);
 | 
							field_to_json(Obj, "certificateExpiryDate", certificateExpiryDate);
 | 
				
			||||||
		field_to_json(Obj, "connectReason", connectReason);
 | 
							field_to_json(Obj, "connectReason", connectReason);
 | 
				
			||||||
 | 
							field_to_json(Obj, "uptime", uptime);
 | 
				
			||||||
 | 
					        field_to_json(Obj, "compatible", Compatible);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef TIP_GATEWAY_SERVICE
 | 
					#ifdef TIP_GATEWAY_SERVICE
 | 
				
			||||||
		hasRADIUSSessions = RADIUSSessionTracker()->HasSessions(SerialNumber);
 | 
							hasRADIUSSessions = RADIUSSessionTracker()->HasSessions(SerialNumber);
 | 
				
			||||||
		AP_WS_Server()->ExtendedAttributes(SerialNumber, hasGPS, sanity,
 | 
					 | 
				
			||||||
										   memoryUsed,
 | 
					 | 
				
			||||||
										   load,
 | 
					 | 
				
			||||||
										   temperature);
 | 
					 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
		field_to_json(Obj, "hasRADIUSSessions", hasRADIUSSessions );
 | 
							field_to_json(Obj, "hasRADIUSSessions", hasRADIUSSessions );
 | 
				
			||||||
		field_to_json(Obj, "hasGPS", hasGPS);
 | 
							field_to_json(Obj, "hasGPS", hasGPS);
 | 
				
			||||||
@@ -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 {
 | 
						void DeviceConnectionStatistics::to_json(Poco::JSON::Object &Obj) const {
 | 
				
			||||||
		field_to_json(Obj, "averageConnectionTime", averageConnectionTime);
 | 
							field_to_json(Obj, "averageConnectionTime", averageConnectionTime);
 | 
				
			||||||
		field_to_json(Obj, "connectedDevices", connectedDevices);
 | 
							field_to_json(Obj, "connectedDevices", connectedDevices);
 | 
				
			||||||
@@ -711,7 +770,7 @@ namespace OpenWifi::GWObjects {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	bool DeviceCertificateUpdateRequest::from_json(const Poco::JSON::Object::Ptr &Obj) {
 | 
						bool DeviceCertificateUpdateRequest::from_json(const Poco::JSON::Object::Ptr &Obj) {
 | 
				
			||||||
		try {
 | 
							try {
 | 
				
			||||||
			field_from_json(Obj, "serialNumber", serialNumber);
 | 
								field_from_json(Obj, "serial", serialNumber);
 | 
				
			||||||
			field_from_json(Obj, "encodedCertificate", encodedCertificate);
 | 
								field_from_json(Obj, "encodedCertificate", encodedCertificate);
 | 
				
			||||||
			return true;
 | 
								return true;
 | 
				
			||||||
		} catch (const Poco::Exception &E) {
 | 
							} catch (const Poco::Exception &E) {
 | 
				
			||||||
@@ -719,4 +778,45 @@ namespace OpenWifi::GWObjects {
 | 
				
			|||||||
		return false;
 | 
							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;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						bool FixedConfig::from_json(const Poco::JSON::Object::Ptr &Obj) {
 | 
				
			||||||
 | 
							try {
 | 
				
			||||||
 | 
								field_from_json(Obj, "serial", serialNumber);
 | 
				
			||||||
 | 
								field_from_json(Obj, "country", country);
 | 
				
			||||||
 | 
								return true;
 | 
				
			||||||
 | 
							} catch (const Poco::Exception &E) {
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return false;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						bool CableDiagnostics::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
 | 
					} // namespace OpenWifi::GWObjects
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -49,8 +49,11 @@ namespace OpenWifi::GWObjects {
 | 
				
			|||||||
		std::double_t load=0.0;
 | 
							std::double_t load=0.0;
 | 
				
			||||||
		std::double_t temperature=0.0;
 | 
							std::double_t temperature=0.0;
 | 
				
			||||||
		std::string 	connectReason;
 | 
							std::string 	connectReason;
 | 
				
			||||||
 | 
							std::uint64_t 	uptime=0;
 | 
				
			||||||
 | 
					        std::uint64_t 	totalConnectionTime=0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		void to_json(const std::string &SerialNumber, Poco::JSON::Object &Obj) ;
 | 
							void to_json(const std::string &SerialNumber, Poco::JSON::Object &Obj) ;
 | 
				
			||||||
 | 
					        bool from_json(const Poco::JSON::Object::Ptr &Obj);
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	struct DeviceRestrictionsKeyInfo {
 | 
						struct DeviceRestrictionsKeyInfo {
 | 
				
			||||||
@@ -112,6 +115,7 @@ namespace OpenWifi::GWObjects {
 | 
				
			|||||||
		std::uint64_t 	lastRecordedContact=0;
 | 
							std::uint64_t 	lastRecordedContact=0;
 | 
				
			||||||
		std::uint64_t 	certificateExpiryDate = 0;
 | 
							std::uint64_t 	certificateExpiryDate = 0;
 | 
				
			||||||
		std::string 	connectReason;
 | 
							std::string 	connectReason;
 | 
				
			||||||
 | 
							bool			blackListed=false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		void to_json(Poco::JSON::Object &Obj) const;
 | 
							void to_json(Poco::JSON::Object &Obj) const;
 | 
				
			||||||
		void to_json_with_status(Poco::JSON::Object &Obj) const;
 | 
							void to_json_with_status(Poco::JSON::Object &Obj) const;
 | 
				
			||||||
@@ -137,13 +141,15 @@ namespace OpenWifi::GWObjects {
 | 
				
			|||||||
	};
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	struct HealthCheck {
 | 
						struct HealthCheck {
 | 
				
			||||||
		std::string SerialNumber;
 | 
					        std::string SerialNumber;
 | 
				
			||||||
		uint64_t UUID = 0;
 | 
					        uint64_t UUID = 0;
 | 
				
			||||||
		std::string Data;
 | 
					        std::string Data;
 | 
				
			||||||
		uint64_t Recorded = 0;
 | 
					        uint64_t Recorded = 0;
 | 
				
			||||||
		uint64_t Sanity = 0;
 | 
					        uint64_t Sanity = 0;
 | 
				
			||||||
		void to_json(Poco::JSON::Object &Obj) const;
 | 
					
 | 
				
			||||||
	};
 | 
					        void to_json(Poco::JSON::Object &Obj) const;
 | 
				
			||||||
 | 
					        bool from_json(const Poco::JSON::Object::Ptr &Obj);
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	struct Capabilities {
 | 
						struct Capabilities {
 | 
				
			||||||
		std::string Capabilities;
 | 
							std::string Capabilities;
 | 
				
			||||||
@@ -174,12 +180,13 @@ namespace OpenWifi::GWObjects {
 | 
				
			|||||||
	};
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	struct DefaultConfiguration {
 | 
						struct DefaultConfiguration {
 | 
				
			||||||
		std::string Name;
 | 
							std::string name;
 | 
				
			||||||
		std::string Configuration;
 | 
							std::string configuration;
 | 
				
			||||||
		Types::StringVec Models;
 | 
							Types::StringVec models;
 | 
				
			||||||
		std::string Description;
 | 
							std::string description;
 | 
				
			||||||
		uint64_t Created;
 | 
							uint64_t created;
 | 
				
			||||||
		uint64_t LastModified;
 | 
							uint64_t lastModified;
 | 
				
			||||||
 | 
							std::string platform;
 | 
				
			||||||
		void to_json(Poco::JSON::Object &Obj) const;
 | 
							void to_json(Poco::JSON::Object &Obj) const;
 | 
				
			||||||
		bool from_json(const Poco::JSON::Object::Ptr &Obj);
 | 
							bool from_json(const Poco::JSON::Object::Ptr &Obj);
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
@@ -513,4 +520,31 @@ namespace OpenWifi::GWObjects {
 | 
				
			|||||||
		bool from_json(const Poco::JSON::Object::Ptr &Obj);
 | 
							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);
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
						struct FixedConfig {
 | 
				
			||||||
 | 
							std::string 	serialNumber;
 | 
				
			||||||
 | 
							std::string 	country;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							bool from_json(const Poco::JSON::Object::Ptr &Obj);
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
						struct CableDiagnostics {
 | 
				
			||||||
 | 
							std::string 	serialNumber;
 | 
				
			||||||
 | 
							std::uint64_t 	when;
 | 
				
			||||||
 | 
							std::vector<std::string> ports;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							bool from_json(const Poco::JSON::Object::Ptr &Obj);
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
} // namespace OpenWifi::GWObjects
 | 
					} // namespace OpenWifi::GWObjects
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -587,6 +587,9 @@ namespace OpenWifi::ProvObjects {
 | 
				
			|||||||
		field_to_json(Obj, "locale", locale);
 | 
							field_to_json(Obj, "locale", locale);
 | 
				
			||||||
		field_to_json(Obj, "realMacAddress", realMacAddress);
 | 
							field_to_json(Obj, "realMacAddress", realMacAddress);
 | 
				
			||||||
		field_to_json(Obj, "doNotAllowOverrides", doNotAllowOverrides);
 | 
							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) {
 | 
						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, "locale", locale);
 | 
				
			||||||
			field_from_json(Obj, "realMacAddress", realMacAddress);
 | 
								field_from_json(Obj, "realMacAddress", realMacAddress);
 | 
				
			||||||
			field_from_json(Obj, "doNotAllowOverrides", doNotAllowOverrides);
 | 
								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;
 | 
								return true;
 | 
				
			||||||
		} catch (...) {
 | 
							} catch (...) {
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -490,9 +490,11 @@ namespace OpenWifi::ProvObjects {
 | 
				
			|||||||
        std::string locale;
 | 
					        std::string locale;
 | 
				
			||||||
        std::string realMacAddress;
 | 
					        std::string realMacAddress;
 | 
				
			||||||
        bool doNotAllowOverrides = false;
 | 
					        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;
 | 
					        void to_json(Poco::JSON::Object &Obj) const;
 | 
				
			||||||
 | 
					 | 
				
			||||||
        bool from_json(const Poco::JSON::Object::Ptr &Obj);
 | 
					        bool from_json(const Poco::JSON::Object::Ptr &Obj);
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -12,6 +12,8 @@
 | 
				
			|||||||
#include "RESTAPI_SecurityObjects.h"
 | 
					#include "RESTAPI_SecurityObjects.h"
 | 
				
			||||||
#include "framework/RESTAPI_utils.h"
 | 
					#include "framework/RESTAPI_utils.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <stdlib.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
using OpenWifi::RESTAPI_utils::field_from_json;
 | 
					using OpenWifi::RESTAPI_utils::field_from_json;
 | 
				
			||||||
using OpenWifi::RESTAPI_utils::field_to_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, "oauthUserInfo", oauthUserInfo);
 | 
				
			||||||
		field_to_json(Obj, "modified", modified);
 | 
							field_to_json(Obj, "modified", modified);
 | 
				
			||||||
		field_to_json(Obj, "signingUp", signingUp);
 | 
							field_to_json(Obj, "signingUp", signingUp);
 | 
				
			||||||
 | 
							Obj.set("userPermissions", permissions_to_json(userPermissions));
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	bool UserInfo::from_json(const Poco::JSON::Object::Ptr &Obj) {
 | 
						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, "oauthUserInfo", oauthUserInfo);
 | 
				
			||||||
			field_from_json(Obj, "modified", modified);
 | 
								field_from_json(Obj, "modified", modified);
 | 
				
			||||||
			field_from_json(Obj, "signingUp", signingUp);
 | 
								field_from_json(Obj, "signingUp", signingUp);
 | 
				
			||||||
 | 
								userPermissions = permissions_from_json(Obj->getObject("userPermissions"));
 | 
				
			||||||
			return true;
 | 
								return true;
 | 
				
			||||||
		} catch (const Poco::Exception &E) {
 | 
							} catch (const Poco::Exception &E) {
 | 
				
			||||||
			std::cout << "Cannot parse: UserInfo" << std::endl;
 | 
								std::cout << "Cannot parse: UserInfo" << std::endl;
 | 
				
			||||||
@@ -737,4 +741,218 @@ namespace OpenWifi::SecurityObjects {
 | 
				
			|||||||
        return false;
 | 
					        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
 | 
					} // namespace OpenWifi::SecurityObjects
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -11,10 +11,15 @@
 | 
				
			|||||||
#include "Poco/Data/LOB.h"
 | 
					#include "Poco/Data/LOB.h"
 | 
				
			||||||
#include "Poco/Data/LOBStream.h"
 | 
					#include "Poco/Data/LOBStream.h"
 | 
				
			||||||
#include "Poco/JSON/Object.h"
 | 
					#include "Poco/JSON/Object.h"
 | 
				
			||||||
 | 
					#include "Poco/Net/HTTPRequest.h"
 | 
				
			||||||
#include "framework/OpenWifiTypes.h"
 | 
					#include "framework/OpenWifiTypes.h"
 | 
				
			||||||
#include "framework/utils.h"
 | 
					#include "framework/utils.h"
 | 
				
			||||||
#include <string>
 | 
					#include <string>
 | 
				
			||||||
#include <type_traits>
 | 
					#include <type_traits>
 | 
				
			||||||
 | 
					#include <iostream>
 | 
				
			||||||
 | 
					#include <fstream>
 | 
				
			||||||
 | 
					#include <map>
 | 
				
			||||||
 | 
					#include <set>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace OpenWifi {
 | 
					namespace OpenWifi {
 | 
				
			||||||
	uint64_t Now();
 | 
						uint64_t Now();
 | 
				
			||||||
@@ -55,6 +60,10 @@ namespace OpenWifi {
 | 
				
			|||||||
			bool from_json(const Poco::JSON::Object::Ptr &Obj);
 | 
								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 {
 | 
							enum USER_ROLE {
 | 
				
			||||||
			UNKNOWN,
 | 
								UNKNOWN,
 | 
				
			||||||
			ROOT,
 | 
								ROOT,
 | 
				
			||||||
@@ -125,6 +134,72 @@ namespace OpenWifi {
 | 
				
			|||||||
			bool from_json(const Poco::JSON::Object::Ptr &Obj);
 | 
								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 {
 | 
							struct UserInfo {
 | 
				
			||||||
			std::string id;
 | 
								std::string id;
 | 
				
			||||||
			std::string name;
 | 
								std::string name;
 | 
				
			||||||
@@ -149,6 +224,7 @@ namespace OpenWifi {
 | 
				
			|||||||
			bool suspended = false;
 | 
								bool suspended = false;
 | 
				
			||||||
			bool blackListed = false;
 | 
								bool blackListed = false;
 | 
				
			||||||
			USER_ROLE userRole;
 | 
								USER_ROLE userRole;
 | 
				
			||||||
 | 
								PermissionMap userPermissions;
 | 
				
			||||||
			UserLoginLoginExtensions userTypeProprietaryInfo;
 | 
								UserLoginLoginExtensions userTypeProprietaryInfo;
 | 
				
			||||||
			std::string securityPolicy;
 | 
								std::string securityPolicy;
 | 
				
			||||||
			uint64_t securityPolicyChange = 0;
 | 
								uint64_t securityPolicyChange = 0;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -24,7 +24,7 @@ namespace OpenWifi::StateUtils {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	bool ComputeAssociations(const Poco::JSON::Object::Ptr RawObject, uint64_t &Radios_2G,
 | 
						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_2G = 0;
 | 
				
			||||||
		Radios_5G = 0;
 | 
							Radios_5G = 0;
 | 
				
			||||||
		Radios_6G = 0;
 | 
							Radios_6G = 0;
 | 
				
			||||||
@@ -90,9 +90,15 @@ namespace OpenWifi::StateUtils {
 | 
				
			|||||||
					}
 | 
										}
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			//			std::cout << Radios_2G << " " << Radios_5G << " " << Radios_6G << std::endl;
 | 
					 | 
				
			||||||
			return true;
 | 
								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;
 | 
							return false;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
} // namespace OpenWifi::StateUtils
 | 
					} // namespace OpenWifi::StateUtils
 | 
				
			||||||
@@ -8,5 +8,5 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
namespace OpenWifi::StateUtils {
 | 
					namespace OpenWifi::StateUtils {
 | 
				
			||||||
	bool ComputeAssociations(const Poco::JSON::Object::Ptr RawObject, uint64_t &Radios_2G,
 | 
						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_->Create();
 | 
				
			||||||
		ScriptDB_->Initialize();
 | 
							ScriptDB_->Initialize();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							FixDeviceTypeBug();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		return 0;
 | 
							return 0;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -16,6 +16,22 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
namespace OpenWifi {
 | 
					namespace OpenWifi {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						class LockedDbSession {
 | 
				
			||||||
 | 
						  public:
 | 
				
			||||||
 | 
							explicit LockedDbSession();
 | 
				
			||||||
 | 
							~LockedDbSession() = default;
 | 
				
			||||||
 | 
							inline std::mutex &Mutex() { return *Mutex_; };
 | 
				
			||||||
 | 
							inline Poco::Data::Session &Session() {
 | 
				
			||||||
 | 
								if(!Session_->isConnected()) {
 | 
				
			||||||
 | 
									Session_->reconnect();
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								return *Session_;
 | 
				
			||||||
 | 
							};
 | 
				
			||||||
 | 
						  private:
 | 
				
			||||||
 | 
							std::shared_ptr<Poco::Data::Session> 	Session_;
 | 
				
			||||||
 | 
							std::shared_ptr<std::mutex> 			Mutex_;
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	class Storage : public StorageClass {
 | 
						class Storage : public StorageClass {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	  public:
 | 
						  public:
 | 
				
			||||||
@@ -90,7 +106,8 @@ namespace OpenWifi {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
		// typedef std::map<std::string,std::string>	DeviceCapabilitiesCache;
 | 
							// typedef std::map<std::string,std::string>	DeviceCapabilitiesCache;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		bool AddLog(const GWObjects::DeviceLog &Log);
 | 
							bool AddLog(LockedDbSession &Session, const GWObjects::DeviceLog &Log);
 | 
				
			||||||
 | 
							bool AddStatisticsData(Poco::Data::Session &Session, const GWObjects::Statistics &Stats);
 | 
				
			||||||
		bool AddStatisticsData(const GWObjects::Statistics &Stats);
 | 
							bool AddStatisticsData(const GWObjects::Statistics &Stats);
 | 
				
			||||||
		bool GetStatisticsData(std::string &SerialNumber, uint64_t FromDate, uint64_t ToDate,
 | 
							bool GetStatisticsData(std::string &SerialNumber, uint64_t FromDate, uint64_t ToDate,
 | 
				
			||||||
							   uint64_t Offset, uint64_t HowMany,
 | 
												   uint64_t Offset, uint64_t HowMany,
 | 
				
			||||||
@@ -102,6 +119,7 @@ namespace OpenWifi {
 | 
				
			|||||||
									 std::vector<GWObjects::Statistics> &Stats);
 | 
														 std::vector<GWObjects::Statistics> &Stats);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		bool AddHealthCheckData(const GWObjects::HealthCheck &Check);
 | 
							bool AddHealthCheckData(const GWObjects::HealthCheck &Check);
 | 
				
			||||||
 | 
							bool AddHealthCheckData(LockedDbSession &Session, const GWObjects::HealthCheck &Check);
 | 
				
			||||||
		bool GetHealthCheckData(std::string &SerialNumber, uint64_t FromDate, uint64_t ToDate,
 | 
							bool GetHealthCheckData(std::string &SerialNumber, uint64_t FromDate, uint64_t ToDate,
 | 
				
			||||||
								uint64_t Offset, uint64_t HowMany,
 | 
													uint64_t Offset, uint64_t HowMany,
 | 
				
			||||||
								std::vector<GWObjects::HealthCheck> &Checks);
 | 
													std::vector<GWObjects::HealthCheck> &Checks);
 | 
				
			||||||
@@ -115,31 +133,43 @@ namespace OpenWifi {
 | 
				
			|||||||
									   uint64_t &NewUUID);
 | 
														   uint64_t &NewUUID);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		bool RollbackDeviceConfigurationChange(std::string & SerialNumber);
 | 
							bool RollbackDeviceConfigurationChange(std::string & SerialNumber);
 | 
				
			||||||
 | 
							bool CompleteDeviceConfigurationChange(Poco::Data::Session &Session, std::string & SerialNumber);
 | 
				
			||||||
		bool CompleteDeviceConfigurationChange(std::string & SerialNumber);
 | 
							bool CompleteDeviceConfigurationChange(std::string & SerialNumber);
 | 
				
			||||||
 | 
							bool CreateDevice(LockedDbSession &Session, GWObjects::Device &);
 | 
				
			||||||
		bool CreateDevice(GWObjects::Device &);
 | 
							bool CreateDevice(GWObjects::Device &);
 | 
				
			||||||
		bool CreateDefaultDevice(std::string &SerialNumber, const Config::Capabilities &Caps,
 | 
							bool CreateDefaultDevice(Poco::Data::Session &Session,std::string &SerialNumber,
 | 
				
			||||||
 | 
													 const Config::Capabilities &Caps,
 | 
				
			||||||
								 std::string &Firmware, const Poco::Net::IPAddress &IPAddress,
 | 
													 std::string &Firmware, const Poco::Net::IPAddress &IPAddress,
 | 
				
			||||||
								 bool simulated);
 | 
													 bool simulated);
 | 
				
			||||||
 | 
							bool CreateDevice(Poco::Data::Session &Sess, 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,
 | 
							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,
 | 
							//		bool GetDevices(uint64_t From, uint64_t HowMany, const std::string & Select,
 | 
				
			||||||
		// std::vector<GWObjects::Device> &Devices, const std::string & orderBy="");
 | 
							// std::vector<GWObjects::Device> &Devices, const std::string & orderBy="");
 | 
				
			||||||
		bool DeleteDevice(std::string &SerialNumber);
 | 
							bool DeleteDevice(std::string &SerialNumber);
 | 
				
			||||||
		bool DeleteDevices(std::string &SerialPattern, bool SimulatedOnly);
 | 
							bool DeleteDevices(std::string &SerialPattern, bool SimulatedOnly);
 | 
				
			||||||
		bool DeleteDevices(std::uint64_t OlderContact, bool SimulatedOnly);
 | 
							bool DeleteDevices(std::uint64_t OlderContact, bool SimulatedOnly);
 | 
				
			||||||
 | 
							std::string GetPlatform(const std::string &SerialNumber);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		bool UpdateDevice(GWObjects::Device &);
 | 
							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 DeviceExists(std::string &SerialNumber);
 | 
				
			||||||
		bool SetConnectInfo(std::string &SerialNumber, std::string &Firmware);
 | 
							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,
 | 
							bool GetDeviceSerialNumbers(uint64_t From, uint64_t HowMany,
 | 
				
			||||||
									std::vector<std::string> &SerialNumbers,
 | 
														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 GetDeviceFWUpdatePolicy(std::string &SerialNumber, std::string &Policy);
 | 
				
			||||||
		bool SetDevicePassword(std::string &SerialNumber, std::string &Password);
 | 
							bool SetDevicePassword(LockedDbSession &Session, std::string &SerialNumber, std::string &Password);
 | 
				
			||||||
		bool UpdateSerialNumberCache();
 | 
							bool UpdateSerialNumberCache();
 | 
				
			||||||
		static void GetDeviceDbFieldList(Types::StringVec &Fields);
 | 
							static void GetDeviceDbFieldList(Types::StringVec &Fields);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -148,9 +178,11 @@ namespace OpenWifi {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
		bool UpdateDeviceCapabilities(std::string &SerialNumber,
 | 
							bool UpdateDeviceCapabilities(std::string &SerialNumber,
 | 
				
			||||||
									  const Config::Capabilities &Capabilities);
 | 
														  const Config::Capabilities &Capabilities);
 | 
				
			||||||
 | 
							bool UpdateDeviceCapabilities(Poco::Data::Session &Session, std::string &SerialNumber,
 | 
				
			||||||
 | 
														  const Config::Capabilities &Capabilities);
 | 
				
			||||||
		bool GetDeviceCapabilities(std::string &SerialNumber, GWObjects::Capabilities &);
 | 
							bool GetDeviceCapabilities(std::string &SerialNumber, GWObjects::Capabilities &);
 | 
				
			||||||
		bool DeleteDeviceCapabilities(std::string &SerialNumber);
 | 
							bool DeleteDeviceCapabilities(std::string &SerialNumber);
 | 
				
			||||||
		bool CreateDeviceCapabilities(std::string &SerialNumber,
 | 
							bool CreateDeviceCapabilities(Poco::Data::Session &Session, std::string &SerialNumber,
 | 
				
			||||||
									  const Config::Capabilities &Capabilities);
 | 
														  const Config::Capabilities &Capabilities);
 | 
				
			||||||
		bool InitCapabilitiesCache();
 | 
							bool InitCapabilitiesCache();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -171,6 +203,7 @@ namespace OpenWifi {
 | 
				
			|||||||
		bool GetDefaultConfigurations(uint64_t From, uint64_t HowMany,
 | 
							bool GetDefaultConfigurations(uint64_t From, uint64_t HowMany,
 | 
				
			||||||
									  std::vector<GWObjects::DefaultConfiguration> &Devices);
 | 
														  std::vector<GWObjects::DefaultConfiguration> &Devices);
 | 
				
			||||||
		bool FindDefaultConfigurationForModel(const std::string &Model,
 | 
							bool FindDefaultConfigurationForModel(const std::string &Model,
 | 
				
			||||||
 | 
																  const std::string &Platform,
 | 
				
			||||||
											  GWObjects::DefaultConfiguration &DefConfig);
 | 
																  GWObjects::DefaultConfiguration &DefConfig);
 | 
				
			||||||
		uint64_t GetDefaultConfigurationsCount();
 | 
							uint64_t GetDefaultConfigurationsCount();
 | 
				
			||||||
		bool DefaultConfigurationAlreadyExists(std::string &Name);
 | 
							bool DefaultConfigurationAlreadyExists(std::string &Name);
 | 
				
			||||||
@@ -210,7 +243,7 @@ namespace OpenWifi {
 | 
				
			|||||||
									 const std::string &Type);
 | 
														 const std::string &Type);
 | 
				
			||||||
		bool CancelWaitFile(std::string &UUID, std::string &ErrorText);
 | 
							bool CancelWaitFile(std::string &UUID, std::string &ErrorText);
 | 
				
			||||||
		bool GetAttachedFileContent(std::string &UUID, const std::string &SerialNumber,
 | 
							bool GetAttachedFileContent(std::string &UUID, const std::string &SerialNumber,
 | 
				
			||||||
									std::string &FileContent, std::string &Type);
 | 
														std::string &FileContent, std::string &Type, int& WaitingForFile);
 | 
				
			||||||
		bool RemoveAttachedFile(std::string &UUID);
 | 
							bool RemoveAttachedFile(std::string &UUID);
 | 
				
			||||||
		bool SetCommandResult(std::string &UUID, std::string &Result);
 | 
							bool SetCommandResult(std::string &UUID, std::string &Result);
 | 
				
			||||||
		bool GetNewestCommands(std::string &SerialNumber, uint64_t HowMany,
 | 
							bool GetNewestCommands(std::string &SerialNumber, uint64_t HowMany,
 | 
				
			||||||
@@ -222,15 +255,15 @@ namespace OpenWifi {
 | 
				
			|||||||
		void RemovedExpiredCommands();
 | 
							void RemovedExpiredCommands();
 | 
				
			||||||
		void RemoveTimedOutCommands();
 | 
							void RemoveTimedOutCommands();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		bool RemoveOldCommands(std::string &SerilNumber, std::string &Command);
 | 
							bool RemoveOldCommands(std::string &SerialNumber, std::string &Command);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		bool AddBlackListDevices(std::vector<GWObjects::BlackListedDevice> &Devices);
 | 
							bool AddBlackListDevices(std::vector<GWObjects::BlackListedDevice> &Devices);
 | 
				
			||||||
		bool AddBlackListDevice(GWObjects::BlackListedDevice &Device);
 | 
							bool AddBlackListDevice(GWObjects::BlackListedDevice &Device);
 | 
				
			||||||
		bool GetBlackListDevice(std::string &SerialNumber, GWObjects::BlackListedDevice &Device);
 | 
							bool GetBlackListDevice(std::string &SerialNumber, GWObjects::BlackListedDevice &Device);
 | 
				
			||||||
		bool DeleteBlackListDevice(std::string &SerialNumber);
 | 
							bool DeleteBlackListDevice(std::string &SerialNumber);
 | 
				
			||||||
		bool IsBlackListed(const std::string &SerialNumber, std::string &reason,
 | 
							bool IsBlackListed(std::uint64_t SerialNumber, std::string &reason,
 | 
				
			||||||
						   std::string &author, std::uint64_t &created);
 | 
											   std::string &author, std::uint64_t &created);
 | 
				
			||||||
		bool IsBlackListed(const std::string &SerialNumber);
 | 
							bool IsBlackListed(std::uint64_t SerialNumber);
 | 
				
			||||||
		bool InitializeBlackListCache();
 | 
							bool InitializeBlackListCache();
 | 
				
			||||||
		bool GetBlackListDevices(uint64_t Offset, uint64_t HowMany,
 | 
							bool GetBlackListDevices(uint64_t Offset, uint64_t HowMany,
 | 
				
			||||||
								 std::vector<GWObjects::BlackListedDevice> &Devices);
 | 
													 std::vector<GWObjects::BlackListedDevice> &Devices);
 | 
				
			||||||
@@ -245,7 +278,9 @@ namespace OpenWifi {
 | 
				
			|||||||
		bool RemoveCommandListRecordsOlderThan(uint64_t Date);
 | 
							bool RemoveCommandListRecordsOlderThan(uint64_t Date);
 | 
				
			||||||
		bool RemoveUploadedFilesRecordsOlderThan(uint64_t Date);
 | 
							bool RemoveUploadedFilesRecordsOlderThan(uint64_t Date);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		bool SetDeviceLastRecordedContact(std::string & SeialNumber, std::uint64_t lastRecordedContact);
 | 
							bool SetDeviceLastRecordedContact(LockedDbSession &Session, std::string & SerialNumber, std::uint64_t lastRecordedContact);
 | 
				
			||||||
 | 
							bool SetDeviceLastRecordedContact(std::string & SerialNumber, std::uint64_t lastRecordedContact);
 | 
				
			||||||
 | 
							bool SetDeviceLastRecordedContact(Poco::Data::Session & Session, std::string & SerialNumber, std::uint64_t lastRecordedContact);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		int Create_Tables();
 | 
							int Create_Tables();
 | 
				
			||||||
		int Create_Statistics();
 | 
							int Create_Statistics();
 | 
				
			||||||
@@ -262,13 +297,24 @@ namespace OpenWifi {
 | 
				
			|||||||
		bool AnalyzeCommands(Types::CountedMap &R);
 | 
							bool AnalyzeCommands(Types::CountedMap &R);
 | 
				
			||||||
		bool AnalyzeDevices(GWObjects::Dashboard &D);
 | 
							bool AnalyzeDevices(GWObjects::Dashboard &D);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							void FixDeviceTypeBug();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		int Start() override;
 | 
							int Start() override;
 | 
				
			||||||
		void Stop() override;
 | 
							void Stop() override;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							inline Poco::Data::Session	StartSession() {
 | 
				
			||||||
 | 
								return Pool_->get();
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	  private:
 | 
						  private:
 | 
				
			||||||
		std::unique_ptr<OpenWifi::ScriptDB> ScriptDB_;
 | 
							std::unique_ptr<OpenWifi::ScriptDB> ScriptDB_;
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	inline auto StorageService() { return Storage::instance(); }
 | 
						inline auto StorageService() { return Storage::instance(); }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						inline LockedDbSession::LockedDbSession() {
 | 
				
			||||||
 | 
							Session_ = std::make_shared<Poco::Data::Session>(Poco::Data::Session(StorageService()->StartSession()));
 | 
				
			||||||
 | 
							Mutex_ = std::make_shared<std::mutex>();
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
} // namespace OpenWifi
 | 
					} // namespace OpenWifi
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -111,7 +111,6 @@ namespace OpenWifi {
 | 
				
			|||||||
					}
 | 
										}
 | 
				
			||||||
				} break;
 | 
									} break;
 | 
				
			||||||
				case TelemetryNotification::NotificationType::unregister: {
 | 
									case TelemetryNotification::NotificationType::unregister: {
 | 
				
			||||||
					std::lock_guard G(Mutex_);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
					auto client = Clients_.find(Notification->Data_);
 | 
										auto client = Clients_.find(Notification->Data_);
 | 
				
			||||||
					if (client != Clients_.end()) {
 | 
										if (client != Clients_.end()) {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -23,7 +23,7 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#include "framework/SubSystemServer.h"
 | 
					#include "framework/SubSystemServer.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "AP_WS_ReactorPool.h"
 | 
					#include "AP_WS_Reactor_Pool.h"
 | 
				
			||||||
#include "TelemetryClient.h"
 | 
					#include "TelemetryClient.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace OpenWifi {
 | 
					namespace OpenWifi {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -129,4 +129,26 @@ namespace OpenWifi {
 | 
				
			|||||||
		return RetrieveApiKeyInformation(SessionToken, UInfo, TID, Expired, Contacted, Suspended);
 | 
							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
 | 
					} // namespace OpenWifi
 | 
				
			||||||
@@ -61,6 +61,8 @@ namespace OpenWifi {
 | 
				
			|||||||
						   SecurityObjects::UserInfoAndPolicy &UInfo, std::uint64_t TID,
 | 
											   SecurityObjects::UserInfoAndPolicy &UInfo, std::uint64_t TID,
 | 
				
			||||||
						   bool &Expired, bool &Contacted, bool &Suspended);
 | 
											   bool &Expired, bool &Contacted, bool &Suspended);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							void EmptyCacheForRole(const std::string &role);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	  private:
 | 
						  private:
 | 
				
			||||||
		Poco::ExpireLRUCache<std::string, OpenWifi::SecurityObjects::UserInfoAndPolicy> Cache_{
 | 
							Poco::ExpireLRUCache<std::string, OpenWifi::SecurityObjects::UserInfoAndPolicy> Cache_{
 | 
				
			||||||
			512, 1200000};
 | 
								512, 1200000};
 | 
				
			||||||
 
 | 
				
			|||||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@@ -5,7 +5,7 @@
 | 
				
			|||||||
#pragma once
 | 
					#pragma once
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "framework/SubSystemServer.h"
 | 
					#include "framework/SubSystemServer.h"
 | 
				
			||||||
 | 
					#include "framework/ow_constants.h"
 | 
				
			||||||
#include <valijson/adapters/poco_json_adapter.hpp>
 | 
					#include <valijson/adapters/poco_json_adapter.hpp>
 | 
				
			||||||
#include <valijson/constraints/constraint.hpp>
 | 
					#include <valijson/constraints/constraint.hpp>
 | 
				
			||||||
#include <valijson/constraints/constraint_visitor.hpp>
 | 
					#include <valijson/constraints/constraint_visitor.hpp>
 | 
				
			||||||
@@ -17,33 +17,42 @@
 | 
				
			|||||||
namespace OpenWifi {
 | 
					namespace OpenWifi {
 | 
				
			||||||
	class ConfigurationValidator : public SubSystemServer {
 | 
						class ConfigurationValidator : public SubSystemServer {
 | 
				
			||||||
	  public:
 | 
						  public:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							enum class ConfigurationType { AP = 0 , SWITCH = 1};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		static auto instance() {
 | 
							static auto instance() {
 | 
				
			||||||
			static auto instance_ = new ConfigurationValidator;
 | 
								static auto instance_ = new ConfigurationValidator;
 | 
				
			||||||
			return instance_;
 | 
								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;
 | 
							int Start() override;
 | 
				
			||||||
		void Stop() override;
 | 
							void Stop() override;
 | 
				
			||||||
		void reinitialize(Poco::Util::Application &self) 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:
 | 
						  private:
 | 
				
			||||||
		bool Initialized_ = false;
 | 
							bool Initialized_ = false;
 | 
				
			||||||
		bool Working_ = false;
 | 
							bool Working_ = false;
 | 
				
			||||||
		void Init();
 | 
							void Init();
 | 
				
			||||||
		std::unique_ptr<valijson::Schema> RootSchema_;
 | 
							std::array<valijson::Schema,2> 			RootSchema_;
 | 
				
			||||||
		std::unique_ptr<valijson::SchemaParser> SchemaParser_;
 | 
							bool SetSchema(ConfigurationType Type, const std::string &SchemaStr);
 | 
				
			||||||
		std::unique_ptr<valijson::adapters::PocoJsonAdapter> PocoJsonAdapter_;
 | 
					 | 
				
			||||||
		Poco::JSON::Object::Ptr SchemaDocPtr_;
 | 
					 | 
				
			||||||
		bool SetSchema(const std::string &SchemaStr);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		ConfigurationValidator()
 | 
							ConfigurationValidator()
 | 
				
			||||||
			: SubSystemServer("ConfigValidator", "CFG-VALIDATOR", "config.validator") {}
 | 
								: SubSystemServer("ConfigValidator", "CFG-VALIDATOR", "config.validator") {}
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	inline auto ConfigurationValidator() { return ConfigurationValidator::instance(); }
 | 
						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) {
 | 
																  bool strict) {
 | 
				
			||||||
		return ConfigurationValidator::instance()->Validate(C, Error, strict);
 | 
							return ConfigurationValidator::instance()->Validate(Type, C, Errors, strict);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
} // namespace OpenWifi
 | 
					} // namespace OpenWifi
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -9,8 +9,6 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
namespace OpenWifi {
 | 
					namespace OpenWifi {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	EventBusManager::EventBusManager(Poco::Logger &L) : Logger_(L) {}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	void EventBusManager::run() {
 | 
						void EventBusManager::run() {
 | 
				
			||||||
		Running_ = true;
 | 
							Running_ = true;
 | 
				
			||||||
		Utils::SetThreadName("fmwk:EventMgr");
 | 
							Utils::SetThreadName("fmwk:EventMgr");
 | 
				
			||||||
@@ -18,9 +16,9 @@ namespace OpenWifi {
 | 
				
			|||||||
		KafkaManager()->PostMessage(KafkaTopics::SERVICE_EVENTS, MicroServicePrivateEndPoint(), Msg,
 | 
							KafkaManager()->PostMessage(KafkaTopics::SERVICE_EVENTS, MicroServicePrivateEndPoint(), Msg,
 | 
				
			||||||
									false);
 | 
														false);
 | 
				
			||||||
		while (Running_) {
 | 
							while (Running_) {
 | 
				
			||||||
			Poco::Thread::trySleep((unsigned long)MicroServiceDaemonBusTimer());
 | 
								if(!Poco::Thread::trySleep((unsigned long)MicroServiceDaemonBusTimer())) {
 | 
				
			||||||
			if (!Running_)
 | 
					                break;
 | 
				
			||||||
				break;
 | 
					            }
 | 
				
			||||||
			Msg = (MicroServiceMakeSystemEventMessage(KafkaTopics::ServiceEvents::EVENT_KEEP_ALIVE));
 | 
								Msg = (MicroServiceMakeSystemEventMessage(KafkaTopics::ServiceEvents::EVENT_KEEP_ALIVE));
 | 
				
			||||||
			KafkaManager()->PostMessage(KafkaTopics::SERVICE_EVENTS, MicroServicePrivateEndPoint(),
 | 
								KafkaManager()->PostMessage(KafkaTopics::SERVICE_EVENTS, MicroServicePrivateEndPoint(),
 | 
				
			||||||
										Msg, false);
 | 
															Msg, false);
 | 
				
			||||||
@@ -31,7 +29,7 @@ namespace OpenWifi {
 | 
				
			|||||||
	};
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	void EventBusManager::Start() {
 | 
						void EventBusManager::Start() {
 | 
				
			||||||
		poco_information(Logger(), "Starting...");
 | 
							poco_information(Logger_, "Starting...");
 | 
				
			||||||
		if (KafkaManager()->Enabled()) {
 | 
							if (KafkaManager()->Enabled()) {
 | 
				
			||||||
			Thread_.start(*this);
 | 
								Thread_.start(*this);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
@@ -39,11 +37,11 @@ namespace OpenWifi {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	void EventBusManager::Stop() {
 | 
						void EventBusManager::Stop() {
 | 
				
			||||||
		if (KafkaManager()->Enabled()) {
 | 
							if (KafkaManager()->Enabled()) {
 | 
				
			||||||
			poco_information(Logger(), "Stopping...");
 | 
								poco_information(Logger_, "Stopping...");
 | 
				
			||||||
			Running_ = false;
 | 
								Running_ = false;
 | 
				
			||||||
			Thread_.wakeUp();
 | 
								Thread_.wakeUp();
 | 
				
			||||||
			Thread_.join();
 | 
								Thread_.join();
 | 
				
			||||||
			poco_information(Logger(), "Stopped...");
 | 
								poco_information(Logger_, "Stopped...");
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -12,7 +12,16 @@ namespace OpenWifi {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	class EventBusManager : public Poco::Runnable {
 | 
						class EventBusManager : public Poco::Runnable {
 | 
				
			||||||
	  public:
 | 
						  public:
 | 
				
			||||||
		explicit EventBusManager(Poco::Logger &L);
 | 
							EventBusManager() :
 | 
				
			||||||
 | 
								Logger_(Poco::Logger::create(
 | 
				
			||||||
 | 
									"EventBusManager", Poco::Logger::root().getChannel(), Poco::Logger::root().getLevel())) {
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							static auto instance() {
 | 
				
			||||||
 | 
								static auto instance_ = new EventBusManager;
 | 
				
			||||||
 | 
								return instance_;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		void run() final;
 | 
							void run() final;
 | 
				
			||||||
		void Start();
 | 
							void Start();
 | 
				
			||||||
		void Stop();
 | 
							void Stop();
 | 
				
			||||||
@@ -24,4 +33,6 @@ namespace OpenWifi {
 | 
				
			|||||||
		Poco::Logger &Logger_;
 | 
							Poco::Logger &Logger_;
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						inline auto EventBusManager() { return EventBusManager::instance(); }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
} // namespace OpenWifi
 | 
					} // namespace OpenWifi
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -79,8 +79,10 @@ namespace OpenWifi {
 | 
				
			|||||||
		Utils::SetThreadName("Kafka:Prod");
 | 
							Utils::SetThreadName("Kafka:Prod");
 | 
				
			||||||
		cppkafka::Configuration Config(
 | 
							cppkafka::Configuration Config(
 | 
				
			||||||
			{{"client.id", MicroServiceConfigGetString("openwifi.kafka.client.id", "")},
 | 
								{{"client.id", MicroServiceConfigGetString("openwifi.kafka.client.id", "")},
 | 
				
			||||||
			 {"metadata.broker.list",
 | 
								 {"metadata.broker.list",MicroServiceConfigGetString("openwifi.kafka.brokerlist", "")} // ,
 | 
				
			||||||
			  MicroServiceConfigGetString("openwifi.kafka.brokerlist", "")}});
 | 
								 // {"send.buffer.bytes", KafkaManager()->KafkaManagerMaximumPayloadSize() }
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					 		);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		AddKafkaSecurity(Config);
 | 
							AddKafkaSecurity(Config);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -105,7 +107,16 @@ namespace OpenWifi {
 | 
				
			|||||||
					NewMessage.partition(0);
 | 
										NewMessage.partition(0);
 | 
				
			||||||
					NewMessage.payload(Msg->Payload());
 | 
										NewMessage.payload(Msg->Payload());
 | 
				
			||||||
					Producer.produce(NewMessage);
 | 
										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) {
 | 
								} catch (const cppkafka::HandleException &E) {
 | 
				
			||||||
				poco_warning(Logger_,
 | 
									poco_warning(Logger_,
 | 
				
			||||||
@@ -115,8 +126,13 @@ namespace OpenWifi {
 | 
				
			|||||||
			} catch (...) {
 | 
								} catch (...) {
 | 
				
			||||||
				poco_error(Logger_, "std::exception");
 | 
									poco_error(Logger_, "std::exception");
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
								if (Queue_.size() == 0) {
 | 
				
			||||||
 | 
									// message queue is empty, flush all previously sent messages
 | 
				
			||||||
 | 
									Producer.flush();
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
			Note = Queue_.waitDequeueNotification();
 | 
								Note = Queue_.waitDequeueNotification();
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
							Producer.flush();
 | 
				
			||||||
		poco_information(Logger_, "Stopped...");
 | 
							poco_information(Logger_, "Stopped...");
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -275,6 +291,7 @@ namespace OpenWifi {
 | 
				
			|||||||
	int KafkaManager::Start() {
 | 
						int KafkaManager::Start() {
 | 
				
			||||||
		if (!KafkaEnabled_)
 | 
							if (!KafkaEnabled_)
 | 
				
			||||||
			return 0;
 | 
								return 0;
 | 
				
			||||||
 | 
							MaxPayloadSize_ = MicroServiceConfigGetInt("openwifi.kafka.max.payload", 250000);
 | 
				
			||||||
		ConsumerThr_.Start();
 | 
							ConsumerThr_.Start();
 | 
				
			||||||
		ProducerThr_.Start();
 | 
							ProducerThr_.Start();
 | 
				
			||||||
		return 0;
 | 
							return 0;
 | 
				
			||||||
@@ -321,4 +338,4 @@ namespace OpenWifi {
 | 
				
			|||||||
											   partitions.front().get_partition()));
 | 
																   partitions.front().get_partition()));
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
} // namespace OpenWifi
 | 
					} // namespace OpenWifi
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -94,11 +94,14 @@ namespace OpenWifi {
 | 
				
			|||||||
			return ConsumerThr_.UnregisterTopicWatcher(Topic,Id);
 | 
								return ConsumerThr_.UnregisterTopicWatcher(Topic,Id);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							std::uint64_t KafkaManagerMaximumPayloadSize() const { return MaxPayloadSize_; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	  private:
 | 
						  private:
 | 
				
			||||||
		bool KafkaEnabled_ = false;
 | 
							bool KafkaEnabled_ = false;
 | 
				
			||||||
		std::string SystemInfoWrapper_;
 | 
							std::string SystemInfoWrapper_;
 | 
				
			||||||
		KafkaProducer ProducerThr_;
 | 
							KafkaProducer ProducerThr_;
 | 
				
			||||||
		KafkaConsumer ConsumerThr_;
 | 
							KafkaConsumer ConsumerThr_;
 | 
				
			||||||
 | 
							std::uint64_t MaxPayloadSize_ = 250000;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		void PartitionAssignment(const cppkafka::TopicPartitionList &partitions);
 | 
							void PartitionAssignment(const cppkafka::TopicPartitionList &partitions);
 | 
				
			||||||
		void PartitionRevocation(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_LEAVE = "leave";
 | 
				
			||||||
		inline const char * EVENT_KEEP_ALIVE = "keep-alive";
 | 
							inline const char * EVENT_KEEP_ALIVE = "keep-alive";
 | 
				
			||||||
		inline const char * EVENT_REMOVE_TOKEN = "remove-token";
 | 
							inline const char * EVENT_REMOVE_TOKEN = "remove-token";
 | 
				
			||||||
 | 
							inline const char * EVENT_PERMISSIONS_UPDATE = "permissions-update";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		namespace Fields {
 | 
							namespace Fields {
 | 
				
			||||||
			inline const char * EVENT = "event";
 | 
								inline const char * EVENT = "event";
 | 
				
			||||||
@@ -37,6 +38,7 @@ namespace OpenWifi::KafkaTopics {
 | 
				
			|||||||
			inline const char * KEY = "key";
 | 
								inline const char * KEY = "key";
 | 
				
			||||||
			inline const char * VRSN = "version";
 | 
								inline const char * VRSN = "version";
 | 
				
			||||||
			inline const char * TOKEN = "token";
 | 
								inline const char * TOKEN = "token";
 | 
				
			||||||
 | 
								inline const char * ROLE = "role";
 | 
				
			||||||
		} // namespace Fields
 | 
							} // namespace Fields
 | 
				
			||||||
	}	  // namespace ServiceEvents
 | 
						}	  // namespace ServiceEvents
 | 
				
			||||||
} // namespace OpenWifi::KafkaTopics
 | 
					} // namespace OpenWifi::KafkaTopics
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,4 +1,5 @@
 | 
				
			|||||||
//
 | 
					//
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
// Created by stephane bourque on 2022-10-26.
 | 
					// Created by stephane bourque on 2022-10-26.
 | 
				
			||||||
//
 | 
					//
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -29,13 +30,29 @@
 | 
				
			|||||||
#include "framework/WebSocketLogger.h"
 | 
					#include "framework/WebSocketLogger.h"
 | 
				
			||||||
#include "framework/utils.h"
 | 
					#include "framework/utils.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef  USE_MEDUSA_CLIENT
 | 
				
			||||||
 | 
					#include <medusa/MedusaClient.h>
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace OpenWifi {
 | 
					namespace OpenWifi {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	void MicroService::Exit(int Reason) { std::exit(Reason); }
 | 
						static std::string MakeServiceListString(const Types::MicroServiceMetaMap &Services) {
 | 
				
			||||||
 | 
					        std::string SvcList;
 | 
				
			||||||
 | 
					        for (const auto &Svc : Services) {
 | 
				
			||||||
 | 
					            if (SvcList.empty())
 | 
				
			||||||
 | 
					                SvcList = Svc.second.Type;
 | 
				
			||||||
 | 
					            else
 | 
				
			||||||
 | 
					                SvcList += ", " + Svc.second.Type;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return SvcList;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	void MicroService::BusMessageReceived([[maybe_unused]] const std::string &Key,
 | 
						void MicroService::BusMessageReceived([[maybe_unused]] const std::string &Key,
 | 
				
			||||||
										  const std::string &Payload) {
 | 
															  const std::string &Payload) {
 | 
				
			||||||
		std::lock_guard G(InfraMutex_);
 | 
							std::lock_guard G(InfraMutex_);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							Poco::Logger &BusLogger = EventBusManager()->Logger();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		try {
 | 
							try {
 | 
				
			||||||
			Poco::JSON::Parser P;
 | 
								Poco::JSON::Parser P;
 | 
				
			||||||
			auto Object = P.parse(Payload).extract<Poco::JSON::Object::Ptr>();
 | 
								auto Object = P.parse(Payload).extract<Poco::JSON::Object::Ptr>();
 | 
				
			||||||
@@ -55,13 +72,10 @@ namespace OpenWifi {
 | 
				
			|||||||
							Object->has(KafkaTopics::ServiceEvents::Fields::KEY)) {
 | 
												Object->has(KafkaTopics::ServiceEvents::Fields::KEY)) {
 | 
				
			||||||
							auto PrivateEndPoint =
 | 
												auto PrivateEndPoint =
 | 
				
			||||||
								Object->get(KafkaTopics::ServiceEvents::Fields::PRIVATE).toString();
 | 
													Object->get(KafkaTopics::ServiceEvents::Fields::PRIVATE).toString();
 | 
				
			||||||
							if (Event == KafkaTopics::ServiceEvents::EVENT_KEEP_ALIVE &&
 | 
												if (Event == KafkaTopics::ServiceEvents::EVENT_LEAVE) {
 | 
				
			||||||
								Services_.find(PrivateEndPoint) != Services_.end()) {
 | 
					 | 
				
			||||||
								Services_[PrivateEndPoint].LastUpdate = Utils::Now();
 | 
					 | 
				
			||||||
							} else if (Event == KafkaTopics::ServiceEvents::EVENT_LEAVE) {
 | 
					 | 
				
			||||||
								Services_.erase(PrivateEndPoint);
 | 
													Services_.erase(PrivateEndPoint);
 | 
				
			||||||
								poco_debug(
 | 
													poco_information(
 | 
				
			||||||
									logger(),
 | 
														BusLogger,
 | 
				
			||||||
									fmt::format(
 | 
														fmt::format(
 | 
				
			||||||
										"Service {} ID={} leaving system.",
 | 
															"Service {} ID={} leaving system.",
 | 
				
			||||||
										Object->get(KafkaTopics::ServiceEvents::Fields::PRIVATE)
 | 
															Object->get(KafkaTopics::ServiceEvents::Fields::PRIVATE)
 | 
				
			||||||
@@ -69,14 +83,7 @@ namespace OpenWifi {
 | 
				
			|||||||
										ID));
 | 
															ID));
 | 
				
			||||||
							} else if (Event == KafkaTopics::ServiceEvents::EVENT_JOIN ||
 | 
												} else if (Event == KafkaTopics::ServiceEvents::EVENT_JOIN ||
 | 
				
			||||||
									   Event == KafkaTopics::ServiceEvents::EVENT_KEEP_ALIVE) {
 | 
														   Event == KafkaTopics::ServiceEvents::EVENT_KEEP_ALIVE) {
 | 
				
			||||||
								poco_debug(
 | 
													auto ServiceInfo = Types::MicroServiceMeta{
 | 
				
			||||||
									logger(),
 | 
					 | 
				
			||||||
									fmt::format(
 | 
					 | 
				
			||||||
										"Service {} ID={} joining system.",
 | 
					 | 
				
			||||||
										Object->get(KafkaTopics::ServiceEvents::Fields::PRIVATE)
 | 
					 | 
				
			||||||
											.toString(),
 | 
					 | 
				
			||||||
										ID));
 | 
					 | 
				
			||||||
								Services_[PrivateEndPoint] = Types::MicroServiceMeta{
 | 
					 | 
				
			||||||
									.Id = ID,
 | 
														.Id = ID,
 | 
				
			||||||
									.Type = Poco::toLower(
 | 
														.Type = Poco::toLower(
 | 
				
			||||||
										Object->get(KafkaTopics::ServiceEvents::Fields::TYPE)
 | 
															Object->get(KafkaTopics::ServiceEvents::Fields::TYPE)
 | 
				
			||||||
@@ -94,20 +101,46 @@ namespace OpenWifi {
 | 
				
			|||||||
												   .toString(),
 | 
																	   .toString(),
 | 
				
			||||||
									.LastUpdate = Utils::Now()};
 | 
														.LastUpdate = Utils::Now()};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
								std::string SvcList;
 | 
					                                auto s1 = MakeServiceListString(Services_);
 | 
				
			||||||
								for (const auto &Svc : Services_) {
 | 
													auto PreviousSize = Services_.size();
 | 
				
			||||||
									if (SvcList.empty())
 | 
													Services_[PrivateEndPoint] = ServiceInfo;
 | 
				
			||||||
										SvcList = Svc.second.Type;
 | 
													auto CurrentSize = Services_.size();
 | 
				
			||||||
									else
 | 
													if(Event == KafkaTopics::ServiceEvents::EVENT_JOIN) {
 | 
				
			||||||
										SvcList += ", " + Svc.second.Type;
 | 
														if(!s1.empty()) {
 | 
				
			||||||
 | 
															poco_information(
 | 
				
			||||||
 | 
																BusLogger,
 | 
				
			||||||
 | 
																fmt::format(
 | 
				
			||||||
 | 
																	"Service {} ID={} is joining the system.",
 | 
				
			||||||
 | 
																	Object
 | 
				
			||||||
 | 
																		->get(
 | 
				
			||||||
 | 
																			KafkaTopics::ServiceEvents::Fields::PRIVATE)
 | 
				
			||||||
 | 
																		.toString(),
 | 
				
			||||||
 | 
																	ID));
 | 
				
			||||||
 | 
														}
 | 
				
			||||||
 | 
														std::string SvcList;
 | 
				
			||||||
 | 
														for (const auto &Svc : Services_) {
 | 
				
			||||||
 | 
															if (SvcList.empty())
 | 
				
			||||||
 | 
																SvcList = Svc.second.Type;
 | 
				
			||||||
 | 
															else
 | 
				
			||||||
 | 
																SvcList += ", " + Svc.second.Type;
 | 
				
			||||||
 | 
														}
 | 
				
			||||||
 | 
														poco_information(
 | 
				
			||||||
 | 
															BusLogger,
 | 
				
			||||||
 | 
															fmt::format("Current list of microservices: {}", SvcList));
 | 
				
			||||||
 | 
													} else if(CurrentSize!=PreviousSize) {
 | 
				
			||||||
 | 
														poco_information(
 | 
				
			||||||
 | 
															BusLogger,
 | 
				
			||||||
 | 
															fmt::format(
 | 
				
			||||||
 | 
																"Service {} ID={} is being added back in.",
 | 
				
			||||||
 | 
																Object
 | 
				
			||||||
 | 
																	->get(KafkaTopics::ServiceEvents::Fields::PRIVATE)
 | 
				
			||||||
 | 
																	.toString(),
 | 
				
			||||||
 | 
																ID));
 | 
				
			||||||
								}
 | 
													}
 | 
				
			||||||
								poco_information(
 | 
					 | 
				
			||||||
									logger(),
 | 
					 | 
				
			||||||
									fmt::format("Current list of microservices: {}", SvcList));
 | 
					 | 
				
			||||||
							}
 | 
												}
 | 
				
			||||||
						} else {
 | 
											} else {
 | 
				
			||||||
							poco_error(
 | 
												poco_information(
 | 
				
			||||||
								logger(),
 | 
													BusLogger,
 | 
				
			||||||
								fmt::format("KAFKA-MSG: invalid event '{}', missing a field.",
 | 
													fmt::format("KAFKA-MSG: invalid event '{}', missing a field.",
 | 
				
			||||||
											Event));
 | 
																Event));
 | 
				
			||||||
						}
 | 
											}
 | 
				
			||||||
@@ -118,32 +151,49 @@ namespace OpenWifi {
 | 
				
			|||||||
								Object->get(KafkaTopics::ServiceEvents::Fields::TOKEN).toString());
 | 
													Object->get(KafkaTopics::ServiceEvents::Fields::TOKEN).toString());
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
						} else {
 | 
											} else {
 | 
				
			||||||
							poco_error(
 | 
												poco_information(
 | 
				
			||||||
								logger(),
 | 
													BusLogger,
 | 
				
			||||||
								fmt::format("KAFKA-MSG: invalid event '{}', missing token", Event));
 | 
													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 {
 | 
										} else {
 | 
				
			||||||
						poco_error(logger(),
 | 
											poco_information(BusLogger,
 | 
				
			||||||
								   fmt::format("Unknown Event: {} Source: {}", Event, ID));
 | 
													   fmt::format("Unknown Event: {} Source: {}", Event, ID));
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			} else {
 | 
								} else {
 | 
				
			||||||
				poco_error(logger(), "Bad bus message.");
 | 
									std::ostringstream os;
 | 
				
			||||||
                std::ostringstream os;
 | 
									Object->stringify(std::cout);
 | 
				
			||||||
                Object->stringify(std::cout);
 | 
									poco_error(BusLogger, fmt::format("Bad bus message: {}", os.str()));
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			auto i = Services_.begin();
 | 
								auto ServiceHint = Services_.begin();
 | 
				
			||||||
			auto now = Utils::Now();
 | 
								auto now = Utils::Now();
 | 
				
			||||||
			for (; i != Services_.end();) {
 | 
					            auto si1 = Services_.size();
 | 
				
			||||||
				if ((now - i->second.LastUpdate) > 60) {
 | 
					            auto ss1 = MakeServiceListString(Services_);
 | 
				
			||||||
					i = Services_.erase(i);
 | 
								while(ServiceHint!=Services_.end()) {
 | 
				
			||||||
 | 
									if ((now - ServiceHint->second.LastUpdate) > 120) {
 | 
				
			||||||
 | 
										poco_information(BusLogger, fmt::format("ZombieService: Removing service {}, ", ServiceHint->second.PublicEndPoint));
 | 
				
			||||||
 | 
										ServiceHint = Services_.erase(ServiceHint);
 | 
				
			||||||
				} else
 | 
									} else
 | 
				
			||||||
					++i;
 | 
										++ServiceHint;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					            if(Services_.size() != si1) {
 | 
				
			||||||
 | 
					                auto ss2 = MakeServiceListString(Services_);
 | 
				
			||||||
 | 
					                poco_information(BusLogger, fmt::format("Current list of microservices: {} -> {}", ss1, ss2));
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		} catch (const Poco::Exception &E) {
 | 
							} catch (const Poco::Exception &E) {
 | 
				
			||||||
			logger().log(E);
 | 
								BusLogger.log(E);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -167,25 +217,29 @@ namespace OpenWifi {
 | 
				
			|||||||
			Res.push_back(ServiceRec);
 | 
								Res.push_back(ServiceRec);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		return Res;
 | 
							return Res;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	void MicroService::LoadConfigurationFile() {
 | 
						void MicroService::LoadConfigurationFile() {
 | 
				
			||||||
		std::string Location = Poco::Environment::get(DAEMON_CONFIG_ENV_VAR, ".");
 | 
					        if(ConfigContent_.empty()) {
 | 
				
			||||||
		ConfigFileName_ =
 | 
					            std::string Location = Poco::Environment::get(DAEMON_CONFIG_ENV_VAR, ".");
 | 
				
			||||||
			ConfigFileName_.empty() ? Location + "/" + DAEMON_PROPERTIES_FILENAME : ConfigFileName_;
 | 
					            ConfigFileName_ =
 | 
				
			||||||
		Poco::Path ConfigFile(ConfigFileName_);
 | 
					                ConfigFileName_.empty() ? Location + "/" + DAEMON_PROPERTIES_FILENAME : ConfigFileName_;
 | 
				
			||||||
 | 
					            Poco::Path ConfigFile(ConfigFileName_);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (!ConfigFile.isFile()) {
 | 
					            if (!ConfigFile.isFile()) {
 | 
				
			||||||
			std::cerr << DAEMON_APP_NAME << ": Configuration " << ConfigFile.toString()
 | 
					                std::cerr << DAEMON_APP_NAME << ": Configuration " << ConfigFile.toString()
 | 
				
			||||||
					  << " does not seem to exist. Please set " + DAEMON_CONFIG_ENV_VAR +
 | 
					                          << " does not seem to exist. Please set " + DAEMON_CONFIG_ENV_VAR +
 | 
				
			||||||
							 " env variable the path of the " + DAEMON_PROPERTIES_FILENAME +
 | 
					                                 " env variable the path of the " + DAEMON_PROPERTIES_FILENAME +
 | 
				
			||||||
							 " file."
 | 
					                                 " file."
 | 
				
			||||||
					  << std::endl;
 | 
					                          << std::endl;
 | 
				
			||||||
			std::exit(Poco::Util::Application::EXIT_CONFIG);
 | 
					                std::exit(Poco::Util::Application::EXIT_CONFIG);
 | 
				
			||||||
		}
 | 
					            }
 | 
				
			||||||
 | 
					            PropConfigurationFile_ = new Poco::Util::PropertyFileConfiguration(ConfigFile.toString());
 | 
				
			||||||
		// 	    loadConfiguration(ConfigFile.toString());
 | 
					        } else {
 | 
				
			||||||
		PropConfigurationFile_ = new Poco::Util::PropertyFileConfiguration(ConfigFile.toString());
 | 
					            std::istringstream is(ConfigContent_);
 | 
				
			||||||
 | 
					            PropConfigurationFile_ = new Poco::Util::PropertyFileConfiguration(is);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
		configPtr()->addWriteable(PropConfigurationFile_, PRIO_DEFAULT);
 | 
							configPtr()->addWriteable(PropConfigurationFile_, PRIO_DEFAULT);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -388,49 +442,69 @@ namespace OpenWifi {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	void DaemonPostInitialization(Poco::Util::Application &self);
 | 
						void DaemonPostInitialization(Poco::Util::Application &self);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	void MicroService::initialize(Poco::Util::Application &self) {
 | 
					    void MicroService::StartEverything(Poco::Util::Application &self) {
 | 
				
			||||||
		// add the default services
 | 
					        LoadConfigurationFile();
 | 
				
			||||||
		LoadConfigurationFile();
 | 
					        InitializeLoggingSystem();
 | 
				
			||||||
		InitializeLoggingSystem();
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		SubSystems_.push_back(KafkaManager());
 | 
					        static bool InitializedBaseService=false;
 | 
				
			||||||
		SubSystems_.push_back(ALBHealthCheckServer());
 | 
					        if(!InitializedBaseService) {
 | 
				
			||||||
		SubSystems_.push_back(RESTAPI_ExtServer());
 | 
					            InitializedBaseService = true;
 | 
				
			||||||
		SubSystems_.push_back(RESTAPI_IntServer());
 | 
					            SubSystems_.push_back(KafkaManager());
 | 
				
			||||||
 | 
					            SubSystems_.push_back(ALBHealthCheckServer());
 | 
				
			||||||
 | 
					            SubSystems_.push_back(RESTAPI_ExtServer());
 | 
				
			||||||
 | 
					            SubSystems_.push_back(RESTAPI_IntServer());
 | 
				
			||||||
#ifndef TIP_SECURITY_SERVICE
 | 
					#ifndef TIP_SECURITY_SERVICE
 | 
				
			||||||
		SubSystems_.push_back(AuthClient());
 | 
					            SubSystems_.push_back(AuthClient());
 | 
				
			||||||
#endif
 | 
					#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"));
 | 
					            Poco::Net::initializeSSL();
 | 
				
			||||||
		DataDir_ = DataDir.path();
 | 
					            Poco::Net::HTTPStreamFactory::registerFactory();
 | 
				
			||||||
		if (!DataDir.exists()) {
 | 
					            Poco::Net::HTTPSStreamFactory::registerFactory();
 | 
				
			||||||
			try {
 | 
					            Poco::Net::FTPStreamFactory::registerFactory();
 | 
				
			||||||
				DataDir.createDirectory();
 | 
					            Poco::Net::FTPSStreamFactory::registerFactory();
 | 
				
			||||||
			} catch (const Poco::Exception &E) {
 | 
					        }
 | 
				
			||||||
				logger().log(E);
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		WWWAssetsDir_ = ConfigPath("openwifi.restapi.wwwassets", "");
 | 
					 | 
				
			||||||
		if (WWWAssetsDir_.empty())
 | 
					 | 
				
			||||||
			WWWAssetsDir_ = DataDir_;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		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();
 | 
					        AllowExternalMicroServices_ = ConfigGetBool("allowexternalmicroservices", true);
 | 
				
			||||||
		ServerApplication::initialize(self);
 | 
					 | 
				
			||||||
		DaemonPostInitialization(self);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		Types::TopicNotifyFunction F = [this](const std::string &Key, const std::string &Payload) {
 | 
					        InitializeSubSystemServers();
 | 
				
			||||||
			this->BusMessageReceived(Key, Payload);
 | 
					        ServerApplication::initialize(self);
 | 
				
			||||||
		};
 | 
					        DaemonPostInitialization(self);
 | 
				
			||||||
		KafkaManager()->RegisterTopicWatcher(KafkaTopics::SERVICE_EVENTS, F);
 | 
					
 | 
				
			||||||
 | 
					        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() {
 | 
						void MicroService::uninitialize() {
 | 
				
			||||||
@@ -530,14 +604,12 @@ namespace OpenWifi {
 | 
				
			|||||||
		for (auto i : SubSystems_) {
 | 
							for (auto i : SubSystems_) {
 | 
				
			||||||
			i->Start();
 | 
								i->Start();
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		EventBusManager_ = std::make_unique<EventBusManager>(Poco::Logger::create(
 | 
							EventBusManager()->Start();
 | 
				
			||||||
			"EventBusManager", Poco::Logger::root().getChannel(), Poco::Logger::root().getLevel()));
 | 
					 | 
				
			||||||
		EventBusManager_->Start();
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	void MicroService::StopSubSystemServers() {
 | 
						void MicroService::StopSubSystemServers() {
 | 
				
			||||||
		AddActivity("Stopping");
 | 
							AddActivity("Stopping");
 | 
				
			||||||
		EventBusManager_->Stop();
 | 
							EventBusManager()->Stop();
 | 
				
			||||||
		for (auto i = SubSystems_.rbegin(); i != SubSystems_.rend(); ++i) {
 | 
							for (auto i = SubSystems_.rbegin(); i != SubSystems_.rend(); ++i) {
 | 
				
			||||||
			(*i)->Stop();
 | 
								(*i)->Stop();
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
@@ -697,7 +769,7 @@ namespace OpenWifi {
 | 
				
			|||||||
			auto APIKEY = Request.get("X-API-KEY");
 | 
								auto APIKEY = Request.get("X-API-KEY");
 | 
				
			||||||
			return APIKEY == MyHash_;
 | 
								return APIKEY == MyHash_;
 | 
				
			||||||
		} catch (const Poco::Exception &E) {
 | 
							} catch (const Poco::Exception &E) {
 | 
				
			||||||
			logger().log(E);
 | 
								Logger_.log(E);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		return false;
 | 
							return false;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -718,6 +790,8 @@ namespace OpenWifi {
 | 
				
			|||||||
		MicroServiceErrorHandler ErrorHandler(*this);
 | 
							MicroServiceErrorHandler ErrorHandler(*this);
 | 
				
			||||||
		Poco::ErrorHandler::set(&ErrorHandler);
 | 
							Poco::ErrorHandler::set(&ErrorHandler);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Args_ = args;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (!HelpRequested_) {
 | 
							if (!HelpRequested_) {
 | 
				
			||||||
			SavePID();
 | 
								SavePID();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -733,11 +807,18 @@ namespace OpenWifi {
 | 
				
			|||||||
				poco_information(logger, "Starting as a daemon.");
 | 
									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_));
 | 
								poco_information(logger, fmt::format("System ID set to {}", ID_));
 | 
				
			||||||
			StartSubSystemServers();
 | 
								StartSubSystemServers();
 | 
				
			||||||
			waitForTerminationRequest();
 | 
								waitForTerminationRequest();
 | 
				
			||||||
			StopSubSystemServers();
 | 
								StopSubSystemServers();
 | 
				
			||||||
			logger.notice(fmt::format("Stopped {}...", DAEMON_APP_NAME));
 | 
								logger.notice(fmt::format("Stopped {}...", DAEMON_APP_NAME));
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		return Application::EXIT_OK;
 | 
							return Application::EXIT_OK;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -55,9 +55,6 @@ namespace OpenWifi {
 | 
				
			|||||||
#include "nlohmann/json.hpp"
 | 
					#include "nlohmann/json.hpp"
 | 
				
			||||||
#include "ow_version.h"
 | 
					#include "ow_version.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define _OWDEBUG_ std::cout << __FILE__ << ":" << __LINE__ << std::endl;
 | 
					 | 
				
			||||||
// #define _OWDEBUG_ Logger().debug(Poco::format("%s: %lu",__FILE__,__LINE__));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
namespace OpenWifi {
 | 
					namespace OpenWifi {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	class MicroService : public Poco::Util::ServerApplication {
 | 
						class MicroService : public Poco::Util::ServerApplication {
 | 
				
			||||||
@@ -70,7 +67,6 @@ namespace OpenWifi {
 | 
				
			|||||||
			  SubSystems_(std::move(Subsystems)), Logger_(Poco::Logger::get("FRAMEWORK")) {
 | 
								  SubSystems_(std::move(Subsystems)), Logger_(Poco::Logger::get("FRAMEWORK")) {
 | 
				
			||||||
			instance_ = this;
 | 
								instance_ = this;
 | 
				
			||||||
			RandomEngine_.seed(std::chrono::steady_clock::now().time_since_epoch().count());
 | 
								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";
 | 
							inline static const char *ExtraConfigurationFilename = "/configuration_override.json";
 | 
				
			||||||
@@ -92,7 +88,7 @@ namespace OpenWifi {
 | 
				
			|||||||
		inline uint64_t DaemonBusTimer() const { return DAEMON_BUS_TIMER; };
 | 
							inline uint64_t DaemonBusTimer() const { return DAEMON_BUS_TIMER; };
 | 
				
			||||||
		[[nodiscard]] const std::string &AppName() { return DAEMON_APP_NAME; }
 | 
							[[nodiscard]] const std::string &AppName() { return DAEMON_APP_NAME; }
 | 
				
			||||||
		static inline uint64_t GetPID() { return Poco::Process::id(); };
 | 
							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";
 | 
								return MyPublicEndPoint_ + "/api/v1";
 | 
				
			||||||
		};
 | 
							};
 | 
				
			||||||
		[[nodiscard]] inline const std::string &GetUIURI() const { return UIURI_; };
 | 
							[[nodiscard]] inline const std::string &GetUIURI() const { return UIURI_; };
 | 
				
			||||||
@@ -107,7 +103,8 @@ namespace OpenWifi {
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
		static MicroService &instance() { return *instance_; }
 | 
							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);
 | 
							void BusMessageReceived(const std::string &Key, const std::string &Payload);
 | 
				
			||||||
		Types::MicroServiceMetaVec GetServices(const std::string &Type);
 | 
							Types::MicroServiceMetaVec GetServices(const std::string &Type);
 | 
				
			||||||
		Types::MicroServiceMetaVec GetServices();
 | 
							Types::MicroServiceMetaVec GetServices();
 | 
				
			||||||
@@ -115,7 +112,9 @@ namespace OpenWifi {
 | 
				
			|||||||
		void Reload();
 | 
							void Reload();
 | 
				
			||||||
		void LoadMyConfig();
 | 
							void LoadMyConfig();
 | 
				
			||||||
		void initialize(Poco::Util::Application &self) override;
 | 
							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 reinitialize(Poco::Util::Application &self) override;
 | 
				
			||||||
		void defineOptions(Poco::Util::OptionSet &options) override;
 | 
							void defineOptions(Poco::Util::OptionSet &options) override;
 | 
				
			||||||
		void handleHelp(const std::string &name, const std::string &value);
 | 
							void handleHelp(const std::string &name, const std::string &value);
 | 
				
			||||||
@@ -132,7 +131,7 @@ namespace OpenWifi {
 | 
				
			|||||||
		void Reload(const std::string &Sub);
 | 
							void Reload(const std::string &Sub);
 | 
				
			||||||
		Types::StringVec GetSubSystems() const;
 | 
							Types::StringVec GetSubSystems() const;
 | 
				
			||||||
		Types::StringPairVec GetLogLevels();
 | 
							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 Default);
 | 
				
			||||||
		uint64_t ConfigGetInt(const std::string &Key);
 | 
							uint64_t ConfigGetInt(const std::string &Key);
 | 
				
			||||||
		uint64_t ConfigGetBool(const std::string &Key, bool Default);
 | 
							uint64_t ConfigGetBool(const std::string &Key, bool Default);
 | 
				
			||||||
@@ -166,12 +165,25 @@ namespace OpenWifi {
 | 
				
			|||||||
								const std::string &FormatterPattern,
 | 
													const std::string &FormatterPattern,
 | 
				
			||||||
								const std::string &root_env_var);
 | 
													const std::string &root_env_var);
 | 
				
			||||||
		inline bool AllowExternalMicroServices() const { return AllowExternalMicroServices_; }
 | 
							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:
 | 
						  private:
 | 
				
			||||||
		static MicroService *instance_;
 | 
							static MicroService *instance_;
 | 
				
			||||||
		bool HelpRequested_ = false;
 | 
							bool HelpRequested_ = false;
 | 
				
			||||||
		std::string LogDir_;
 | 
							std::string LogDir_;
 | 
				
			||||||
		std::string ConfigFileName_;
 | 
							std::string ConfigFileName_;
 | 
				
			||||||
 | 
					        std::string ConfigContent_;
 | 
				
			||||||
		uint64_t ID_ = 1;
 | 
							uint64_t ID_ = 1;
 | 
				
			||||||
		Poco::SharedPtr<Poco::Crypto::RSAKey> AppKey_;
 | 
							Poco::SharedPtr<Poco::Crypto::RSAKey> AppKey_;
 | 
				
			||||||
		bool DebugMode_ = false;
 | 
							bool DebugMode_ = false;
 | 
				
			||||||
@@ -201,7 +213,7 @@ namespace OpenWifi {
 | 
				
			|||||||
		Poco::JWT::Signer Signer_;
 | 
							Poco::JWT::Signer Signer_;
 | 
				
			||||||
		Poco::Logger &Logger_;
 | 
							Poco::Logger &Logger_;
 | 
				
			||||||
		Poco::ThreadPool TimerPool_{"timer:pool", 2, 32};
 | 
							Poco::ThreadPool TimerPool_{"timer:pool", 2, 32};
 | 
				
			||||||
		std::unique_ptr<EventBusManager> EventBusManager_;
 | 
					        ArgVec Args_;
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	inline MicroService *MicroService::instance_ = nullptr;
 | 
						inline MicroService *MicroService::instance_ = nullptr;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -133,4 +133,8 @@ namespace OpenWifi {
 | 
				
			|||||||
		return MicroService::instance().Hash();
 | 
							return MicroService::instance().Hash();
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    std::optional<OpenWifi::Types::MicroServiceMeta> MicroServicePrivateAccessKey(const std::string &servicePrivateEndPoint) {
 | 
				
			||||||
 | 
					        return MicroService::instance().GetPrivateEndPointServiceKey(servicePrivateEndPoint);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
} // namespace OpenWifi
 | 
					} // namespace OpenWifi
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -23,7 +23,9 @@ namespace OpenWifi {
 | 
				
			|||||||
	std::string MicroServiceConfigGetString(const std::string &Key,
 | 
						std::string MicroServiceConfigGetString(const std::string &Key,
 | 
				
			||||||
											const std::string &DefaultValue);
 | 
																const std::string &DefaultValue);
 | 
				
			||||||
	std::string MicroServiceAccessKey();
 | 
						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::uint64_t MicroServiceConfigGetInt(const std::string &Key, std::uint64_t DefaultValue);
 | 
				
			||||||
	std::string MicroServicePrivateEndPoint();
 | 
						std::string MicroServicePrivateEndPoint();
 | 
				
			||||||
	std::uint64_t MicroServiceID();
 | 
						std::uint64_t MicroServiceID();
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -60,9 +60,52 @@ namespace OpenWifi {
 | 
				
			|||||||
			  AlwaysAuthorize_(AlwaysAuthorize), Server_(Server), MyRates_(Profile),
 | 
								  AlwaysAuthorize_(AlwaysAuthorize), Server_(Server), MyRates_(Profile),
 | 
				
			||||||
			  TransactionId_(TransactionId) {}
 | 
								  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,
 | 
							inline bool RoleIsAuthorized([[maybe_unused]] const std::string &Path,
 | 
				
			||||||
									 [[maybe_unused]] const std::string &Method,
 | 
														 [[maybe_unused]] const std::string &Method,
 | 
				
			||||||
									 [[maybe_unused]] std::string &Reason) {
 | 
														 [[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;
 | 
								return true;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -431,6 +474,11 @@ namespace OpenWifi {
 | 
				
			|||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							inline void Accepted() {
 | 
				
			||||||
 | 
								PrepareResponse(Poco::Net::HTTPResponse::HTTP_ACCEPTED);
 | 
				
			||||||
 | 
								Response->send();
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		inline void SendCompressedTarFile(const std::string &FileName, const std::string &Content) {
 | 
							inline void SendCompressedTarFile(const std::string &FileName, const std::string &Content) {
 | 
				
			||||||
			Response->setStatus(Poco::Net::HTTPResponse::HTTPStatus::HTTP_OK);
 | 
								Response->setStatus(Poco::Net::HTTPResponse::HTTPStatus::HTTP_OK);
 | 
				
			||||||
			SetCommonHeaders();
 | 
								SetCommonHeaders();
 | 
				
			||||||
@@ -552,8 +600,8 @@ namespace OpenWifi {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
		inline bool IsAuthorized(bool &Expired, bool &Contacted, bool SubOnly = false);
 | 
							inline bool IsAuthorized(bool &Expired, bool &Contacted, bool SubOnly = false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		inline void ReturnObject(Poco::JSON::Object &Object) {
 | 
							inline void ReturnObject(Poco::JSON::Object &Object, Poco::Net::HTTPResponse::HTTPStatus Status = Poco::Net::HTTPResponse::HTTP_OK) {
 | 
				
			||||||
			PrepareResponse();
 | 
								PrepareResponse(Status);
 | 
				
			||||||
			if (Request != nullptr) {
 | 
								if (Request != nullptr) {
 | 
				
			||||||
				//   can we compress ???
 | 
									//   can we compress ???
 | 
				
			||||||
				auto AcceptedEncoding = Request->find("Accept-Encoding");
 | 
									auto AcceptedEncoding = Request->find("Accept-Encoding");
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -47,6 +47,8 @@ namespace OpenWifi {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							Poco::Data::SessionPool &Pool() { return *Pool_; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	  private:
 | 
						  private:
 | 
				
			||||||
		inline int Setup_SQLite();
 | 
							inline int Setup_SQLite();
 | 
				
			||||||
		inline int Setup_MySQL();
 | 
							inline int Setup_MySQL();
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -58,11 +58,9 @@ namespace OpenWifi {
 | 
				
			|||||||
	void UI_WebSocketClientServer::run() {
 | 
						void UI_WebSocketClientServer::run() {
 | 
				
			||||||
		Running_ = true;
 | 
							Running_ = true;
 | 
				
			||||||
		while (Running_) {
 | 
							while (Running_) {
 | 
				
			||||||
			Poco::Thread::trySleep(2000);
 | 
								if(!Poco::Thread::trySleep(2000)) {
 | 
				
			||||||
 | 
					                break;
 | 
				
			||||||
			if (!Running_)
 | 
					            }
 | 
				
			||||||
				break;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			std::lock_guard G(LocalMutex_);
 | 
								std::lock_guard G(LocalMutex_);
 | 
				
			||||||
			for (const auto i : ToBeRemoved_) {
 | 
								for (const auto i : ToBeRemoved_) {
 | 
				
			||||||
				// std::cout << "Erasing old WS UI connection..." << std::endl;
 | 
									// std::cout << "Erasing old WS UI connection..." << std::endl;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -7,57 +7,59 @@
 | 
				
			|||||||
#include <vector>
 | 
					#include <vector>
 | 
				
			||||||
#include <string>
 | 
					#include <string>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "ow_constants.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace OpenWifi {
 | 
					namespace OpenWifi {
 | 
				
			||||||
	inline  const std::vector<std::pair<std::string, std::string>> DefaultDeviceTypeList{
 | 
						inline  const std::vector<std::pair<std::string, std::string>> DefaultDeviceTypeList{
 | 
				
			||||||
		{"actiontec_web7200", "AP"},
 | 
							{"actiontec_web7200", Platforms::AP},
 | 
				
			||||||
		{"cig_wf186w", "AP"},
 | 
							{"cig_wf186w", Platforms::AP},
 | 
				
			||||||
		{"cig_wf188n", "AP"},
 | 
							{"cig_wf188n", Platforms::AP},
 | 
				
			||||||
		{"cig_wf194c4", "AP"},
 | 
							{"cig_wf194c4", Platforms::AP},
 | 
				
			||||||
		{"cig_wf196", "AP"},
 | 
							{"cig_wf196", Platforms::AP},
 | 
				
			||||||
		{"cig_wf196-ca", "AP"},
 | 
							{"cig_wf196-ca", Platforms::AP},
 | 
				
			||||||
		{"cig_wf196-ca-ath12", "AP"},
 | 
							{"cig_wf196-ca-ath12", Platforms::AP},
 | 
				
			||||||
		{"cig_wf196-us", "AP"},
 | 
							{"cig_wf196-us", Platforms::AP},
 | 
				
			||||||
		{"cig_wf610d", "AP"},
 | 
							{"cig_wf610d", Platforms::AP},
 | 
				
			||||||
		{"cig_wf660a", "AP"},
 | 
							{"cig_wf660a", Platforms::AP},
 | 
				
			||||||
		{"cig_wf808", "AP"},
 | 
							{"cig_wf808", Platforms::AP},
 | 
				
			||||||
		{"cybertan_eww622-a1", "AP"},
 | 
							{"cybertan_eww622-a1", Platforms::AP},
 | 
				
			||||||
		{"edgecore_eap101", "AP"},
 | 
							{"edgecore_eap101", Platforms::AP},
 | 
				
			||||||
		{"edgecore_eap101-ath12", "AP"},
 | 
							{"edgecore_eap101-ath12", Platforms::AP},
 | 
				
			||||||
		{"edgecore_eap102", "AP"},
 | 
							{"edgecore_eap102", Platforms::AP},
 | 
				
			||||||
		{"edgecore_eap104", "AP"},
 | 
							{"edgecore_eap104", Platforms::AP},
 | 
				
			||||||
		{"edgecore_eap104-ath12", "AP"},
 | 
							{"edgecore_eap104-ath12", Platforms::AP},
 | 
				
			||||||
		{"edgecore_ecs4100-12ph", "AP"},
 | 
							{"edgecore_ecs4100-12ph", Platforms::AP},
 | 
				
			||||||
		{"edgecore_ecw5211", "AP"},
 | 
							{"edgecore_ecw5211", Platforms::AP},
 | 
				
			||||||
		{"edgecore_ecw5410", "AP"},
 | 
							{"edgecore_ecw5410", Platforms::AP},
 | 
				
			||||||
		{"edgecore_oap100", "AP"},
 | 
							{"edgecore_oap100", Platforms::AP},
 | 
				
			||||||
		{"edgecore_spw2ac1200", "SWITCH"},
 | 
							{"edgecore_spw2ac1200", Platforms::SWITCH},
 | 
				
			||||||
		{"edgecore_spw2ac1200-lan-poe", "SWITCH"},
 | 
							{"edgecore_spw2ac1200-lan-poe", Platforms::SWITCH},
 | 
				
			||||||
		{"edgecore_ssw2ac2600", "SWITCH"},
 | 
							{"edgecore_ssw2ac2600", Platforms::SWITCH},
 | 
				
			||||||
		{"hfcl_ion4", "AP"},
 | 
							{"hfcl_ion4", Platforms::AP},
 | 
				
			||||||
		{"hfcl_ion4x", "AP"},
 | 
							{"hfcl_ion4x", Platforms::AP},
 | 
				
			||||||
		{"hfcl_ion4x_2", "AP"},
 | 
							{"hfcl_ion4x_2", Platforms::AP},
 | 
				
			||||||
		{"hfcl_ion4xe", "AP"},
 | 
							{"hfcl_ion4xe", Platforms::AP},
 | 
				
			||||||
		{"hfcl_ion4xi", "AP"},
 | 
							{"hfcl_ion4xi", Platforms::AP},
 | 
				
			||||||
		{"indio_um-305ac", "AP"},
 | 
							{"indio_um-305ac", Platforms::AP},
 | 
				
			||||||
		{"indio_um-305ax", "AP"},
 | 
							{"indio_um-305ax", Platforms::AP},
 | 
				
			||||||
		{"indio_um-310ax-v1", "AP"},
 | 
							{"indio_um-310ax-v1", Platforms::AP},
 | 
				
			||||||
		{"indio_um-325ac", "AP"},
 | 
							{"indio_um-325ac", Platforms::AP},
 | 
				
			||||||
		{"indio_um-510ac-v3", "AP"},
 | 
							{"indio_um-510ac-v3", Platforms::AP},
 | 
				
			||||||
		{"indio_um-510axm-v1", "AP"},
 | 
							{"indio_um-510axm-v1", Platforms::AP},
 | 
				
			||||||
		{"indio_um-510axp-v1", "AP"},
 | 
							{"indio_um-510axp-v1", Platforms::AP},
 | 
				
			||||||
		{"indio_um-550ac", "AP"},
 | 
							{"indio_um-550ac", Platforms::AP},
 | 
				
			||||||
		{"linksys_e8450-ubi", "AP"},
 | 
							{"linksys_e8450-ubi", Platforms::AP},
 | 
				
			||||||
		{"linksys_ea6350-v4", "AP"},
 | 
							{"linksys_ea6350-v4", Platforms::AP},
 | 
				
			||||||
		{"linksys_ea8300", "AP"},
 | 
							{"linksys_ea8300", Platforms::AP},
 | 
				
			||||||
		{"liteon_wpx8324", "AP"},
 | 
							{"liteon_wpx8324", Platforms::AP},
 | 
				
			||||||
		{"meshpp_s618_cp01", "AP"},
 | 
							{"meshpp_s618_cp01", Platforms::AP},
 | 
				
			||||||
		{"meshpp_s618_cp03", "AP"},
 | 
							{"meshpp_s618_cp03", Platforms::AP},
 | 
				
			||||||
		{"udaya_a5-id2", "AP"},
 | 
							{"udaya_a5-id2", Platforms::AP},
 | 
				
			||||||
		{"wallys_dr40x9", "AP"},
 | 
							{"wallys_dr40x9", Platforms::AP},
 | 
				
			||||||
		{"wallys_dr6018", "AP"},
 | 
							{"wallys_dr6018", Platforms::AP},
 | 
				
			||||||
		{"wallys_dr6018_v4", "AP"},
 | 
							{"wallys_dr6018_v4", Platforms::AP},
 | 
				
			||||||
		{"x64_vm", "AP"},
 | 
							{"x64_vm", Platforms::AP},
 | 
				
			||||||
		{"yuncore_ax840", "AP"},
 | 
							{"yuncore_ax840", Platforms::AP},
 | 
				
			||||||
		{"yuncore_fap640", "AP"},
 | 
							{"yuncore_fap640", Platforms::AP},
 | 
				
			||||||
		{"yuncore_fap650", "AP"}};
 | 
							{"yuncore_fap650", Platforms::AP}};
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -576,8 +576,8 @@ namespace ORM {
 | 
				
			|||||||
		bool UpdateRecord(field_name_t FieldName, const T &Value, const RecordType &R) {
 | 
							bool UpdateRecord(field_name_t FieldName, const T &Value, const RecordType &R) {
 | 
				
			||||||
			try {
 | 
								try {
 | 
				
			||||||
				assert(ValidFieldName(FieldName));
 | 
									assert(ValidFieldName(FieldName));
 | 
				
			||||||
 | 
					 | 
				
			||||||
				Poco::Data::Session Session = Pool_.get();
 | 
									Poco::Data::Session Session = Pool_.get();
 | 
				
			||||||
 | 
					                Session.begin();
 | 
				
			||||||
				Poco::Data::Statement Update(Session);
 | 
									Poco::Data::Statement Update(Session);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				RecordTuple RT;
 | 
									RecordTuple RT;
 | 
				
			||||||
@@ -593,6 +593,7 @@ namespace ORM {
 | 
				
			|||||||
				Update.execute();
 | 
									Update.execute();
 | 
				
			||||||
				if (Cache_)
 | 
									if (Cache_)
 | 
				
			||||||
					Cache_->UpdateCache(R);
 | 
										Cache_->UpdateCache(R);
 | 
				
			||||||
 | 
					                Session.commit();
 | 
				
			||||||
				return true;
 | 
									return true;
 | 
				
			||||||
			} catch (const Poco::Exception &E) {
 | 
								} catch (const Poco::Exception &E) {
 | 
				
			||||||
				Logger_.log(E);
 | 
									Logger_.log(E);
 | 
				
			||||||
@@ -662,6 +663,7 @@ namespace ORM {
 | 
				
			|||||||
				assert(ValidFieldName(FieldName));
 | 
									assert(ValidFieldName(FieldName));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				Poco::Data::Session Session = Pool_.get();
 | 
									Poco::Data::Session Session = Pool_.get();
 | 
				
			||||||
 | 
					                Session.begin();
 | 
				
			||||||
				Poco::Data::Statement Delete(Session);
 | 
									Poco::Data::Statement Delete(Session);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				std::string St = "delete from " + TableName_ + " where " + FieldName + "=?";
 | 
									std::string St = "delete from " + TableName_ + " where " + FieldName + "=?";
 | 
				
			||||||
@@ -671,6 +673,7 @@ namespace ORM {
 | 
				
			|||||||
				Delete.execute();
 | 
									Delete.execute();
 | 
				
			||||||
				if (Cache_)
 | 
									if (Cache_)
 | 
				
			||||||
					Cache_->Delete(FieldName, Value);
 | 
										Cache_->Delete(FieldName, Value);
 | 
				
			||||||
 | 
					                Session.commit();
 | 
				
			||||||
				return true;
 | 
									return true;
 | 
				
			||||||
			} catch (const Poco::Exception &E) {
 | 
								} catch (const Poco::Exception &E) {
 | 
				
			||||||
				Logger_.log(E);
 | 
									Logger_.log(E);
 | 
				
			||||||
@@ -682,11 +685,13 @@ namespace ORM {
 | 
				
			|||||||
			try {
 | 
								try {
 | 
				
			||||||
				assert(!WhereClause.empty());
 | 
									assert(!WhereClause.empty());
 | 
				
			||||||
				Poco::Data::Session Session = Pool_.get();
 | 
									Poco::Data::Session Session = Pool_.get();
 | 
				
			||||||
 | 
					                Session.begin();
 | 
				
			||||||
				Poco::Data::Statement Delete(Session);
 | 
									Poco::Data::Statement Delete(Session);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				std::string St = "delete from " + TableName_ + " where " + WhereClause;
 | 
									std::string St = "delete from " + TableName_ + " where " + WhereClause;
 | 
				
			||||||
				Delete << St;
 | 
									Delete << St;
 | 
				
			||||||
				Delete.execute();
 | 
									Delete.execute();
 | 
				
			||||||
 | 
					                Session.commit();
 | 
				
			||||||
				return true;
 | 
									return true;
 | 
				
			||||||
			} catch (const Poco::Exception &E) {
 | 
								} catch (const Poco::Exception &E) {
 | 
				
			||||||
				Logger_.log(E);
 | 
									Logger_.log(E);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -565,6 +565,7 @@ namespace OpenWifi::RESTAPI::Protocol {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	static const char *TRANSFER = "transfer";
 | 
						static const char *TRANSFER = "transfer";
 | 
				
			||||||
	static const char *CERTUPDATE = "certupdate";
 | 
						static const char *CERTUPDATE = "certupdate";
 | 
				
			||||||
 | 
						static const char *POWERCYCLE = "powercycle";
 | 
				
			||||||
	static const char *RRM = "rrm";
 | 
						static const char *RRM = "rrm";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	static const char *REQUIREMENTS = "requirements";
 | 
						static const char *REQUIREMENTS = "requirements";
 | 
				
			||||||
@@ -579,6 +580,9 @@ namespace OpenWifi::RESTAPI::Protocol {
 | 
				
			|||||||
	static const char *INTERVAL = "interval";
 | 
						static const char *INTERVAL = "interval";
 | 
				
			||||||
	static const char *UI = "UI";
 | 
						static const char *UI = "UI";
 | 
				
			||||||
	static const char *BANDWIDTH = "bandwidth";
 | 
						static const char *BANDWIDTH = "bandwidth";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						static const char *FIXEDCONFIG = "fixedconfig";
 | 
				
			||||||
 | 
						static const char *CABLEDIAGNOSTICS = "cablediagnostics";
 | 
				
			||||||
} // namespace OpenWifi::RESTAPI::Protocol
 | 
					} // namespace OpenWifi::RESTAPI::Protocol
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace OpenWifi::uCentralProtocol {
 | 
					namespace OpenWifi::uCentralProtocol {
 | 
				
			||||||
@@ -607,6 +611,7 @@ namespace OpenWifi::uCentralProtocol {
 | 
				
			|||||||
	static const char *CFGPENDING = "cfgpending";
 | 
						static const char *CFGPENDING = "cfgpending";
 | 
				
			||||||
	static const char *RECOVERY = "recovery";
 | 
						static const char *RECOVERY = "recovery";
 | 
				
			||||||
	static const char *COMPRESS_64 = "compress_64";
 | 
						static const char *COMPRESS_64 = "compress_64";
 | 
				
			||||||
 | 
						static const char *COMPRESS_SZ = "compress_sz";
 | 
				
			||||||
	static const char *CAPABILITIES = "capabilities";
 | 
						static const char *CAPABILITIES = "capabilities";
 | 
				
			||||||
	static const char *REQUEST_UUID = "request_uuid";
 | 
						static const char *REQUEST_UUID = "request_uuid";
 | 
				
			||||||
	static const char *SANITY = "sanity";
 | 
						static const char *SANITY = "sanity";
 | 
				
			||||||
@@ -687,9 +692,13 @@ namespace OpenWifi::uCentralProtocol {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	static const char *TRANSFER = "transfer";
 | 
						static const char *TRANSFER = "transfer";
 | 
				
			||||||
	static const char *CERTUPDATE = "certupdate";
 | 
						static const char *CERTUPDATE = "certupdate";
 | 
				
			||||||
 | 
						static const char *POWERCYCLE = "powercycle";
 | 
				
			||||||
	static const char *RRM = "rrm";
 | 
						static const char *RRM = "rrm";
 | 
				
			||||||
	static const char *ACTIONS = "actions";
 | 
						static const char *ACTIONS = "actions";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						static const char *FIXEDCONFIG = "fixedconfig";
 | 
				
			||||||
 | 
						static const char *CABLEDIAGNOSTICS = "cablediagnostics";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
} // namespace OpenWifi::uCentralProtocol
 | 
					} // namespace OpenWifi::uCentralProtocol
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace OpenWifi::uCentralProtocol::Events {
 | 
					namespace OpenWifi::uCentralProtocol::Events {
 | 
				
			||||||
@@ -785,6 +794,9 @@ namespace OpenWifi::APCommands {
 | 
				
			|||||||
		rrm,
 | 
							rrm,
 | 
				
			||||||
		certupdate,
 | 
							certupdate,
 | 
				
			||||||
		transfer,
 | 
							transfer,
 | 
				
			||||||
 | 
							powercycle,
 | 
				
			||||||
 | 
							fixedconfig,
 | 
				
			||||||
 | 
							cablediagnostics,
 | 
				
			||||||
		unknown
 | 
							unknown
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -799,7 +811,8 @@ namespace OpenWifi::APCommands {
 | 
				
			|||||||
		RESTAPI::Protocol::EVENTQUEUE,	 RESTAPI::Protocol::TELEMETRY,
 | 
							RESTAPI::Protocol::EVENTQUEUE,	 RESTAPI::Protocol::TELEMETRY,
 | 
				
			||||||
		RESTAPI::Protocol::PING,		 RESTAPI::Protocol::SCRIPT,
 | 
							RESTAPI::Protocol::PING,		 RESTAPI::Protocol::SCRIPT,
 | 
				
			||||||
		RESTAPI::Protocol::RRM,		 	 RESTAPI::Protocol::CERTUPDATE,
 | 
							RESTAPI::Protocol::RRM,		 	 RESTAPI::Protocol::CERTUPDATE,
 | 
				
			||||||
		RESTAPI::Protocol::TRANSFER
 | 
							RESTAPI::Protocol::TRANSFER,	 RESTAPI::Protocol::POWERCYCLE,
 | 
				
			||||||
 | 
							RESTAPI::Protocol::FIXEDCONFIG,  RESTAPI::Protocol::CABLEDIAGNOSTICS
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	inline const char *to_string(Commands Cmd) { return uCentralAPCommands[(uint8_t)Cmd]; }
 | 
						inline const char *to_string(Commands Cmd) { return uCentralAPCommands[(uint8_t)Cmd]; }
 | 
				
			||||||
@@ -828,6 +841,11 @@ namespace OpenWifi::Provisioning::DeviceClass {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
} // 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__)
 | 
					#if defined(__GNUC__)
 | 
				
			||||||
#pragma GCC diagnostic pop
 | 
					#pragma GCC diagnostic pop
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -590,6 +590,26 @@ namespace OpenWifi::Utils {
 | 
				
			|||||||
		return false;
 | 
							return false;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						//
 | 
				
			||||||
 | 
						// Compress given data using utility function and encode it in base64 format.
 | 
				
			||||||
 | 
						//
 | 
				
			||||||
 | 
						bool CompressAndEncodeBase64(const std::string& UnCompressedData, std::string& CompressedBase64Data) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							unsigned long CompressedDataSize = UnCompressedData.size();
 | 
				
			||||||
 | 
							std::vector<Bytef> CompressedData(CompressedDataSize);
 | 
				
			||||||
 | 
							auto status = compress(&CompressedData[0], &CompressedDataSize,
 | 
				
			||||||
 | 
													(Bytef*) UnCompressedData.c_str(), UnCompressedData.size());
 | 
				
			||||||
 | 
							if (status == Z_OK) {
 | 
				
			||||||
 | 
								CompressedBase64Data = OpenWifi::Utils::base64encode(&CompressedData[0], CompressedDataSize);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							else {
 | 
				
			||||||
 | 
								// failed to compress data
 | 
				
			||||||
 | 
								return false;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							return true;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	bool IsAlphaNumeric(const std::string &s) {
 | 
						bool IsAlphaNumeric(const std::string &s) {
 | 
				
			||||||
		return std::all_of(s.begin(), s.end(), [](char c) -> bool { return isalnum(c); });
 | 
							return std::all_of(s.begin(), s.end(), [](char c) -> bool { return isalnum(c); });
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -126,20 +126,6 @@ namespace OpenWifi::Utils {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	[[nodiscard]] std::uint64_t ConvertDate(const std::string &d);
 | 
						[[nodiscard]] std::uint64_t ConvertDate(const std::string &d);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	[[nodiscard]] inline uint8_t CalculateMacAddressHash(std::uint64_t value) {
 | 
					 | 
				
			||||||
		uint8_t hash = 0, i=6;
 | 
					 | 
				
			||||||
		while(i) {
 | 
					 | 
				
			||||||
			hash ^= (value & 0xFF) + 1;
 | 
					 | 
				
			||||||
			value >>= 8;
 | 
					 | 
				
			||||||
			--i;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		return hash;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	[[nodiscard]] inline uint8_t CalculateMacAddressHash(const std::string & value) {
 | 
					 | 
				
			||||||
		return CalculateMacAddressHash(MACToInt(value));
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	template <typename T> std::string int_to_hex(T i) {
 | 
						template <typename T> std::string int_to_hex(T i) {
 | 
				
			||||||
		std::stringstream stream;
 | 
							std::stringstream stream;
 | 
				
			||||||
		stream << std::setfill('0') << std::setw(12) << std::hex << i;
 | 
							stream << std::setfill('0') << std::setw(12) << std::hex << i;
 | 
				
			||||||
@@ -165,6 +151,8 @@ namespace OpenWifi::Utils {
 | 
				
			|||||||
	bool ExtractBase64CompressedData(const std::string &CompressedData,
 | 
						bool ExtractBase64CompressedData(const std::string &CompressedData,
 | 
				
			||||||
									 std::string &UnCompressedData, uint64_t compress_sz);
 | 
														 std::string &UnCompressedData, uint64_t compress_sz);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						bool CompressAndEncodeBase64(const std::string& UnCompressedData, std::string& CompressedData);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	inline bool match(const char* first, const char* second)
 | 
						inline bool match(const char* first, const char* second)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		// If we reach at the end of both strings, we are done
 | 
							// If we reach at the end of both strings, we are done
 | 
				
			||||||
@@ -330,5 +318,90 @@ namespace OpenWifi::Utils {
 | 
				
			|||||||
        uint32_t        Port;
 | 
					        uint32_t        Port;
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						class CompressedString {
 | 
				
			||||||
 | 
						  public:
 | 
				
			||||||
 | 
							CompressedString() {
 | 
				
			||||||
 | 
								DecompressedSize_ = 0;
 | 
				
			||||||
 | 
							};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							explicit CompressedString(const std::string &Data) : DecompressedSize_(Data.size()) {
 | 
				
			||||||
 | 
								CompressIt(Data);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							CompressedString(const CompressedString &Data) {
 | 
				
			||||||
 | 
								this->DecompressedSize_ = Data.DecompressedSize_;
 | 
				
			||||||
 | 
								this->CompressedData_ = Data.CompressedData_;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							CompressedString& operator=(const CompressedString& rhs) {
 | 
				
			||||||
 | 
								if (this != &rhs) {
 | 
				
			||||||
 | 
									this->DecompressedSize_ = rhs.DecompressedSize_;
 | 
				
			||||||
 | 
									this->CompressedData_ = rhs.CompressedData_;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								return *this;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							CompressedString& operator=(CompressedString&& rhs) {
 | 
				
			||||||
 | 
								if (this != &rhs) {
 | 
				
			||||||
 | 
									this->DecompressedSize_ = rhs.DecompressedSize_;
 | 
				
			||||||
 | 
									this->CompressedData_ = rhs.CompressedData_;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								return *this;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							~CompressedString() = default;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							operator std::string() const {
 | 
				
			||||||
 | 
								return DecompressIt();
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							CompressedString &operator=(const std::string &Data) {
 | 
				
			||||||
 | 
								DecompressedSize_ = Data.size();
 | 
				
			||||||
 | 
								CompressIt(Data);
 | 
				
			||||||
 | 
								return *this;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							auto CompressedSize() const { return CompressedData_.size(); }
 | 
				
			||||||
 | 
							auto DecompressedSize() const { return DecompressedSize_; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						  private:
 | 
				
			||||||
 | 
							std::string     CompressedData_;
 | 
				
			||||||
 | 
							std::size_t     DecompressedSize_;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							inline void CompressIt(const std::string &Data) {
 | 
				
			||||||
 | 
								z_stream strm; // = {0};
 | 
				
			||||||
 | 
								CompressedData_.resize(Data.size());
 | 
				
			||||||
 | 
								strm.next_in = (Bytef *)Data.data();
 | 
				
			||||||
 | 
								strm.avail_in = Data.size();
 | 
				
			||||||
 | 
								strm.next_out = (Bytef *)CompressedData_.data();
 | 
				
			||||||
 | 
								strm.avail_out = Data.size();
 | 
				
			||||||
 | 
								strm.zalloc = Z_NULL;
 | 
				
			||||||
 | 
								strm.zfree = Z_NULL;
 | 
				
			||||||
 | 
								strm.opaque = Z_NULL;
 | 
				
			||||||
 | 
								deflateInit2(&strm, Z_DEFAULT_COMPRESSION, Z_DEFLATED, 15 + 16, 8, Z_DEFAULT_STRATEGY);
 | 
				
			||||||
 | 
								deflate(&strm, Z_FINISH);
 | 
				
			||||||
 | 
								deflateEnd(&strm);
 | 
				
			||||||
 | 
								CompressedData_.resize(strm.total_out);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							[[nodiscard]] std::string DecompressIt() const {
 | 
				
			||||||
 | 
								std::string Result;
 | 
				
			||||||
 | 
								if(DecompressedSize_!=0) {
 | 
				
			||||||
 | 
									Result.resize(DecompressedSize_);
 | 
				
			||||||
 | 
									z_stream strm ; //= {0};
 | 
				
			||||||
 | 
									strm.next_in = (Bytef *)CompressedData_.data();
 | 
				
			||||||
 | 
									strm.avail_in = CompressedData_.size();
 | 
				
			||||||
 | 
									strm.next_out = (Bytef *)Result.data();
 | 
				
			||||||
 | 
									strm.avail_out = Result.size();
 | 
				
			||||||
 | 
									strm.zalloc = Z_NULL;
 | 
				
			||||||
 | 
									strm.zfree = Z_NULL;
 | 
				
			||||||
 | 
									strm.opaque = Z_NULL;
 | 
				
			||||||
 | 
									inflateInit2(&strm, 15 + 32);
 | 
				
			||||||
 | 
									inflate(&strm, Z_FINISH);
 | 
				
			||||||
 | 
									inflateEnd(&strm);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								return Result;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
} // namespace OpenWifi::Utils
 | 
					} // namespace OpenWifi::Utils
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -146,7 +146,7 @@ namespace OpenWifi {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
				auto WebClientSecureContext =
 | 
									auto WebClientSecureContext =
 | 
				
			||||||
					new Poco::Net::Context(Poco::Net::Context::SERVER_USE, KeyFileName,
 | 
										new Poco::Net::Context(Poco::Net::Context::SERVER_USE, KeyFileName,
 | 
				
			||||||
										   CertFileName, "", Poco::Net::Context::VERIFY_RELAXED);
 | 
															   CertFileName, "", Poco::Net::Context::VERIFY_NONE);
 | 
				
			||||||
				Poco::Crypto::X509Certificate WebRoot(RootCaFileName);
 | 
									Poco::Crypto::X509Certificate WebRoot(RootCaFileName);
 | 
				
			||||||
				WebClientSecureContext->addCertificateAuthority(WebRoot);
 | 
									WebClientSecureContext->addCertificateAuthority(WebRoot);
 | 
				
			||||||
				WebClientSecureContext->disableStatelessSessionResumption();
 | 
									WebClientSecureContext->disableStatelessSessionResumption();
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -56,10 +56,10 @@ namespace OpenWifi {
 | 
				
			|||||||
	struct DeviceDetails {
 | 
						struct DeviceDetails {
 | 
				
			||||||
		std::string reason;
 | 
							std::string reason;
 | 
				
			||||||
		std::string author;
 | 
							std::string author;
 | 
				
			||||||
		std::uint64_t created;
 | 
							std::uint64_t created=Utils::Now();
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	static std::map<std::string, DeviceDetails> BlackListDevices;
 | 
						static std::map<std::uint64_t , DeviceDetails> BlackListDevices;
 | 
				
			||||||
	static std::recursive_mutex BlackListMutex;
 | 
						static std::recursive_mutex BlackListMutex;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	bool Storage::InitializeBlackListCache() {
 | 
						bool Storage::InitializeBlackListCache() {
 | 
				
			||||||
@@ -78,7 +78,7 @@ namespace OpenWifi {
 | 
				
			|||||||
				auto Reason = RSet[1].convert<std::string>();
 | 
									auto Reason = RSet[1].convert<std::string>();
 | 
				
			||||||
				auto Author = RSet[2].convert<std::string>();
 | 
									auto Author = RSet[2].convert<std::string>();
 | 
				
			||||||
				auto Created = RSet[3].convert<std::uint64_t>();
 | 
									auto Created = RSet[3].convert<std::uint64_t>();
 | 
				
			||||||
				BlackListDevices[SerialNumber] =
 | 
									BlackListDevices[Utils::MACToInt(SerialNumber)] =
 | 
				
			||||||
					DeviceDetails{.reason = Reason, .author = Author, .created = Created};
 | 
										DeviceDetails{.reason = Reason, .author = Author, .created = Created};
 | 
				
			||||||
				More = RSet.moveNext();
 | 
									More = RSet.moveNext();
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
@@ -93,6 +93,7 @@ namespace OpenWifi {
 | 
				
			|||||||
	bool Storage::AddBlackListDevice(GWObjects::BlackListedDevice &Device) {
 | 
						bool Storage::AddBlackListDevice(GWObjects::BlackListedDevice &Device) {
 | 
				
			||||||
		try {
 | 
							try {
 | 
				
			||||||
			Poco::Data::Session Sess = Pool_->get();
 | 
								Poco::Data::Session Sess = Pool_->get();
 | 
				
			||||||
 | 
								Sess.begin();
 | 
				
			||||||
			Poco::Data::Statement Insert(Sess);
 | 
								Poco::Data::Statement Insert(Sess);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			std::string St{"INSERT INTO BlackList (" + DB_BlackListDeviceSelectFields + ") " +
 | 
								std::string St{"INSERT INTO BlackList (" + DB_BlackListDeviceSelectFields + ") " +
 | 
				
			||||||
@@ -102,9 +103,9 @@ namespace OpenWifi {
 | 
				
			|||||||
			ConvertBlackListDeviceRecord(Device, T);
 | 
								ConvertBlackListDeviceRecord(Device, T);
 | 
				
			||||||
			Insert << ConvertParams(St), Poco::Data::Keywords::use(T);
 | 
								Insert << ConvertParams(St), Poco::Data::Keywords::use(T);
 | 
				
			||||||
			Insert.execute();
 | 
								Insert.execute();
 | 
				
			||||||
 | 
								Sess.commit();
 | 
				
			||||||
			std::lock_guard G(BlackListMutex);
 | 
								std::lock_guard G(BlackListMutex);
 | 
				
			||||||
			BlackListDevices[Device.serialNumber] = DeviceDetails{
 | 
								BlackListDevices[Utils::MACToInt(Device.serialNumber)] = DeviceDetails{
 | 
				
			||||||
				.reason = Device.reason, .author = Device.author, .created = Device.created};
 | 
									.reason = Device.reason, .author = Device.author, .created = Device.created};
 | 
				
			||||||
			return true;
 | 
								return true;
 | 
				
			||||||
		} catch (const Poco::Exception &E) {
 | 
							} catch (const Poco::Exception &E) {
 | 
				
			||||||
@@ -130,6 +131,7 @@ namespace OpenWifi {
 | 
				
			|||||||
	bool Storage::DeleteBlackListDevice(std::string &SerialNumber) {
 | 
						bool Storage::DeleteBlackListDevice(std::string &SerialNumber) {
 | 
				
			||||||
		try {
 | 
							try {
 | 
				
			||||||
			Poco::Data::Session Sess = Pool_->get();
 | 
								Poco::Data::Session Sess = Pool_->get();
 | 
				
			||||||
 | 
								Sess.begin();
 | 
				
			||||||
			Poco::Data::Statement Delete(Sess);
 | 
								Poco::Data::Statement Delete(Sess);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			std::string St{"DELETE FROM BlackList WHERE SerialNumber=?"};
 | 
								std::string St{"DELETE FROM BlackList WHERE SerialNumber=?"};
 | 
				
			||||||
@@ -137,9 +139,9 @@ namespace OpenWifi {
 | 
				
			|||||||
			Poco::toLowerInPlace(SerialNumber);
 | 
								Poco::toLowerInPlace(SerialNumber);
 | 
				
			||||||
			Delete << ConvertParams(St), Poco::Data::Keywords::use(SerialNumber);
 | 
								Delete << ConvertParams(St), Poco::Data::Keywords::use(SerialNumber);
 | 
				
			||||||
			Delete.execute();
 | 
								Delete.execute();
 | 
				
			||||||
 | 
								Sess.commit();
 | 
				
			||||||
			std::lock_guard G(BlackListMutex);
 | 
								std::lock_guard G(BlackListMutex);
 | 
				
			||||||
			BlackListDevices.erase(SerialNumber);
 | 
								BlackListDevices.erase(Utils::MACToInt(SerialNumber));
 | 
				
			||||||
			return true;
 | 
								return true;
 | 
				
			||||||
		} catch (const Poco::Exception &E) {
 | 
							} catch (const Poco::Exception &E) {
 | 
				
			||||||
			poco_warning(Logger(), fmt::format("{}: Failed with: {}", std::string(__func__),
 | 
								poco_warning(Logger(), fmt::format("{}: Failed with: {}", std::string(__func__),
 | 
				
			||||||
@@ -177,6 +179,7 @@ namespace OpenWifi {
 | 
				
			|||||||
										GWObjects::BlackListedDevice &Device) {
 | 
															GWObjects::BlackListedDevice &Device) {
 | 
				
			||||||
		try {
 | 
							try {
 | 
				
			||||||
			Poco::Data::Session Sess = Pool_->get();
 | 
								Poco::Data::Session Sess = Pool_->get();
 | 
				
			||||||
 | 
								Sess.begin();
 | 
				
			||||||
			Poco::Data::Statement Update(Sess);
 | 
								Poco::Data::Statement Update(Sess);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			std::string St{"UPDATE BlackList SET " + DB_BlackListDeviceUpdateFields +
 | 
								std::string St{"UPDATE BlackList SET " + DB_BlackListDeviceUpdateFields +
 | 
				
			||||||
@@ -187,9 +190,9 @@ namespace OpenWifi {
 | 
				
			|||||||
			Update << ConvertParams(St), Poco::Data::Keywords::use(T),
 | 
								Update << ConvertParams(St), Poco::Data::Keywords::use(T),
 | 
				
			||||||
				Poco::Data::Keywords::use(SerialNumber);
 | 
									Poco::Data::Keywords::use(SerialNumber);
 | 
				
			||||||
			Update.execute();
 | 
								Update.execute();
 | 
				
			||||||
 | 
								Sess.commit();
 | 
				
			||||||
			std::lock_guard G(BlackListMutex);
 | 
								std::lock_guard G(BlackListMutex);
 | 
				
			||||||
			BlackListDevices[Device.serialNumber] = DeviceDetails{
 | 
								BlackListDevices[Utils::MACToInt(Device.serialNumber)] = DeviceDetails{
 | 
				
			||||||
				.reason = Device.reason, .author = Device.author, .created = Device.created};
 | 
									.reason = Device.reason, .author = Device.author, .created = Device.created};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			return true;
 | 
								return true;
 | 
				
			||||||
@@ -233,10 +236,10 @@ namespace OpenWifi {
 | 
				
			|||||||
		return BlackListDevices.size();
 | 
							return BlackListDevices.size();
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	bool Storage::IsBlackListed(const std::string &SerialNumber, std::string &reason,
 | 
						bool Storage::IsBlackListed(std::uint64_t SerialNumber, std::string &reason,
 | 
				
			||||||
								std::string &author, std::uint64_t &created) {
 | 
													std::string &author, std::uint64_t &created) {
 | 
				
			||||||
		std::lock_guard G(BlackListMutex);
 | 
							std::lock_guard G(BlackListMutex);
 | 
				
			||||||
		auto DeviceHint = BlackListDevices.find(Poco::toLower(SerialNumber));
 | 
							auto DeviceHint = BlackListDevices.find(SerialNumber);
 | 
				
			||||||
		if (DeviceHint == end(BlackListDevices))
 | 
							if (DeviceHint == end(BlackListDevices))
 | 
				
			||||||
			return false;
 | 
								return false;
 | 
				
			||||||
		reason = DeviceHint->second.reason;
 | 
							reason = DeviceHint->second.reason;
 | 
				
			||||||
@@ -245,9 +248,9 @@ namespace OpenWifi {
 | 
				
			|||||||
		return true;
 | 
							return true;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	bool Storage::IsBlackListed(const std::string &SerialNumber) {
 | 
						bool Storage::IsBlackListed(std::uint64_t SerialNumber) {
 | 
				
			||||||
		std::lock_guard G(BlackListMutex);
 | 
							std::lock_guard G(BlackListMutex);
 | 
				
			||||||
		auto DeviceHint = BlackListDevices.find(Poco::toLower(SerialNumber));
 | 
							auto DeviceHint = BlackListDevices.find(SerialNumber);
 | 
				
			||||||
		return DeviceHint != end(BlackListDevices);
 | 
							return DeviceHint != end(BlackListDevices);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
} // namespace OpenWifi
 | 
					} // namespace OpenWifi
 | 
				
			||||||
@@ -17,11 +17,11 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
namespace OpenWifi {
 | 
					namespace OpenWifi {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	bool Storage::CreateDeviceCapabilities(std::string &SerialNumber,
 | 
						bool Storage::CreateDeviceCapabilities(Poco::Data::Session &Session, std::string &SerialNumber,
 | 
				
			||||||
										   const Config::Capabilities &Capabilities) {
 | 
															   const Config::Capabilities &Capabilities) {
 | 
				
			||||||
		try {
 | 
							try {
 | 
				
			||||||
			Poco::Data::Session Sess = Pool_->get();
 | 
								Session.begin();
 | 
				
			||||||
			Poco::Data::Statement UpSert(Sess);
 | 
								Poco::Data::Statement UpSert(Session);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			std::string TCaps{Capabilities.AsString()};
 | 
								std::string TCaps{Capabilities.AsString()};
 | 
				
			||||||
			uint64_t Now = Utils::Now();
 | 
								uint64_t Now = Utils::Now();
 | 
				
			||||||
@@ -33,6 +33,7 @@ namespace OpenWifi {
 | 
				
			|||||||
				Poco::Data::Keywords::use(Now), Poco::Data::Keywords::use(TCaps),
 | 
									Poco::Data::Keywords::use(Now), Poco::Data::Keywords::use(TCaps),
 | 
				
			||||||
				Poco::Data::Keywords::use(Now);
 | 
									Poco::Data::Keywords::use(Now);
 | 
				
			||||||
			UpSert.execute();
 | 
								UpSert.execute();
 | 
				
			||||||
 | 
								Session.commit();
 | 
				
			||||||
			return true;
 | 
								return true;
 | 
				
			||||||
		} catch (const Poco::Exception &E) {
 | 
							} catch (const Poco::Exception &E) {
 | 
				
			||||||
			poco_warning(Logger(), fmt::format("{}: Failed with: {}", std::string(__func__),
 | 
								poco_warning(Logger(), fmt::format("{}: Failed with: {}", std::string(__func__),
 | 
				
			||||||
@@ -41,11 +42,11 @@ namespace OpenWifi {
 | 
				
			|||||||
		return false;
 | 
							return false;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	bool Storage::UpdateDeviceCapabilities(std::string &SerialNumber,
 | 
						bool Storage::UpdateDeviceCapabilities(Poco::Data::Session &Session, std::string &SerialNumber,
 | 
				
			||||||
										   const Config::Capabilities &Caps) {
 | 
															   const Config::Capabilities &Caps) {
 | 
				
			||||||
		try {
 | 
							try {
 | 
				
			||||||
			Poco::Data::Session Sess = Pool_->get();
 | 
								Session.begin();
 | 
				
			||||||
			Poco::Data::Statement UpSert(Sess);
 | 
								Poco::Data::Statement UpSert(Session);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			uint64_t Now = Utils::Now();
 | 
								uint64_t Now = Utils::Now();
 | 
				
			||||||
			if (!Caps.Compatible().empty() && !Caps.Platform().empty())
 | 
								if (!Caps.Compatible().empty() && !Caps.Platform().empty())
 | 
				
			||||||
@@ -61,6 +62,7 @@ namespace OpenWifi {
 | 
				
			|||||||
				Poco::Data::Keywords::use(Now), Poco::Data::Keywords::use(TCaps),
 | 
									Poco::Data::Keywords::use(Now), Poco::Data::Keywords::use(TCaps),
 | 
				
			||||||
				Poco::Data::Keywords::use(Now);
 | 
									Poco::Data::Keywords::use(Now);
 | 
				
			||||||
			UpSert.execute();
 | 
								UpSert.execute();
 | 
				
			||||||
 | 
								Session.commit();
 | 
				
			||||||
			return true;
 | 
								return true;
 | 
				
			||||||
		} catch (const Poco::Exception &E) {
 | 
							} catch (const Poco::Exception &E) {
 | 
				
			||||||
			poco_warning(Logger(), fmt::format("{}: Failed with: {}", std::string(__func__),
 | 
								poco_warning(Logger(), fmt::format("{}: Failed with: {}", std::string(__func__),
 | 
				
			||||||
@@ -99,13 +101,14 @@ namespace OpenWifi {
 | 
				
			|||||||
	bool Storage::DeleteDeviceCapabilities(std::string &SerialNumber) {
 | 
						bool Storage::DeleteDeviceCapabilities(std::string &SerialNumber) {
 | 
				
			||||||
		try {
 | 
							try {
 | 
				
			||||||
			Poco::Data::Session Sess = Pool_->get();
 | 
								Poco::Data::Session Sess = Pool_->get();
 | 
				
			||||||
 | 
								Sess.begin();
 | 
				
			||||||
			Poco::Data::Statement Delete(Sess);
 | 
								Poco::Data::Statement Delete(Sess);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			std::string St{"DELETE FROM Capabilities WHERE SerialNumber=?"};
 | 
								std::string St{"DELETE FROM Capabilities WHERE SerialNumber=?"};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			Delete << ConvertParams(St), Poco::Data::Keywords::use(SerialNumber);
 | 
								Delete << ConvertParams(St), Poco::Data::Keywords::use(SerialNumber);
 | 
				
			||||||
			Delete.execute();
 | 
								Delete.execute();
 | 
				
			||||||
 | 
								Sess.commit();
 | 
				
			||||||
			return true;
 | 
								return true;
 | 
				
			||||||
		} catch (const Poco::Exception &E) {
 | 
							} catch (const Poco::Exception &E) {
 | 
				
			||||||
			poco_warning(Logger(), fmt::format("{}: Failed with: {}", std::string(__func__),
 | 
								poco_warning(Logger(), fmt::format("{}: Failed with: {}", std::string(__func__),
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -105,6 +105,7 @@ namespace OpenWifi {
 | 
				
			|||||||
	bool Storage::RemoveOldCommands(std::string &SerialNumber, std::string &Command) {
 | 
						bool Storage::RemoveOldCommands(std::string &SerialNumber, std::string &Command) {
 | 
				
			||||||
		try {
 | 
							try {
 | 
				
			||||||
			Poco::Data::Session Sess = Pool_->get();
 | 
								Poco::Data::Session Sess = Pool_->get();
 | 
				
			||||||
 | 
								Sess.begin();
 | 
				
			||||||
			Poco::Data::Statement Delete(Sess);
 | 
								Poco::Data::Statement Delete(Sess);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			std::string St{
 | 
								std::string St{
 | 
				
			||||||
@@ -112,8 +113,7 @@ namespace OpenWifi {
 | 
				
			|||||||
			Delete << ConvertParams(St), Poco::Data::Keywords::use(SerialNumber),
 | 
								Delete << ConvertParams(St), Poco::Data::Keywords::use(SerialNumber),
 | 
				
			||||||
				Poco::Data::Keywords::use(Command);
 | 
									Poco::Data::Keywords::use(Command);
 | 
				
			||||||
			Delete.execute();
 | 
								Delete.execute();
 | 
				
			||||||
			Delete.reset(Sess);
 | 
								Sess.commit();
 | 
				
			||||||
 | 
					 | 
				
			||||||
			return true;
 | 
								return true;
 | 
				
			||||||
		} catch (const Poco::Exception &E) {
 | 
							} catch (const Poco::Exception &E) {
 | 
				
			||||||
			Logger().log(E);
 | 
								Logger().log(E);
 | 
				
			||||||
@@ -146,6 +146,7 @@ namespace OpenWifi {
 | 
				
			|||||||
			RemoveOldCommands(SerialNumber, Command.Command);
 | 
								RemoveOldCommands(SerialNumber, Command.Command);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			Poco::Data::Session Sess = Pool_->get();
 | 
								Poco::Data::Session Sess = Pool_->get();
 | 
				
			||||||
 | 
								Sess.begin();
 | 
				
			||||||
			Poco::Data::Statement Insert(Sess);
 | 
								Poco::Data::Statement Insert(Sess);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			std::string St{"INSERT INTO CommandList ( " + DB_Command_SelectFields + " ) VALUES( " +
 | 
								std::string St{"INSERT INTO CommandList ( " + DB_Command_SelectFields + " ) VALUES( " +
 | 
				
			||||||
@@ -156,7 +157,7 @@ namespace OpenWifi {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
			Insert << ConvertParams(St), Poco::Data::Keywords::use(R);
 | 
								Insert << ConvertParams(St), Poco::Data::Keywords::use(R);
 | 
				
			||||||
			Insert.execute();
 | 
								Insert.execute();
 | 
				
			||||||
 | 
								Sess.commit();
 | 
				
			||||||
			return true;
 | 
								return true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		} catch (const Poco::Exception &E) {
 | 
							} catch (const Poco::Exception &E) {
 | 
				
			||||||
@@ -215,6 +216,7 @@ namespace OpenWifi {
 | 
				
			|||||||
	bool Storage::DeleteCommands(std::string &SerialNumber, uint64_t FromDate, uint64_t ToDate) {
 | 
						bool Storage::DeleteCommands(std::string &SerialNumber, uint64_t FromDate, uint64_t ToDate) {
 | 
				
			||||||
		try {
 | 
							try {
 | 
				
			||||||
			Poco::Data::Session Sess = Pool_->get();
 | 
								Poco::Data::Session Sess = Pool_->get();
 | 
				
			||||||
 | 
								Sess.begin();
 | 
				
			||||||
			Poco::Data::Statement Delete(Sess);
 | 
								Poco::Data::Statement Delete(Sess);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			bool DatesIncluded = (FromDate != 0 || ToDate != 0);
 | 
								bool DatesIncluded = (FromDate != 0 || ToDate != 0);
 | 
				
			||||||
@@ -237,8 +239,7 @@ namespace OpenWifi {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
			Delete << IntroStatement + DateSelector;
 | 
								Delete << IntroStatement + DateSelector;
 | 
				
			||||||
			Delete.execute();
 | 
								Delete.execute();
 | 
				
			||||||
			Delete.reset(Sess);
 | 
								Sess.commit();
 | 
				
			||||||
 | 
					 | 
				
			||||||
			return true;
 | 
								return true;
 | 
				
			||||||
		} catch (const Poco::Exception &E) {
 | 
							} catch (const Poco::Exception &E) {
 | 
				
			||||||
			Logger().log(E);
 | 
								Logger().log(E);
 | 
				
			||||||
@@ -274,7 +275,6 @@ namespace OpenWifi {
 | 
				
			|||||||
				if (Records.size() < HowMany)
 | 
									if (Records.size() < HowMany)
 | 
				
			||||||
					Done = true;
 | 
										Done = true;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			Select.reset(Sess);
 | 
					 | 
				
			||||||
			return true;
 | 
								return true;
 | 
				
			||||||
		} catch (const Poco::Exception &E) {
 | 
							} catch (const Poco::Exception &E) {
 | 
				
			||||||
			Logger().log(E);
 | 
								Logger().log(E);
 | 
				
			||||||
@@ -286,6 +286,7 @@ namespace OpenWifi {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
		try {
 | 
							try {
 | 
				
			||||||
			Poco::Data::Session Sess = Pool_->get();
 | 
								Poco::Data::Session Sess = Pool_->get();
 | 
				
			||||||
 | 
								Sess.begin();
 | 
				
			||||||
			Poco::Data::Statement Update(Sess);
 | 
								Poco::Data::Statement Update(Sess);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			std::string St{"UPDATE CommandList SET Status=?,  Executed=?,  Completed=?,  "
 | 
								std::string St{"UPDATE CommandList SET Status=?,  Executed=?,  Completed=?,  "
 | 
				
			||||||
@@ -299,7 +300,7 @@ namespace OpenWifi {
 | 
				
			|||||||
				Poco::Data::Keywords::use(Command.ErrorCode), Poco::Data::Keywords::use(UUID);
 | 
									Poco::Data::Keywords::use(Command.ErrorCode), Poco::Data::Keywords::use(UUID);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			Update.execute();
 | 
								Update.execute();
 | 
				
			||||||
 | 
								Sess.commit();
 | 
				
			||||||
			return true;
 | 
								return true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		} catch (const Poco::Exception &E) {
 | 
							} catch (const Poco::Exception &E) {
 | 
				
			||||||
@@ -311,6 +312,7 @@ namespace OpenWifi {
 | 
				
			|||||||
	bool Storage::SetCommandExecuted(std::string &CommandUUID) {
 | 
						bool Storage::SetCommandExecuted(std::string &CommandUUID) {
 | 
				
			||||||
		try {
 | 
							try {
 | 
				
			||||||
			Poco::Data::Session Sess = Pool_->get();
 | 
								Poco::Data::Session Sess = Pool_->get();
 | 
				
			||||||
 | 
								Sess.begin();
 | 
				
			||||||
			Poco::Data::Statement Update(Sess);
 | 
								Poco::Data::Statement Update(Sess);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			auto Now = Utils::Now();
 | 
								auto Now = Utils::Now();
 | 
				
			||||||
@@ -321,6 +323,7 @@ namespace OpenWifi {
 | 
				
			|||||||
			Update << ConvertParams(St), Poco::Data::Keywords::use(Now),
 | 
								Update << ConvertParams(St), Poco::Data::Keywords::use(Now),
 | 
				
			||||||
				Poco::Data::Keywords::use(Status), Poco::Data::Keywords::use(CommandUUID);
 | 
									Poco::Data::Keywords::use(Status), Poco::Data::Keywords::use(CommandUUID);
 | 
				
			||||||
			Update.execute();
 | 
								Update.execute();
 | 
				
			||||||
 | 
								Sess.commit();
 | 
				
			||||||
			return true;
 | 
								return true;
 | 
				
			||||||
		} catch (const Poco::Exception &E) {
 | 
							} catch (const Poco::Exception &E) {
 | 
				
			||||||
			Logger().log(E);
 | 
								Logger().log(E);
 | 
				
			||||||
@@ -331,6 +334,7 @@ namespace OpenWifi {
 | 
				
			|||||||
	void Storage::RemovedExpiredCommands() {
 | 
						void Storage::RemovedExpiredCommands() {
 | 
				
			||||||
		try {
 | 
							try {
 | 
				
			||||||
			Poco::Data::Session Sess = Pool_->get();
 | 
								Poco::Data::Session Sess = Pool_->get();
 | 
				
			||||||
 | 
								Sess.begin();
 | 
				
			||||||
			Poco::Data::Statement Update(Sess);
 | 
								Poco::Data::Statement Update(Sess);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			auto Now = Utils::Now(), Window = Now - CommandManager()->CommandTimeout();
 | 
								auto Now = Utils::Now(), Window = Now - CommandManager()->CommandTimeout();
 | 
				
			||||||
@@ -341,8 +345,7 @@ namespace OpenWifi {
 | 
				
			|||||||
			Update << ConvertParams(St), Poco::Data::Keywords::use(Now),
 | 
								Update << ConvertParams(St), Poco::Data::Keywords::use(Now),
 | 
				
			||||||
				Poco::Data::Keywords::use(Status), Poco::Data::Keywords::use(Window);
 | 
									Poco::Data::Keywords::use(Status), Poco::Data::Keywords::use(Window);
 | 
				
			||||||
			Update.execute();
 | 
								Update.execute();
 | 
				
			||||||
			Update.reset(Sess);
 | 
								Sess.commit();
 | 
				
			||||||
 | 
					 | 
				
			||||||
		} catch (const Poco::Exception &E) {
 | 
							} catch (const Poco::Exception &E) {
 | 
				
			||||||
			Logger().log(E);
 | 
								Logger().log(E);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
@@ -351,6 +354,7 @@ namespace OpenWifi {
 | 
				
			|||||||
	bool Storage::SetCommandLastTry(std::string &CommandUUID) {
 | 
						bool Storage::SetCommandLastTry(std::string &CommandUUID) {
 | 
				
			||||||
		try {
 | 
							try {
 | 
				
			||||||
			Poco::Data::Session Sess = Pool_->get();
 | 
								Poco::Data::Session Sess = Pool_->get();
 | 
				
			||||||
 | 
								Sess.begin();
 | 
				
			||||||
			Poco::Data::Statement Update(Sess);
 | 
								Poco::Data::Statement Update(Sess);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			auto Now = Utils::Now();
 | 
								auto Now = Utils::Now();
 | 
				
			||||||
@@ -359,6 +363,7 @@ namespace OpenWifi {
 | 
				
			|||||||
			Update << ConvertParams(St), Poco::Data::Keywords::use(Now),
 | 
								Update << ConvertParams(St), Poco::Data::Keywords::use(Now),
 | 
				
			||||||
				Poco::Data::Keywords::use(CommandUUID);
 | 
									Poco::Data::Keywords::use(CommandUUID);
 | 
				
			||||||
			Update.execute();
 | 
								Update.execute();
 | 
				
			||||||
 | 
								Sess.commit();
 | 
				
			||||||
			return true;
 | 
								return true;
 | 
				
			||||||
		} catch (const Poco::Exception &E) {
 | 
							} catch (const Poco::Exception &E) {
 | 
				
			||||||
			Logger().log(E);
 | 
								Logger().log(E);
 | 
				
			||||||
@@ -369,6 +374,7 @@ namespace OpenWifi {
 | 
				
			|||||||
	void Storage::RemoveTimedOutCommands() {
 | 
						void Storage::RemoveTimedOutCommands() {
 | 
				
			||||||
		try {
 | 
							try {
 | 
				
			||||||
			Poco::Data::Session Sess = Pool_->get();
 | 
								Poco::Data::Session Sess = Pool_->get();
 | 
				
			||||||
 | 
								Sess.begin();
 | 
				
			||||||
			Poco::Data::Statement Update(Sess);
 | 
								Poco::Data::Statement Update(Sess);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			auto Now = Utils::Now(), Window = Now - CommandManager()->CommandTimeout();
 | 
								auto Now = Utils::Now(), Window = Now - CommandManager()->CommandTimeout();
 | 
				
			||||||
@@ -377,7 +383,7 @@ namespace OpenWifi {
 | 
				
			|||||||
			Update << ConvertParams(St), Poco::Data::Keywords::use(Now),
 | 
								Update << ConvertParams(St), Poco::Data::Keywords::use(Now),
 | 
				
			||||||
				Poco::Data::Keywords::use(Window);
 | 
									Poco::Data::Keywords::use(Window);
 | 
				
			||||||
			Update.execute();
 | 
								Update.execute();
 | 
				
			||||||
			Update.reset(Sess);
 | 
								Sess.commit();
 | 
				
			||||||
		} catch (const Poco::Exception &E) {
 | 
							} catch (const Poco::Exception &E) {
 | 
				
			||||||
			Logger().log(E);
 | 
								Logger().log(E);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
@@ -386,6 +392,7 @@ namespace OpenWifi {
 | 
				
			|||||||
	bool Storage::SetCommandTimedOut(std::string &CommandUUID) {
 | 
						bool Storage::SetCommandTimedOut(std::string &CommandUUID) {
 | 
				
			||||||
		try {
 | 
							try {
 | 
				
			||||||
			Poco::Data::Session Sess = Pool_->get();
 | 
								Poco::Data::Session Sess = Pool_->get();
 | 
				
			||||||
 | 
								Sess.begin();
 | 
				
			||||||
			Poco::Data::Statement Update(Sess);
 | 
								Poco::Data::Statement Update(Sess);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			auto Now = Utils::Now();
 | 
								auto Now = Utils::Now();
 | 
				
			||||||
@@ -395,6 +402,7 @@ namespace OpenWifi {
 | 
				
			|||||||
			Update << ConvertParams(St), Poco::Data::Keywords::use(Now),
 | 
								Update << ConvertParams(St), Poco::Data::Keywords::use(Now),
 | 
				
			||||||
				Poco::Data::Keywords::use(Status), Poco::Data::Keywords::use(CommandUUID);
 | 
									Poco::Data::Keywords::use(Status), Poco::Data::Keywords::use(CommandUUID);
 | 
				
			||||||
			Update.execute();
 | 
								Update.execute();
 | 
				
			||||||
 | 
								Sess.commit();
 | 
				
			||||||
			return true;
 | 
								return true;
 | 
				
			||||||
		} catch (const Poco::Exception &E) {
 | 
							} catch (const Poco::Exception &E) {
 | 
				
			||||||
			Logger().log(E);
 | 
								Logger().log(E);
 | 
				
			||||||
@@ -425,6 +433,7 @@ namespace OpenWifi {
 | 
				
			|||||||
	bool Storage::DeleteCommand(std::string &UUID) {
 | 
						bool Storage::DeleteCommand(std::string &UUID) {
 | 
				
			||||||
		try {
 | 
							try {
 | 
				
			||||||
			Poco::Data::Session Sess = Pool_->get();
 | 
								Poco::Data::Session Sess = Pool_->get();
 | 
				
			||||||
 | 
								Sess.begin();
 | 
				
			||||||
			Poco::Data::Statement Delete(Sess);
 | 
								Poco::Data::Statement Delete(Sess);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			std::string St{"DELETE FROM CommandList WHERE UUID=?"};
 | 
								std::string St{"DELETE FROM CommandList WHERE UUID=?"};
 | 
				
			||||||
@@ -435,8 +444,7 @@ namespace OpenWifi {
 | 
				
			|||||||
			St = "DELETE FROM FileUploads WHERE UUID=?";
 | 
								St = "DELETE FROM FileUploads WHERE UUID=?";
 | 
				
			||||||
			Delete << ConvertParams(St), Poco::Data::Keywords::use(UUID);
 | 
								Delete << ConvertParams(St), Poco::Data::Keywords::use(UUID);
 | 
				
			||||||
			Delete.execute();
 | 
								Delete.execute();
 | 
				
			||||||
			Delete.reset(Sess);
 | 
								Sess.commit();
 | 
				
			||||||
 | 
					 | 
				
			||||||
			return true;
 | 
								return true;
 | 
				
			||||||
		} catch (const Poco::Exception &E) {
 | 
							} catch (const Poco::Exception &E) {
 | 
				
			||||||
			Logger().log(E);
 | 
								Logger().log(E);
 | 
				
			||||||
@@ -510,6 +518,7 @@ namespace OpenWifi {
 | 
				
			|||||||
			auto Now = Utils::Now();
 | 
								auto Now = Utils::Now();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			Poco::Data::Session Sess = Pool_->get();
 | 
								Poco::Data::Session Sess = Pool_->get();
 | 
				
			||||||
 | 
								Sess.begin();
 | 
				
			||||||
			Poco::Data::Statement Update(Sess);
 | 
								Poco::Data::Statement Update(Sess);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			std::string St{"UPDATE CommandList SET Executed=? WHERE UUID=?"};
 | 
								std::string St{"UPDATE CommandList SET Executed=? WHERE UUID=?"};
 | 
				
			||||||
@@ -518,7 +527,7 @@ namespace OpenWifi {
 | 
				
			|||||||
				Poco::Data::Keywords::use(UUID);
 | 
									Poco::Data::Keywords::use(UUID);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			Update.execute();
 | 
								Update.execute();
 | 
				
			||||||
 | 
								Sess.commit();
 | 
				
			||||||
			return true;
 | 
								return true;
 | 
				
			||||||
		} catch (const Poco::Exception &E) {
 | 
							} catch (const Poco::Exception &E) {
 | 
				
			||||||
			Logger().log(E);
 | 
								Logger().log(E);
 | 
				
			||||||
@@ -555,6 +564,7 @@ namespace OpenWifi {
 | 
				
			|||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			Poco::Data::Session Sess = Pool_->get();
 | 
								Poco::Data::Session Sess = Pool_->get();
 | 
				
			||||||
 | 
								Sess.begin();
 | 
				
			||||||
			Poco::Data::Statement Update(Sess);
 | 
								Poco::Data::Statement Update(Sess);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			auto Status = to_string(Storage::CommandExecutionType::COMMAND_COMPLETED);
 | 
								auto Status = to_string(Storage::CommandExecutionType::COMMAND_COMPLETED);
 | 
				
			||||||
@@ -566,6 +576,7 @@ namespace OpenWifi {
 | 
				
			|||||||
				Poco::Data::Keywords::use(ResultStr), Poco::Data::Keywords::use(Status),
 | 
									Poco::Data::Keywords::use(ResultStr), Poco::Data::Keywords::use(Status),
 | 
				
			||||||
				Poco::Data::Keywords::use(tET), Poco::Data::Keywords::use(UUID);
 | 
									Poco::Data::Keywords::use(tET), Poco::Data::Keywords::use(UUID);
 | 
				
			||||||
			Update.execute();
 | 
								Update.execute();
 | 
				
			||||||
 | 
								Sess.commit();
 | 
				
			||||||
			return true;
 | 
								return true;
 | 
				
			||||||
		} catch (const Poco::Exception &E) {
 | 
							} catch (const Poco::Exception &E) {
 | 
				
			||||||
			Logger().log(E);
 | 
								Logger().log(E);
 | 
				
			||||||
@@ -603,6 +614,7 @@ namespace OpenWifi {
 | 
				
			|||||||
	bool Storage::CancelWaitFile(std::string &UUID, std::string &ErrorText) {
 | 
						bool Storage::CancelWaitFile(std::string &UUID, std::string &ErrorText) {
 | 
				
			||||||
		try {
 | 
							try {
 | 
				
			||||||
			Poco::Data::Session Sess = Pool_->get();
 | 
								Poco::Data::Session Sess = Pool_->get();
 | 
				
			||||||
 | 
								Sess.begin();
 | 
				
			||||||
			auto Now = Utils::Now();
 | 
								auto Now = Utils::Now();
 | 
				
			||||||
			uint64_t Size = 0, WaitForFile = 0;
 | 
								uint64_t Size = 0, WaitForFile = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -616,6 +628,7 @@ namespace OpenWifi {
 | 
				
			|||||||
				Poco::Data::Keywords::use(ErrorText), Poco::Data::Keywords::use(Now),
 | 
									Poco::Data::Keywords::use(ErrorText), Poco::Data::Keywords::use(Now),
 | 
				
			||||||
				Poco::Data::Keywords::use(UUID);
 | 
									Poco::Data::Keywords::use(UUID);
 | 
				
			||||||
			Update.execute();
 | 
								Update.execute();
 | 
				
			||||||
 | 
								Sess.commit();
 | 
				
			||||||
			return true;
 | 
								return true;
 | 
				
			||||||
		} catch (const Poco::Exception &E) {
 | 
							} catch (const Poco::Exception &E) {
 | 
				
			||||||
			Logger().log(E);
 | 
								Logger().log(E);
 | 
				
			||||||
@@ -631,27 +644,16 @@ namespace OpenWifi {
 | 
				
			|||||||
			uint64_t Size = FileContent.str().size();
 | 
								uint64_t Size = FileContent.str().size();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			Poco::Data::Session Sess = Pool_->get();
 | 
								Poco::Data::Session Sess = Pool_->get();
 | 
				
			||||||
 | 
								Sess.begin();
 | 
				
			||||||
			Poco::Data::Statement Statement(Sess);
 | 
								Poco::Data::Statement Statement(Sess);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			std::string StatementStr;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			//	Get the existing command
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			StatementStr =
 | 
					 | 
				
			||||||
				"UPDATE CommandList SET WaitingForFile=?, AttachDate=?, AttachSize=? WHERE UUID=?";
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			Statement << ConvertParams(StatementStr), Poco::Data::Keywords::use(WaitForFile),
 | 
					 | 
				
			||||||
				Poco::Data::Keywords::use(Now), Poco::Data::Keywords::use(Size),
 | 
					 | 
				
			||||||
				Poco::Data::Keywords::use(UUID);
 | 
					 | 
				
			||||||
			Statement.execute();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			if (Size < FileUploader()->MaxSize()) {
 | 
								if (Size < FileUploader()->MaxSize()) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				Poco::Data::BLOB TheBlob;
 | 
									Poco::Data::BLOB TheBlob;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				TheBlob.appendRaw((const unsigned char *)FileContent.str().c_str(),
 | 
									TheBlob.appendRaw((const unsigned char *)FileContent.str().c_str(),
 | 
				
			||||||
								  FileContent.str().size());
 | 
													  FileContent.str().size());
 | 
				
			||||||
 | 
									Sess.begin();
 | 
				
			||||||
				Poco::Data::Statement Insert(Sess);
 | 
									Poco::Data::Statement Insert(Sess);
 | 
				
			||||||
				std::string FileType{Type};
 | 
									std::string FileType{Type};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -662,10 +664,24 @@ namespace OpenWifi {
 | 
				
			|||||||
					Poco::Data::Keywords::use(FileType), Poco::Data::Keywords::use(Now),
 | 
										Poco::Data::Keywords::use(FileType), Poco::Data::Keywords::use(Now),
 | 
				
			||||||
					Poco::Data::Keywords::use(TheBlob);
 | 
										Poco::Data::Keywords::use(TheBlob);
 | 
				
			||||||
				Insert.execute();
 | 
									Insert.execute();
 | 
				
			||||||
				return true;
 | 
									Sess.commit();
 | 
				
			||||||
			} else {
 | 
								} else {
 | 
				
			||||||
				poco_warning(Logger(), fmt::format("File {} is too large.", UUID));
 | 
									poco_warning(Logger(), fmt::format("File {} is too large.", UUID));
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
								Sess.commit();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								// update CommandList here to ensure that file us uploaded
 | 
				
			||||||
 | 
								std::string StatementStr;
 | 
				
			||||||
 | 
								StatementStr =
 | 
				
			||||||
 | 
									"UPDATE CommandList SET WaitingForFile=?, AttachDate=?, AttachSize=? WHERE UUID=?";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								Statement << ConvertParams(StatementStr), Poco::Data::Keywords::use(WaitForFile),
 | 
				
			||||||
 | 
									Poco::Data::Keywords::use(Now), Poco::Data::Keywords::use(Size),
 | 
				
			||||||
 | 
									Poco::Data::Keywords::use(UUID);
 | 
				
			||||||
 | 
								Statement.execute();
 | 
				
			||||||
 | 
								Sess.commit();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								return true;
 | 
				
			||||||
		} catch (const Poco::Exception &E) {
 | 
							} catch (const Poco::Exception &E) {
 | 
				
			||||||
			Logger().log(E);
 | 
								Logger().log(E);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
@@ -673,7 +689,7 @@ namespace OpenWifi {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	bool Storage::GetAttachedFileContent(std::string &UUID, const std::string &SerialNumber,
 | 
						bool Storage::GetAttachedFileContent(std::string &UUID, const std::string &SerialNumber,
 | 
				
			||||||
										 std::string &FileContent, std::string &Type) {
 | 
															 std::string &FileContent, std::string &Type, int &WaitingForFile) {
 | 
				
			||||||
		try {
 | 
							try {
 | 
				
			||||||
			Poco::Data::BLOB L;
 | 
								Poco::Data::BLOB L;
 | 
				
			||||||
			/*
 | 
								/*
 | 
				
			||||||
@@ -686,10 +702,10 @@ namespace OpenWifi {
 | 
				
			|||||||
			Poco::Data::Statement Select1(Sess);
 | 
								Poco::Data::Statement Select1(Sess);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			std::string TmpSerialNumber;
 | 
								std::string TmpSerialNumber;
 | 
				
			||||||
			std::string st1{"SELECT SerialNumber, Command FROM CommandList WHERE UUID=?"};
 | 
								std::string st1{"SELECT SerialNumber, Command , WaitingForFile FROM CommandList WHERE UUID=?"};
 | 
				
			||||||
			std::string Command;
 | 
								std::string Command;
 | 
				
			||||||
			Select1 << ConvertParams(st1), Poco::Data::Keywords::into(TmpSerialNumber),
 | 
								Select1 << ConvertParams(st1), Poco::Data::Keywords::into(TmpSerialNumber),
 | 
				
			||||||
				Poco::Data::Keywords::into(Command), Poco::Data::Keywords::use(UUID);
 | 
									Poco::Data::Keywords::into(Command), Poco::Data::Keywords::into(WaitingForFile), Poco::Data::Keywords::use(UUID);
 | 
				
			||||||
			Select1.execute();
 | 
								Select1.execute();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if (TmpSerialNumber != SerialNumber) {
 | 
								if (TmpSerialNumber != SerialNumber) {
 | 
				
			||||||
@@ -712,6 +728,7 @@ namespace OpenWifi {
 | 
				
			|||||||
	bool Storage::SetCommandResult(std::string &UUID, std::string &Result) {
 | 
						bool Storage::SetCommandResult(std::string &UUID, std::string &Result) {
 | 
				
			||||||
		try {
 | 
							try {
 | 
				
			||||||
			Poco::Data::Session Sess = Pool_->get();
 | 
								Poco::Data::Session Sess = Pool_->get();
 | 
				
			||||||
 | 
								Sess.begin();
 | 
				
			||||||
			Poco::Data::Statement Update(Sess);
 | 
								Poco::Data::Statement Update(Sess);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			auto Now = Utils::Now();
 | 
								auto Now = Utils::Now();
 | 
				
			||||||
@@ -722,6 +739,7 @@ namespace OpenWifi {
 | 
				
			|||||||
				Poco::Data::Keywords::use(Result), Poco::Data::Keywords::use(Status),
 | 
									Poco::Data::Keywords::use(Result), Poco::Data::Keywords::use(Status),
 | 
				
			||||||
				Poco::Data::Keywords::use(UUID);
 | 
									Poco::Data::Keywords::use(UUID);
 | 
				
			||||||
			Update.execute();
 | 
								Update.execute();
 | 
				
			||||||
 | 
								Sess.commit();
 | 
				
			||||||
			return true;
 | 
								return true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		} catch (const Poco::Exception &E) {
 | 
							} catch (const Poco::Exception &E) {
 | 
				
			||||||
@@ -733,13 +751,14 @@ namespace OpenWifi {
 | 
				
			|||||||
	bool Storage::RemoveAttachedFile(std::string &UUID) {
 | 
						bool Storage::RemoveAttachedFile(std::string &UUID) {
 | 
				
			||||||
		try {
 | 
							try {
 | 
				
			||||||
			Poco::Data::Session Sess = Pool_->get();
 | 
								Poco::Data::Session Sess = Pool_->get();
 | 
				
			||||||
 | 
								Sess.begin();
 | 
				
			||||||
			Poco::Data::Statement Delete(Sess);
 | 
								Poco::Data::Statement Delete(Sess);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			std::string St{"DELETE FROM FileUploads WHERE UUID=?"};
 | 
								std::string St{"DELETE FROM FileUploads WHERE UUID=?"};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			Delete << ConvertParams(St), Poco::Data::Keywords::use(UUID);
 | 
								Delete << ConvertParams(St), Poco::Data::Keywords::use(UUID);
 | 
				
			||||||
			Delete.execute();
 | 
								Delete.execute();
 | 
				
			||||||
 | 
								Sess.commit();
 | 
				
			||||||
			return true;
 | 
								return true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		} catch (const Poco::Exception &E) {
 | 
							} catch (const Poco::Exception &E) {
 | 
				
			||||||
@@ -751,11 +770,13 @@ namespace OpenWifi {
 | 
				
			|||||||
	bool Storage::RemoveUploadedFilesRecordsOlderThan(uint64_t Date) {
 | 
						bool Storage::RemoveUploadedFilesRecordsOlderThan(uint64_t Date) {
 | 
				
			||||||
		try {
 | 
							try {
 | 
				
			||||||
			Poco::Data::Session Sess = Pool_->get();
 | 
								Poco::Data::Session Sess = Pool_->get();
 | 
				
			||||||
 | 
								Sess.begin();
 | 
				
			||||||
			Poco::Data::Statement Delete(Sess);
 | 
								Poco::Data::Statement Delete(Sess);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			std::string St1{"delete from FileUploads where Created<?"};
 | 
								std::string St1{"delete from FileUploads where Created<?"};
 | 
				
			||||||
			Delete << ConvertParams(St1), Poco::Data::Keywords::use(Date);
 | 
								Delete << ConvertParams(St1), Poco::Data::Keywords::use(Date);
 | 
				
			||||||
			Delete.execute();
 | 
								Delete.execute();
 | 
				
			||||||
 | 
								Sess.commit();
 | 
				
			||||||
			return true;
 | 
								return true;
 | 
				
			||||||
		} catch (const Poco::Exception &E) {
 | 
							} catch (const Poco::Exception &E) {
 | 
				
			||||||
			Logger().log(E);
 | 
								Logger().log(E);
 | 
				
			||||||
@@ -766,11 +787,13 @@ namespace OpenWifi {
 | 
				
			|||||||
	bool Storage::RemoveCommandListRecordsOlderThan(uint64_t Date) {
 | 
						bool Storage::RemoveCommandListRecordsOlderThan(uint64_t Date) {
 | 
				
			||||||
		try {
 | 
							try {
 | 
				
			||||||
			Poco::Data::Session Sess = Pool_->get();
 | 
								Poco::Data::Session Sess = Pool_->get();
 | 
				
			||||||
 | 
								Sess.begin();
 | 
				
			||||||
			Poco::Data::Statement Delete(Sess);
 | 
								Poco::Data::Statement Delete(Sess);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			std::string St1{"delete from CommandList where Submitted<?"};
 | 
								std::string St1{"delete from CommandList where Submitted<?"};
 | 
				
			||||||
			Delete << ConvertParams(St1), Poco::Data::Keywords::use(Date);
 | 
								Delete << ConvertParams(St1), Poco::Data::Keywords::use(Date);
 | 
				
			||||||
			Delete.execute();
 | 
								Delete.execute();
 | 
				
			||||||
 | 
								Sess.commit();
 | 
				
			||||||
			return true;
 | 
								return true;
 | 
				
			||||||
		} catch (const Poco::Exception &E) {
 | 
							} catch (const Poco::Exception &E) {
 | 
				
			||||||
			Logger().log(E);
 | 
								Logger().log(E);
 | 
				
			||||||
 
 | 
				
			|||||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user