Initial port of PAWS-C

This commit is contained in:
Kashif Ali
2020-04-03 12:10:53 -07:00
parent 6443a0143d
commit cf6a655f6d
7266 changed files with 7939036 additions and 263 deletions

View File

@@ -1,184 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<?fileVersion 4.0.0?><cproject storage_type_id="org.eclipse.cdt.core.XmlProjectDescriptionStorage">
<storageModule moduleId="org.eclipse.cdt.core.settings">
<cconfiguration id="0.1782736718">
<storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="0.1782736718" moduleId="org.eclipse.cdt.core.settings" name="Default">
<externalSettings/>
<extensions>
<extension id="org.eclipse.cdt.core.VCErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
<extension id="org.eclipse.cdt.core.GmakeErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
<extension id="org.eclipse.cdt.core.CWDLocator" point="org.eclipse.cdt.core.ErrorParser"/>
<extension id="org.eclipse.cdt.core.GCCErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
<extension id="org.eclipse.cdt.core.GASErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
<extension id="org.eclipse.cdt.core.GLDErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
</extensions>
</storageModule>
<storageModule moduleId="cdtBuildSystem" version="4.0.0">
<configuration buildProperties="" description="" id="0.1782736718" name="Default" parent="org.eclipse.cdt.build.core.prefbase.cfg">
<folderInfo id="0.1782736718." name="/" resourcePath="">
<toolChain id="org.eclipse.cdt.build.core.prefbase.toolchain.1475280735" name="No ToolChain" resourceTypeBasedDiscovery="false" superClass="org.eclipse.cdt.build.core.prefbase.toolchain">
<targetPlatform id="org.eclipse.cdt.build.core.prefbase.toolchain.1475280735.349926031" name=""/>
<builder id="org.eclipse.cdt.build.core.settings.default.builder.1481025371" keepEnvironmentInBuildfile="false" managedBuildOn="false" name="Gnu Make Builder" superClass="org.eclipse.cdt.build.core.settings.default.builder"/>
<tool id="org.eclipse.cdt.build.core.settings.holder.libs.1744114255" name="holder for library settings" superClass="org.eclipse.cdt.build.core.settings.holder.libs"/>
<tool id="org.eclipse.cdt.build.core.settings.holder.77598736" name="Assembly" superClass="org.eclipse.cdt.build.core.settings.holder">
<inputType id="org.eclipse.cdt.build.core.settings.holder.inType.682734013" languageId="org.eclipse.cdt.core.assembly" languageName="Assembly" sourceContentType="org.eclipse.cdt.core.asmSource" superClass="org.eclipse.cdt.build.core.settings.holder.inType"/>
</tool>
<tool id="org.eclipse.cdt.build.core.settings.holder.633855209" name="GNU C++" superClass="org.eclipse.cdt.build.core.settings.holder">
<inputType id="org.eclipse.cdt.build.core.settings.holder.inType.1261857088" languageId="org.eclipse.cdt.core.g++" languageName="GNU C++" sourceContentType="org.eclipse.cdt.core.cxxSource,org.eclipse.cdt.core.cxxHeader" superClass="org.eclipse.cdt.build.core.settings.holder.inType"/>
</tool>
<tool id="org.eclipse.cdt.build.core.settings.holder.680528758" name="GNU C" superClass="org.eclipse.cdt.build.core.settings.holder">
<inputType id="org.eclipse.cdt.build.core.settings.holder.inType.935501517" languageId="org.eclipse.cdt.core.gcc" languageName="GNU C" sourceContentType="org.eclipse.cdt.core.cSource,org.eclipse.cdt.core.cHeader" superClass="org.eclipse.cdt.build.core.settings.holder.inType"/>
</tool>
</toolChain>
</folderInfo>
</configuration>
</storageModule>
<storageModule moduleId="org.eclipse.cdt.core.externalSettings"/>
</cconfiguration>
</storageModule>
<storageModule moduleId="cdtBuildSystem" version="4.0.0">
<project id="ocmw_24rdjan17.null.2081730398" name="ocmw_24rdjan17"/>
</storageModule>
<storageModule moduleId="scannerConfiguration">
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
<profile id="org.eclipse.cdt.make.core.GCCStandardMakePerProjectProfile">
<buildOutputProvider>
<openAction enabled="true" filePath=""/>
<parser enabled="true"/>
</buildOutputProvider>
<scannerInfoProvider id="specsFile">
<runAction arguments="-E -P -v -dD ${plugin_state_location}/${specs_file}" command="gcc" useDefault="true"/>
<parser enabled="true"/>
</scannerInfoProvider>
</profile>
<profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfile">
<buildOutputProvider>
<openAction enabled="true" filePath=""/>
<parser enabled="true"/>
</buildOutputProvider>
<scannerInfoProvider id="specsFile">
<runAction arguments="-E -P -v -dD ${plugin_state_location}/${specs_file}" command="gcc" useDefault="true"/>
<parser enabled="true"/>
</scannerInfoProvider>
</profile>
<profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileCPP">
<buildOutputProvider>
<openAction enabled="true" filePath=""/>
<parser enabled="true"/>
</buildOutputProvider>
<scannerInfoProvider id="specsFile">
<runAction arguments="-E -P -v -dD ${plugin_state_location}/specs.cpp" command="g++" useDefault="true"/>
<parser enabled="true"/>
</scannerInfoProvider>
</profile>
<profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileC">
<buildOutputProvider>
<openAction enabled="true" filePath=""/>
<parser enabled="true"/>
</buildOutputProvider>
<scannerInfoProvider id="specsFile">
<runAction arguments="-E -P -v -dD ${plugin_state_location}/specs.c" command="gcc" useDefault="true"/>
<parser enabled="true"/>
</scannerInfoProvider>
</profile>
<scannerConfigBuildInfo instanceId="0.832805871">
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
</scannerConfigBuildInfo>
<scannerConfigBuildInfo instanceId="0.1783974533">
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
<profile id="org.eclipse.cdt.make.core.GCCStandardMakePerProjectProfile">
<buildOutputProvider>
<openAction enabled="true" filePath=""/>
<parser enabled="true"/>
</buildOutputProvider>
<scannerInfoProvider id="specsFile">
<runAction arguments="-E -P -v -dD ${plugin_state_location}/${specs_file}" command="gcc" useDefault="true"/>
<parser enabled="true"/>
</scannerInfoProvider>
</profile>
<profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfile">
<buildOutputProvider>
<openAction enabled="true" filePath=""/>
<parser enabled="true"/>
</buildOutputProvider>
<scannerInfoProvider id="specsFile">
<runAction arguments="-E -P -v -dD ${plugin_state_location}/${specs_file}" command="gcc" useDefault="true"/>
<parser enabled="true"/>
</scannerInfoProvider>
</profile>
<profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileCPP">
<buildOutputProvider>
<openAction enabled="true" filePath=""/>
<parser enabled="true"/>
</buildOutputProvider>
<scannerInfoProvider id="specsFile">
<runAction arguments="-E -P -v -dD ${plugin_state_location}/specs.cpp" command="g++" useDefault="true"/>
<parser enabled="true"/>
</scannerInfoProvider>
</profile>
<profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileC">
<buildOutputProvider>
<openAction enabled="true" filePath=""/>
<parser enabled="true"/>
</buildOutputProvider>
<scannerInfoProvider id="specsFile">
<runAction arguments="-E -P -v -dD ${plugin_state_location}/specs.c" command="gcc" useDefault="true"/>
<parser enabled="true"/>
</scannerInfoProvider>
</profile>
</scannerConfigBuildInfo>
<scannerConfigBuildInfo instanceId="0.1850940622">
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
</scannerConfigBuildInfo>
<scannerConfigBuildInfo instanceId="0.2117040597">
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
</scannerConfigBuildInfo>
<scannerConfigBuildInfo instanceId="0.1782736718">
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
</scannerConfigBuildInfo>
<scannerConfigBuildInfo instanceId="0.1102575359">
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
<profile id="org.eclipse.cdt.make.core.GCCStandardMakePerProjectProfile">
<buildOutputProvider>
<openAction enabled="true" filePath=""/>
<parser enabled="true"/>
</buildOutputProvider>
<scannerInfoProvider id="specsFile">
<runAction arguments="-E -P -v -dD ${plugin_state_location}/${specs_file}" command="gcc" useDefault="true"/>
<parser enabled="true"/>
</scannerInfoProvider>
</profile>
<profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfile">
<buildOutputProvider>
<openAction enabled="true" filePath=""/>
<parser enabled="true"/>
</buildOutputProvider>
<scannerInfoProvider id="specsFile">
<runAction arguments="-E -P -v -dD ${plugin_state_location}/${specs_file}" command="gcc" useDefault="true"/>
<parser enabled="true"/>
</scannerInfoProvider>
</profile>
<profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileCPP">
<buildOutputProvider>
<openAction enabled="true" filePath=""/>
<parser enabled="true"/>
</buildOutputProvider>
<scannerInfoProvider id="specsFile">
<runAction arguments="-E -P -v -dD ${plugin_state_location}/specs.cpp" command="g++" useDefault="true"/>
<parser enabled="true"/>
</scannerInfoProvider>
</profile>
<profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileC">
<buildOutputProvider>
<openAction enabled="true" filePath=""/>
<parser enabled="true"/>
</buildOutputProvider>
<scannerInfoProvider id="specsFile">
<runAction arguments="-E -P -v -dD ${plugin_state_location}/specs.c" command="gcc" useDefault="true"/>
<parser enabled="true"/>
</scannerInfoProvider>
</profile>
</scannerConfigBuildInfo>
</storageModule>
<storageModule moduleId="org.eclipse.cdt.core.LanguageSettingsProviders"/>
</cproject>

View File

@@ -1,79 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>ocmw_new_test</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.cdt.managedbuilder.core.genmakebuilder</name>
<triggers>clean,full,incremental,</triggers>
<arguments>
<dictionary>
<key>?name?</key>
<value></value>
</dictionary>
<dictionary>
<key>org.eclipse.cdt.make.core.append_environment</key>
<value>true</value>
</dictionary>
<dictionary>
<key>org.eclipse.cdt.make.core.autoBuildTarget</key>
<value>all</value>
</dictionary>
<dictionary>
<key>org.eclipse.cdt.make.core.buildArguments</key>
<value></value>
</dictionary>
<dictionary>
<key>org.eclipse.cdt.make.core.buildCommand</key>
<value>make</value>
</dictionary>
<dictionary>
<key>org.eclipse.cdt.make.core.cleanBuildTarget</key>
<value>clean</value>
</dictionary>
<dictionary>
<key>org.eclipse.cdt.make.core.contents</key>
<value>org.eclipse.cdt.make.core.activeConfigSettings</value>
</dictionary>
<dictionary>
<key>org.eclipse.cdt.make.core.enableAutoBuild</key>
<value>false</value>
</dictionary>
<dictionary>
<key>org.eclipse.cdt.make.core.enableCleanBuild</key>
<value>true</value>
</dictionary>
<dictionary>
<key>org.eclipse.cdt.make.core.enableFullBuild</key>
<value>true</value>
</dictionary>
<dictionary>
<key>org.eclipse.cdt.make.core.fullBuildTarget</key>
<value>all</value>
</dictionary>
<dictionary>
<key>org.eclipse.cdt.make.core.stopOnError</key>
<value>true</value>
</dictionary>
<dictionary>
<key>org.eclipse.cdt.make.core.useDefaultBuildCmd</key>
<value>true</value>
</dictionary>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder</name>
<triggers>full,incremental,</triggers>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.cdt.core.cnature</nature>
<nature>org.eclipse.cdt.core.ccnature</nature>
<nature>org.eclipse.cdt.managedbuilder.core.managedBuildNature</nature>
<nature>org.eclipse.cdt.managedbuilder.core.ScannerConfigNature</nature>
</natures>
</projectDescription>

View File

@@ -0,0 +1,2 @@
# PAWSC
Protocol to Access White Space Cellular

View File

@@ -0,0 +1,288 @@
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
##
## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
# User-specific files
*.suo
*.user
*.userosscache
*.sln.docstates
# User-specific files (MonoDevelop/Xamarin Studio)
*.userprefs
# Build results
[Dd]ebug/
[Dd]ebugPublic/
[Rr]elease/
[Rr]eleases/
x64/
x86/
bld/
[Bb]in/
[Oo]bj/
[Ll]og/
# Visual Studio 2015 cache/options directory
.vs/
# Uncomment if you have tasks that create the project's static files in wwwroot
#wwwroot/
# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*
# NUNIT
*.VisualState.xml
TestResult.xml
# Build Results of an ATL Project
[Dd]ebugPS/
[Rr]eleasePS/
dlldata.c
# .NET Core
project.lock.json
project.fragment.lock.json
artifacts/
**/Properties/launchSettings.json
*_i.c
*_p.c
*_i.h
*.ilk
*.meta
*.obj
*.pch
*.pdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*.log
*.vspscc
*.vssscc
.builds
*.pidb
*.svclog
*.scc
# Chutzpah Test files
_Chutzpah*
# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opendb
*.opensdf
*.sdf
*.cachefile
*.VC.db
*.VC.VC.opendb
# Visual Studio profiler
*.psess
*.vsp
*.vspx
*.sap
# TFS 2012 Local Workspace
$tf/
# Guidance Automation Toolkit
*.gpState
# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
*.DotSettings.user
# JustCode is a .NET coding add-in
.JustCode
# TeamCity is a build add-in
_TeamCity*
# DotCover is a Code Coverage Tool
*.dotCover
# Visual Studio code coverage results
*.coverage
*.coveragexml
# NCrunch
_NCrunch_*
.*crunch*.local.xml
nCrunchTemp_*
# MightyMoose
*.mm.*
AutoTest.Net/
# Web workbench (sass)
.sass-cache/
# Installshield output folder
[Ee]xpress/
# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help/*.HxT
DocProject/Help/*.HxC
DocProject/Help/*.hhc
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html
# Click-Once directory
publish/
# Publish Web Output
*.[Pp]ublish.xml
*.azurePubxml
# TODO: Comment the next line if you want to checkin your web deploy settings
# but database connection strings (with potential passwords) will be unencrypted
*.pubxml
*.publishproj
# Microsoft Azure Web App publish settings. Comment the next line if you want to
# checkin your Azure Web App publish settings, but sensitive information contained
# in these scripts will be unencrypted
PublishScripts/
# NuGet Packages
*.nupkg
# The packages folder can be ignored because of Package Restore
**/packages/*
# except build/, which is used as an MSBuild target.
!**/packages/build/
# Uncomment if necessary however generally it will be regenerated when needed
#!**/packages/repositories.config
# NuGet v3's project.json files produces more ignorable files
*.nuget.props
*.nuget.targets
# Microsoft Azure Build Output
csx/
*.build.csdef
# Microsoft Azure Emulator
ecf/
rcf/
# Windows Store app package directories and files
AppPackages/
BundleArtifacts/
Package.StoreAssociation.xml
_pkginfo.txt
# Visual Studio cache files
# files ending in .cache can be ignored
*.[Cc]ache
# but keep track of directories ending in .cache
!*.[Cc]ache/
# Others
ClientBin/
~$*
*~
*.dbmdl
*.dbproj.schemaview
*.jfm
*.pfx
*.publishsettings
orleans.codegen.cs
# Since there are multiple workflows, uncomment next line to ignore bower_components
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
#bower_components/
# RIA/Silverlight projects
Generated_Code/
# Backup & report files from converting an old project file
# to a newer Visual Studio version. Backup files are not needed,
# because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm
# SQL Server files
*.mdf
*.ldf
*.ndf
# Business Intelligence projects
*.rdl.data
*.bim.layout
*.bim_*.settings
# Microsoft Fakes
FakesAssemblies/
# GhostDoc plugin setting file
*.GhostDoc.xml
# Node.js Tools for Visual Studio
.ntvs_analysis.dat
node_modules/
# Typescript v1 declaration files
typings/
# Visual Studio 6 build log
*.plg
# Visual Studio 6 workspace options file
*.opt
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
*.vbw
# Visual Studio LightSwitch build output
**/*.HTMLClient/GeneratedArtifacts
**/*.DesktopClient/GeneratedArtifacts
**/*.DesktopClient/ModelManifest.xml
**/*.Server/GeneratedArtifacts
**/*.Server/ModelManifest.xml
_Pvt_Extensions
# Paket dependency manager
.paket/paket.exe
paket-files/
# FAKE - F# Make
.fake/
# JetBrains Rider
.idea/
*.sln.iml
# CodeRush
.cr/
# Python Tools for Visual Studio (PTVS)
__pycache__/
*.pyc
# Cake - Uncomment if you are using it
# tools/**
# !tools/packages.config
# Telerik's JustMock configuration file
*.jmconfig
# BizTalk build output
*.btp.cs
*.btm.cs
*.odx.cs
*.xsd.cs

View File

@@ -0,0 +1,21 @@
MIT License
Copyright (c) Microsoft Corporation. All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE

View File

@@ -0,0 +1,14 @@
#
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License.
#
.PHONY: all
all:
make -C libs
make -C apps
.PHONY: clean
clean:
make -C libs clean
make -C apps clean

View File

@@ -0,0 +1,29 @@
#
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License.
#
TARGET_PLATFORM ?= native
C_SRC ?= $(wildcard ./*.c)
C_OBJ = $(addprefix obj/$(TARGET_PLATFORM)/,$(patsubst %.c,%.o,$(C_SRC)))
DEPS = $(patsubst %.o,%.d,$(C_OBJ))
LIBS_DIR = $(PRJROOT)/libs
CFLAGS += -D_GNU_SOURCE -g -MMD -msoft-float -std=c99 -Wall -Werror -Wextra
INC_DIRS = -I$(LIBS_DIR) -I.
C_LIBS = -L$(LIBS_DIR)
# add SDK stuff
ifeq ($(TARGET_PLATFORM),fap)
SDK_LIBS_DIR = -L/opt/E40_SDK/sysroots/ppce500v2-ipa-linux-gnuspe/usr/lib
INC_DIRS += -I/opt/E40_SDK/sysroots/ppce500v2-ipa-linux-gnuspe/usr/include
C_LIBS += $(SDK_LIBS_DIR)
endif
ifeq ($(TARGET_PLATFORM),$(filter $(TARGET_PLATFORM),native test))
SDK_LIBS_DIR = -L/opt/E40_SDK/sysroots/x86_64-cpesdk-linux/usr/lib
INC_DIRS += -I/opt/E40_SDK/sysroots/x86_64-cpesdk-linux/usr/include
C_LIBS += $(SDK_LIBS_DIR)
endif

View File

@@ -0,0 +1,84 @@
# Introduction
This is a client which provides LTE access, via a small/femto cell, by communicating with a TVWSDB to negotiate a spectrum. There are two main applications which, together, accomplish this : PAWS and SCTP-AGENT.
## PAWS
This is the application which communicates with an Ofcom-certified TVWS database. The user will need to configure details on the various devices for this to be achieved.
Referer to RFC 7545 for more details.
## SCTP-AGENT
This is an application which controls access to the MME itself. It is used to control the transfer of data between the local small-cell eNodeB LTE software, and the MME itself.
It uses the information from PAWS to determine whether it needs to block the data transfer. However it can also be configured to ignore the PAWS status.
The block diagrams below shows the general topologies.
![](https://github.com/Microsoft/SpectrumDBClient/blob/master/topology.JPG)
# TVWSDB
As discussed, PAWS needs to communicate with a TVWSDB. The user will need to register all clients with this, get security tokens etc, and configure this in the SQL databases mentioned below.
# Build instructions
## Set environment variable
> export PRJROOT="root-dir-containing-apps-and-libs"
## SCTP-AGENT
### Config options
There are some build options in apps/sctp-agent/sctp_cfg_options.h. Change these as required.
### Set up real "tcps1", or use dummy.
+ The SCTP-agent can communicate in either SCTP ot TCP mode, by setting "SocketInfo.mme_connection_type" to "tcp|sctp".
+ If you run in SCTP mode, you need to create a soft-link in the apps/sctp-agent directory to point to dummy_tcps1
> cd $PRJROOT/apps/sctp-agent
> ln -s dummy_tcps1 tcps1
+ NOTE that the dummy_tcps1 is purely used to allow the code to compile. It does not provide a TCP-based access
+ If you run in TCP mode, you need to use the tcps1 library, and create a softlink in the apps/sctp-agent directory to point to the directory where you have cloned tcps1lib.
> cd $PRJROOT/apps/sctp-agent
> ln -s <tcps1lib-directory> tcps1
## Compile code
> cd $PRJROOT
> make TARGET_PLATFORM=native|fap clean
> make TARGET_PLATFORM=native|fap
## Databases (PAWS/SCTP)
+ Both the PAWS and SCTP agent are configured using an SQL database.
+ The schema for each of these can be found on the "sql_db" subdirectory of each of these apps.
+ Furthermore "<app>_native" in each of these directories gives a full example.
+ To generate different databases, update the "json" files in these directories and run the Makefile with TARGET_PLATFORM="native|fap"
+ Note that the databases are not automatically built by a "make" at the top level.
## Databases (FemTo)
This whole small cell client assumes that there is also a "femto.db" that can be read.
## Database locations
The location where these databases are found in hardcoded. To change, update the following files accordingly :-
### PAWS
> apps/paws/fap/main.c
>apps/paws/native/main.c
### SCTP-AGENT
> apps/sctp-agent/fap/device_db_info.h
> apps/sctp-agent/native/device_db_info.h
## TARGET_PLATFORM
+ You will see above the TARGET_PLATFORM should be set to "native|fap" when running "make". In this case, "native" means x86 linux.
+ For "fap" the user would need to setup their environment as required.
## Contributions
Contributions in the form of bug reports, feature requests and PRs are always welcome.
Please follow these steps before submitting a PR:
* Create an issue describing the bug or feature request.
* Clone the repository and create a topic branch.
* Make changes, adding new tests for new functionality.
* Submit a PR.
## License
See [LICENSE](LICENSE).
## Code of Conduct
This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments.

View File

@@ -0,0 +1,16 @@
#
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License.
#
.PHONY: all
all:
make -C paws
make -C sctp-agent
make -C paws db
make -C sctp-agent db
.PHONY: clean
clean:
make -C paws clean
make -C sctp-agent clean

View File

@@ -0,0 +1,30 @@
#
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License.
#
include ${PRJROOT}/Makefile.common
C_SRC += $(wildcard $(TARGET_PLATFORM)/*.c)
APP = paws
C_LIBS += -l4gclient -lm
## if TARGET_PLATFORM = fap or native or unittest
## ifeq ($(TARGET_PLATFORM),$(filter $(TARGET_PLATFORM),fap native))
C_LIBS += -lsqlite3 -lssl -lcrypto
INC_DIRS += -I./paws_db -I./lte_db -I./sctp_agent_db
DB_SRC = $(wildcard paws_db/*.c)
DB_SRC += $(wildcard lte_db/*.c)
DB_SRC += $(wildcard sctp_agent_db/*.c)
C_SRC += $(DB_SRC)
DEPS = $(patsubst %.o,%.d,$(C_OBJ))
##endif
include ${PRJROOT}/rules.mk
.PHONY: db
db:
make -C sql_db db

View File

@@ -0,0 +1,75 @@
/*
Copyright (c) Microsoft Corporation. All rights reserved.
Licensed under the MIT License.
*/
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <unistd.h>
#include <time.h>
#include "paws_globals.h"
#include "lte_db_info.h"
#include "paws_db_info.h"
#include "sctp_agent_db_info.h"
#include "paws_common.h"
#include "paws_combiner_sm.h"
#include "utils/types.h"
#include "utils/utils.h"
int main()
{
paws_combiner_sm_t* comb = NULL;
uint32_t sctp_agent_port;
uint32_t sctp_agent_status_perdiocity;
// wait a while for other services to come up
sleep(10);
if (!(set_paws_db_location("/config/paws.db")))
fatal_error("Cant set PAWS-DB location");
if (!(set_sctp_agent_db_location("/config/sctp_agent.db")))
fatal_error("Cant set SCTP-AGENT-DB location");
if (!(set_lte_db_location("/config/femto.db")))
fatal_error("Cant set Device-DB location");
// create the ssl context.
if (!(https_init()))
fatal_error("Problem in https_init");
// get the CloudLog settings
get_gPawsLoggerSettings();
// get the DeviceId
populate_gDeviceName();
// loop until the SCTP settings are read correctly
while (1)
{
if ((get_sctp_agent_info(&sctp_agent_port, &sctp_agent_status_perdiocity)))
break;
sleep(1); // try in a second
}
if (!(comb = paws_combiner_sm_create("combiner", sctp_agent_port, sctp_agent_status_perdiocity)))
fatal_error("Cant initialise sytem");
PUBLIC_FUNC(comb, Run)(comb);
paws_combiner_sm_free(&comb);
PawsGlobalsFree();
// free ssl txt.
https_free();
return 0;
}

View File

@@ -0,0 +1,24 @@
/*
Copyright (c) Microsoft Corporation. All rights reserved.
Licensed under the MIT License.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "paws_device_specific.h"
//#######################################################################################
void system_reboot(void)
{
system("reboot");
}
//#######################################################################################
bool reboot_device_on_admin_disable(void)
{
return false; // for the FAP, the PAWS will not reboot the FAP upon setting Admin=False.
// Instead, status=0 will be sent to the SCTP-AGENT agent, which will indirectly cause the eNB sw to disable the radio.
}

View File

@@ -0,0 +1,34 @@
/*
Copyright (c) Microsoft Corporation. All rights reserved.
Licensed under the MIT License.
*/
#include <stdio.h>
#include "lte_db_info.h"
#define MAX_LTE_DB_NAME (100)
static char g_lte_db[MAX_LTE_DB_NAME] = "\0";
//#######################################################################################
bool set_lte_db_location(char* db)
{
if (!db)
return false;
int slen = snprintf(g_lte_db, MAX_LTE_DB_NAME, "%s", db);
if ((slen <= 0) || (slen >= MAX_LTE_DB_NAME))
return false;
return true;
}
//#######################################################################################
char* get_lte_db_location(void)
{
return &g_lte_db[0];
}

View File

@@ -0,0 +1,17 @@
/*
Copyright (c) Microsoft Corporation. All rights reserved.
Licensed under the MIT License.
*/
#include <stdint.h>
#include <stdbool.h>
#ifndef LTE_DB_INFO_H_
#define LTE_DB_INFO_H_
extern bool set_lte_db_location(char* db);
extern char* get_lte_db_location(void);
#endif // LTE_DB_INFO_H_

View File

@@ -0,0 +1,217 @@
/*
Copyright (c) Microsoft Corporation. All rights reserved.
Licensed under the MIT License.
*/
#include <stdlib.h>
#include "lte_utils.h"
#include "logger/logger.h"
typedef struct {
uint16_t band_id;
uint32_t Fdl_low_100khz;
uint32_t Fdl_high_100khz;
uint32_t Ndl_offset;
uint32_t Ndl_high_offset;
uint32_t Ful_low_100khz;
uint32_t Ful_high_100khz;
uint32_t Nul_offset;
uint32_t Nul_high_offset;
uint16_t bw_mhz; // max bandwidth
} lte_band_info_t ;
static lte_band_info_t lte_band_info[] = {
{
13, // band_id;
7460, // Fdl_low_100khz;
7560, // Fdl_high_100khz;
5180, // Ndl_offset;
5279, // Ndl_high_offset;
7770, // Ful_low_100khz;
7870, // Ful_high_100khz;
23180, // Nul_offset;
23279, // Nul_high_offset;
10 // bw_mhz - max bandwidth
}
};
//#######################################################################################
static lte_band_info_t* get_lte_band_info(uint16_t band_id)
{
// walk lte_band_info and find band
for (uint32_t i = 0; i < (sizeof(lte_band_info) / sizeof(lte_band_info_t)); i++)
{
lte_band_info_t* b = &lte_band_info[i];
if (b->band_id == band_id)
{
return b;
}
}
return NULL;
}
//#######################################################################################
bool get_lte_band_channel(uint16_t band_id, lte_direction_e dir, uint32_t* start_hz, uint32_t *end_hz, int32_t *spacing_hz)
{
bool found = false;
lte_band_info_t* band = get_lte_band_info(band_id);
if (band)
{
found = true;
*start_hz = (dir == LTE_UL) ? (band->Ful_low_100khz*100000) : (band->Fdl_low_100khz*100000);
*end_hz = *start_hz + (band->bw_mhz*1000000);
*spacing_hz = (band->Ful_low_100khz * 100000) - (band->Fdl_low_100khz * 100000);
}
return found;
}
//#######################################################################################
uint32_t dl_hz_to_earfcn(uint16_t band_id, uint32_t fdl_)
{
lte_band_info_t* band = NULL;
uint32_t fdl = fdl_ / 100000; //convert to 100khz
if ((band = get_lte_band_info(band_id)))
{
// is it even in range
if ((fdl < band->Fdl_low_100khz) || (fdl > band->Fdl_high_100khz))
return 0;
// Fdl = Fdl_low + 0.1(Ndl - Ndl_offset)
// so,
// Ndl = ((fdl - Fdl_low) * 10) + Ndl_offset
//
uint32_t ndl = (fdl - band->Fdl_low_100khz) + band->Ndl_offset;
return ndl;
}
return 0;
}
//#######################################################################################
uint32_t ul_hz_to_earfcn(uint16_t band_id, uint32_t ful_)
{
lte_band_info_t* band = NULL;
uint32_t ful = ful_ / 100000; //convert to 100khz
if ((band = get_lte_band_info(band_id)))
{
// is it even in range
if ((ful < band->Ful_low_100khz) || (ful > band->Ful_high_100khz))
return 0;
// Ful = Ful_flow + 0.1(Nul - Nul_offset)
// so,
// Nul = ((ful - Ful_low) * 10) + Nul_offset
//
uint32_t nul = (ful - band->Ful_low_100khz) + band->Nul_offset;
return nul;
}
return 0;
}
//#######################################################################################
uint32_t dl_earfcn_to_hz(uint16_t band_id, uint32_t Ndl)
{
lte_band_info_t* band = NULL;
if ((band = get_lte_band_info(band_id)))
{
// is it even in range
if ((Ndl < band->Ndl_offset) || (Ndl > band->Ndl_high_offset))
return 0;
// Fdl = Fdl_low + 0.1(Ndl - Ndl_offset)
uint32_t fdl = band->Fdl_low_100khz + (Ndl - band->Ndl_offset);
fdl *= 100000; //convert to hz
return fdl;
}
return 0;
}
//#######################################################################################
uint32_t ul_earfcn_to_hz(uint16_t band_id, uint32_t Nul)
{
lte_band_info_t* band = NULL;
if ((band = get_lte_band_info(band_id)))
{
// is it even in range
if ((Nul < band->Nul_offset) || (Nul > band->Nul_high_offset))
return 0;
// Ful = Ful_low + 0.1(Nul - Nul_offset)
uint32_t ful = (band->Ful_low_100khz + ((Nul - band->Nul_offset)));
ful *= 100000; //convert to hz
return ful;
}
return 0;
}
//#######################################################################################
// pmax and ref_sig_power are stored in units of 0.1dB
bool validate_lte_cfg(uint16_t band_id, int bandwidth, int ref_sig_power, int earfcndl, int earfcnul, int pmax)
{
lte_band_info_t* band = NULL;
if (!(band = get_lte_band_info(band_id)))
return false;
// is Pmax in range
if (pmax < (LTE_PMAX_MIN * 10)) // pmax is stored in units of 0.1dB
return false;
if (pmax > (LTE_PMAX_MAX * 10)) // pmax is stored in units of 0.1dB
return false;
// bandwidth to Mhz
uint32_t bw_hz;
if (bandwidth == 25)
bw_hz = 5000000;
else if (bandwidth == 50)
bw_hz = 10000000;
else if(bandwidth == 100)
bw_hz = 20000000;
else
return false;
// is DL in range
uint32_t fdl = dl_earfcn_to_hz(band_id, earfcndl);
if (fdl == 0)
return 0;
if (((fdl - (bw_hz/2)) < (band->Fdl_low_100khz * 100000)) || ((fdl + (bw_hz/2)) > (band->Fdl_high_100khz * 100000)))
return 0;
// is UL in range
uint32_t ful = ul_earfcn_to_hz(band_id, earfcnul);
if (ful == 0)
return 0;
if (((ful - (bw_hz/2)) < (band->Ful_low_100khz * 100000)) || ((ful + (bw_hz/2)) > (band->Ful_high_100khz * 100000)))
return 0;
// ref sig power
if (ref_sig_power < (-50 * 10)) // ref_sig_power is stored in units of 0.1dB
{
return false;
}
return true;
}

View File

@@ -0,0 +1,29 @@
/*
Copyright (c) Microsoft Corporation. All rights reserved.
Licensed under the MIT License.
*/
#ifndef DEVICE_UTILS_H_
#define DEVICE_UTILS_H_
#include <stdint.h>
#include <stdbool.h>
#include "utils/types.h"
#define LTE_PMAX_MIN (-30)
#define LTE_PMAX_MAX (33)
extern bool get_lte_band_channel(uint16_t id, lte_direction_e dir, uint32_t *start_hz, uint32_t *end_hz, int32_t *spacing_hz);
extern uint32_t dl_hz_to_earfcn(uint16_t band_id, uint32_t fdl);
extern uint32_t ul_hz_to_earfcn(uint16_t band_id, uint32_t ful);
extern uint32_t dl_earfcn_to_hz(uint16_t band_id, uint32_t Ndl);
extern uint32_t ul_earfcn_to_hz(uint16_t band_id, uint32_t Nul);
extern bool validate_lte_cfg(uint16_t band_id, int bandwidth, int ref_sig_power, int earfcndl, int earfcnul, int pmax);
#endif // DEVICE_UTILS_H_

View File

@@ -0,0 +1,690 @@
/*
Copyright (c) Microsoft Corporation. All rights reserved.
Licensed under the MIT License.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/stat.h>
#include <time.h>
#include <sqlite3.h>
#include "utils/utils.h"
#include "json-parser/json.h"
#include "json-parser/json_utils.h"
#include "lte_db_info.h"
#include "lte_utils.h"
#include "paws_types.h"
#include "paws_common.h"
#include "paws_globals.h"
#include "paws_dal_device_cfg.h"
#include "paws_dal_utils.h"
#include "paws_device_specific.h"
//#######################################################################################
#define MAX_SQL_LEN (200)
static char sql_str[MAX_SQL_LEN];
static char tmp[200];
#define SQL_STRCAT(s) strncat(sql_str, s, MAX_SQL_LEN - strlen(sql_str) - 1);
static int current_adminState = -1; // we don't write adminState=0. To disable we issue command to SCTP-Agent which will cause eNB software to disable the radio.
// -1 means not set
static device_cfg_params_t current_device_cfg = { 0 };
#define MAX_RADIATED_POWER_DBM (36)
//#######################################################################################
bool paws_get_device_name(device_name_t device_name)
{
sqlite3 *sql_hdl = NULL;
sqlite3_stmt *stmt = NULL;
int rc;
memset(device_name, 0, sizeof(device_name_t));
// get datafile location and open it
char* db_sql_file = get_lte_db_location();
if (!db_sql_file)
{
goto error_hdl;
}
sqlite3_open(db_sql_file, &sql_hdl);
if (!sql_hdl)
{
goto error_hdl;
}
// get the DeviceId. We use FAPServiceAccessMgmtLTE.HNBName
const char *sql = "SELECT HNBName FROM FAPServiceAccessMgmtLTE";
rc = sqlite3_prepare_v2(sql_hdl, sql, -1, &stmt, NULL);
if (rc != SQLITE_OK)
{
goto error_hdl;
}
while ((rc = sqlite3_step(stmt)) == SQLITE_ROW)
{
char* tmp = (char*)sqlite3_column_text(stmt, 0);
if (tmp)
{
snprintf(device_name, sizeof(device_name_t), "%s", tmp);
}
}
if (rc != SQLITE_DONE)
{
goto error_hdl;
}
sqlite3_finalize(stmt); stmt = NULL;
// release database
if (sql_hdl) sqlite3_close(sql_hdl);
return true;
error_hdl:
if (sql_hdl) sqlite3_close(sql_hdl);
if (stmt) sqlite3_finalize(stmt);
return false;
}
//#######################################################################################
static bool sql_get_master_cfg(device_cfg_params_t* cfg, bool use_override)
{
sqlite3 *sql_hdl = NULL;
sqlite3_stmt *stmt = NULL;
int rc;
if (!cfg)
{
goto error_hdl;
}
memset(cfg, 0, sizeof(device_cfg_params_t));
// get datafile location and open it
char* db_sql_file = get_lte_db_location();
if (!db_sql_file)
{
goto error_hdl;
}
sqlite3_open(db_sql_file, &sql_hdl);
if (!sql_hdl)
{
goto error_hdl;
}
if (current_adminState == -1) // only read AdminState if it hasn't been read previously
{
// get the Admin State
const char *sql = "SELECT AdminState FROM FAPServiceFAPControlLTE";
rc = sqlite3_prepare_v2(sql_hdl, sql, -1, &stmt, NULL);
if (rc != SQLITE_OK)
{
goto error_hdl;
}
while ((rc = sqlite3_step(stmt)) == SQLITE_ROW)
{
current_adminState = sqlite3_column_int(stmt, 0);
}
if (rc != SQLITE_DONE)
{
goto error_hdl;
}
sqlite3_finalize(stmt); stmt = NULL;
}
cfg->admin_state = current_adminState;
// get x_000295_external_pa_gain
const char *sql4 = "SELECT X_000295_ExternalPAGain FROM FAPServiceCellConfigLTERANRF";
rc = sqlite3_prepare_v2(sql_hdl, sql4, -1, &stmt, NULL);
if (rc != SQLITE_OK)
{
goto error_hdl;
}
while ((rc = sqlite3_step(stmt)) == SQLITE_ROW)
{
cfg->x_000295_external_pa_gain = sqlite3_column_int(stmt, 0);
}
if (rc != SQLITE_DONE)
{
goto error_hdl;
}
sqlite3_finalize(stmt); stmt = NULL;
// get MaxPower - stored in dB as units of dBM, so we'll multiply by 10 and store it as units of 0.1db, as per other fields.
const char *sql2 = "SELECT MaxTxPower FROM FAPServiceCapabilities";
rc = sqlite3_prepare_v2(sql_hdl, sql2, -1, &stmt, NULL);
if (rc != SQLITE_OK)
{
goto error_hdl;
}
while ((rc = sqlite3_step(stmt)) == SQLITE_ROW)
{
cfg->capabilities_max_tx_power = sqlite3_column_int(stmt, 0) * 10;
}
if (rc != SQLITE_DONE)
{
goto error_hdl;
}
sqlite3_finalize(stmt); stmt = NULL;
// get MinPower - stored in dB as units of 0.1dB, so we'll keep it like that.
const char *sql3 = "SELECT X_000295_MinTxPower FROM FAPServiceCapabilitiesLTE";
rc = sqlite3_prepare_v2(sql_hdl, sql3, -1, &stmt, NULL);
if (rc != SQLITE_OK)
{
goto error_hdl;
}
while ((rc = sqlite3_step(stmt)) == SQLITE_ROW)
{
cfg->capabilities_min_tx_power = sqlite3_column_int(stmt, 0);
}
if (rc != SQLITE_DONE)
{
goto error_hdl;
}
sqlite3_finalize(stmt); stmt = NULL;
if (use_override)
{
cfg->bandwidth = current_device_cfg.bandwidth;
cfg->earfcndl = current_device_cfg.earfcndl;
cfg->earfcnul = current_device_cfg.earfcnul;
cfg->ref_sig_power = current_device_cfg.ref_sig_power;
cfg->pmax = current_device_cfg.pmax;
}
else
{
// get bandwidth, ref_sig_power, earfcndl, earfcnul
const char *sql4 = "SELECT ULBandwidth, ReferenceSignalPower, EARFCNDL, EARFCNUL FROM FAPServiceCellConfigLTERANRF";
rc = sqlite3_prepare_v2(sql_hdl, sql4, -1, &stmt, NULL);
if (rc != SQLITE_OK)
{
goto error_hdl;
}
while ((rc = sqlite3_step(stmt)) == SQLITE_ROW)
{
cfg->bandwidth = sqlite3_column_int(stmt, 0);
cfg->ref_sig_power = sqlite3_column_int(stmt, 1) * 10;
cfg->earfcndl = sqlite3_column_int(stmt, 2);
cfg->earfcnul = sqlite3_column_int(stmt, 3);
}
if (rc != SQLITE_DONE)
{
goto error_hdl;
}
sqlite3_finalize(stmt); stmt = NULL;
// get Pmax
const char *sql5 = "SELECT PMax FROM FAPServiceCellConfigLTERANMobilityIdleModeIntraFreq";
rc = sqlite3_prepare_v2(sql_hdl, sql5, -1, &stmt, NULL);
if (rc != SQLITE_OK)
{
goto error_hdl;
}
while ((rc = sqlite3_step(stmt)) == SQLITE_ROW)
{
cfg->pmax = sqlite3_column_int(stmt, 0) * 10;
}
if (rc != SQLITE_DONE)
{
goto error_hdl;
}
sqlite3_finalize(stmt); stmt = NULL;
}
// release database
if (sql_hdl) sqlite3_close(sql_hdl);
return true;
error_hdl:
if (sql_hdl) sqlite3_close(sql_hdl);
if (stmt) sqlite3_finalize(stmt);
return false;
}
//#######################################################################################
//
//
// +---------+ +---------+ +------------+
// | FAP |------------------------>| LRE |----------*------------>| Antenna |------------*-------------->
// +---------+ +---------+ | +------------+ |
// | |
// | |
// total_ref_sig_power total_power
// (max_pa_power) (max_tx_power)
//
// total_power = that specified in the AVAIL_SPEC_RESP (or by Ofcom for Override)
// min_pa_power <= total_reg_sig_power <= max_pa_power
// total_ref_sig_power + antenna_gain <= max_tx_power
//
static bool limit_and_validate_cfg(void* logger, device_cfg_params_t* dst, int min_pa_power, int max_pa_power, int master_antenna_gain, int max_tx_power, int lre)
{
float _10log_numRBelements = 0;
// total power = 10xlog(num_100k_blocks) + dbm_per100k;
// fix the 10xlog(num_100k_blocks) based on bandwdith
if (dst->bandwidth == 25)
{
_10log_numRBelements = 24.77;
}
else if (dst->bandwidth == 50)
{
_10log_numRBelements = 27.78;
}
else if (dst->bandwidth == 100)
{
_10log_numRBelements = 30.79;
}
else
return false;
dst->capabilities_min_tx_power = min_pa_power;
dst->capabilities_max_tx_power = max_pa_power;
dst->antenna_gain = master_antenna_gain;
dst->x_000295_external_pa_gain = lre;
dst->total_ref_sig_power = dst->ref_sig_power + (_10log_numRBelements*10) + dst->antenna_gain;
// check the max radiated power is not exceeded
if (dst->total_ref_sig_power > max_tx_power)
{
char dbg[200];
sprintf(dbg, "Limiting DL power to maximum allowed to be radiated [%.2fdBm]", max_tx_power / 10.0);
logger_log(logger, dbg, LOG_NOTICE, "Device-Cfg", true, true, NULL, 0, NULL, gPawsCloudLogger, gDeviceName, PAWS_LOG_TYPE);
dst->total_ref_sig_power = max_tx_power;
dst->limited = true;
}
// take off the antenna gain to check the max_pa and min_pa
dst->total_ref_sig_power -= dst->antenna_gain;
// check min
if (dst->total_ref_sig_power < min_pa_power)
{
char dbg[200];
sprintf(dbg, "Invalid cfg : Allowed DL power is below Minimum Power of the device. Ref_sig_power=%.2fdBm Minimum_Ref_sig_power=%.2fdBm \n",
(float)dst->total_ref_sig_power/10.0, (float)min_pa_power/10.0);
logger_log(logger, dbg, LOG_ERROR, "Device-Cfg", true, true, NULL, 0, NULL, gPawsCloudLogger, gDeviceName, PAWS_LOG_TYPE);
return false;
}
// check max
if (dst->total_ref_sig_power > max_pa_power)
{
char dbg[200];
sprintf(dbg, "Limiting DL power to maximum of the device [%.2fdBm]", dst->capabilities_max_tx_power/10.0);
logger_log(logger, dbg, LOG_NOTICE, "Device-Cfg", true, true, NULL, 0, NULL, gPawsCloudLogger, gDeviceName, PAWS_LOG_TYPE);
dst->total_ref_sig_power = max_pa_power;
dst->limited = true;
}
dst->ref_sig_power = dst->total_ref_sig_power - (_10log_numRBelements * 10);
// check Pmax min
if (dst->pmax < (LTE_PMAX_MIN * 10))
{
char dbg[200];
sprintf(dbg, "Invalid cfg : Allowed UL power is below Minimum Power of an LTE UE. PMax=%.2fdBm PMax(min)=%d.0dBm \n",
(float)dst->pmax / 10.0, LTE_PMAX_MIN);
logger_log(logger, dbg, LOG_ERROR, "Device-Cfg", true, true, NULL, 0, NULL, gPawsCloudLogger, gDeviceName, PAWS_LOG_TYPE);
return false;
}
// check Pmax max
if (dst->pmax > (LTE_PMAX_MAX * 10))
{
char dbg[200];
sprintf(dbg, "Limiting UL power to maximum of an LTE UE [%d.0dBm]", LTE_PMAX_MAX);
logger_log(logger, dbg, LOG_NOTICE, "Device-Cfg", true, true, NULL, 0, NULL, gPawsCloudLogger, gDeviceName, PAWS_LOG_TYPE);
dst->pmax = (LTE_PMAX_MAX * 10);
dst->limited = true;
}
// fail safe - just to double check the valiues are consistent
if (!(validate_lte_cfg(13, dst->bandwidth, dst->ref_sig_power, dst->earfcndl, dst->earfcnul, dst->pmax)))
{
char dbg[200];
sprintf(dbg, "Invalid cfg : Bandwidth=%d(RB) earfcndl=%d earfcnul=%d ref_sig_power=%.2fdBm Pmax=%.2fdBm",
dst->bandwidth, dst->earfcndl, dst->earfcnul, (float)dst->ref_sig_power/10.0, (float)dst->pmax/10.0);
logger_log(logger, dbg, LOG_ERROR, "Device-Cfg", true, true, NULL, 0, NULL, gPawsCloudLogger, gDeviceName, PAWS_LOG_TYPE);
return false;
}
return true;
}
//#######################################################################################
bool create_device_cfg_params(void* logger, device_cfg_params_t* dst, int min_tx_power, int max_tx_power, device_cfg_t* paws_cfg, int master_antenna_gain, int lre)
{
float _10log_numRBelements = 0;
float _10log_num100kblocks = 0;
if ((!dst) || (!paws_cfg))
return false;
memset(dst, 0, sizeof(device_cfg_params_t));
// set the capabilities
dst->capabilities_min_tx_power = min_tx_power;
dst->capabilities_max_tx_power = max_tx_power;
dst->antenna_gain = master_antenna_gain;
dst->x_000295_external_pa_gain = lre;
// adminState
dst->admin_state = paws_cfg->device_enabled;
if (dst->admin_state)
{
// bandwidth
if (paws_cfg->bandwidth == 5000000)
dst->bandwidth = 25;
else if (paws_cfg->bandwidth == 10000000)
dst->bandwidth = 50;
else if (paws_cfg->bandwidth == 20000000)
dst->bandwidth = 100;
else
return false;
// uarcfn
if ((dst->earfcndl = dl_hz_to_earfcn(13, paws_cfg->dl_start_hz + (paws_cfg->bandwidth / 2))) == 0)
return false;
if ((dst->earfcnul = ul_hz_to_earfcn(13, paws_cfg->ul_start_hz + (paws_cfg->bandwidth / 2))) == 0)
return false;
// total power = 10xlog(num_100k_blocks) + dbm_per100k;
// fix the 10xlog(num_100k_blocks) based on bandwdith
if (dst->bandwidth == 25)
{
_10log_numRBelements = 24.77;
_10log_num100kblocks = 16.98;
}
else if (dst->bandwidth == 50)
{
_10log_numRBelements = 27.78;
_10log_num100kblocks = 20.00;
}
else if (dst->bandwidth == 100)
{
_10log_numRBelements = 30.79;
_10log_num100kblocks = 23.01;
}
else
return false;
dst->pmax = (int)((_10log_num100kblocks + paws_cfg->ul_dbm_per100k) * 10.0);
dst->limited = false;
// Ref power must fall between MinTxPower and MaxTxPower
uint32_t max_total_power = (_10log_num100kblocks + paws_cfg->dl_dbm_per100k) * 10;
dst->total_ref_sig_power = max_total_power - dst->antenna_gain;
// create power per 100k
dst->ref_sig_power = dst->total_ref_sig_power - (_10log_numRBelements * 10);
if (!(limit_and_validate_cfg(logger, dst, dst->capabilities_min_tx_power, dst->capabilities_max_tx_power, master_antenna_gain, max_total_power, lre)))
return false;
}
return true;
}
//#######################################################################################
bool process_device_cfg_params(void* logger, device_cfg_params_t* new_, device_cfg_params_t* curr, bool* admin_state_changed, bool *cfg_changed, bool *reboot_needed, bool spectrum_override_present)
{
sqlite3 *sql_hdl = NULL;
char* error_msg = NULL;
sql_str[0] = '\0';
tmp[0] = '\0';
if ((!new_) || (!curr) || (!cfg_changed) || (!reboot_needed))
{
goto error_hdl;
}
*cfg_changed = false;
*reboot_needed = false;
*admin_state_changed = false;
// get datafile location and open it
char* db_sql_file = get_lte_db_location();
if (!db_sql_file)
{
goto error_hdl;
}
sqlite3_open(db_sql_file, &sql_hdl);
if (!sql_hdl)
{
goto error_hdl;
}
// write params
if (new_->admin_state)
{
// ULBandwidth, ReferenceSignalPower, EARFCNDL, EARFCNUL
// build SQL command
sprintf(tmp, "UPDATE FAPServiceCellConfigLTERANRF SET "); SQL_STRCAT(tmp);
// Bandwidth
if (new_->bandwidth != curr->bandwidth)
{
sprintf(tmp, "ULBandwidth = %d, DLBandwidth = %d", new_->bandwidth, new_->bandwidth); SQL_STRCAT(tmp);
*cfg_changed = true;
current_device_cfg.bandwidth = new_->bandwidth;
}
// ReferenceSignalPower
if ((new_->ref_sig_power/10) != (curr->ref_sig_power/10)) // divide by 10 as the femto,db does not have granularity to 0.1db
{
if (*cfg_changed) SQL_STRCAT(",");
sprintf(tmp, "ReferenceSignalPower = %d", new_->ref_sig_power / 10); SQL_STRCAT(tmp);
*cfg_changed = true;
current_device_cfg.ref_sig_power = new_->ref_sig_power;
}
// EARFCNDL
if (new_->earfcndl != curr->earfcndl)
{
if (*cfg_changed) SQL_STRCAT(",");
sprintf(tmp, "EARFCNDL = %d", new_->earfcndl); SQL_STRCAT(tmp);
*cfg_changed = true;
current_device_cfg.earfcndl = new_->earfcndl;
}
// EARFCNUL
if (new_->earfcnul != curr->earfcnul)
{
if (*cfg_changed) SQL_STRCAT(",");
sprintf(tmp, "EARFCNUL = %d", new_->earfcnul); SQL_STRCAT(tmp);
*cfg_changed = true;
current_device_cfg.earfcnul = new_->earfcnul;
}
if (*cfg_changed)
{
logger_log(logger, sql_str, LOG_NOTICE, "Device-Cfg", true, true, NULL, 0, NULL, gPawsCloudLogger, gDeviceName, PAWS_LOG_TYPE);
if (!spectrum_override_present)
{
// run command
int rc = sqlite3_exec(sql_hdl, sql_str, NULL, NULL, &error_msg);
if (rc != SQLITE_OK)
{
goto error_hdl;
}
}
}
// Pmax
if ((new_->pmax/10) != (curr->pmax/10)) // divide by 10 as the femto.db does not have granularity to 0.1db
{
*cfg_changed = true;
current_device_cfg.pmax = new_->pmax;
// build SQL command
sprintf(sql_str, "UPDATE FAPServiceCellConfigLTERANMobilityIdleModeIntraFreq SET Pmax=%d", new_->pmax / 10);
logger_log(logger, sql_str, LOG_NOTICE, "Device-Cfg", true, true, NULL, 0, NULL, gPawsCloudLogger, gDeviceName, PAWS_LOG_TYPE);
if (!spectrum_override_present)
{
// run command
int rc = sqlite3_exec(sql_hdl, sql_str, NULL, NULL, &error_msg);
if (rc != SQLITE_OK)
{
goto error_hdl;
}
}
}
}
// AdminState
if (new_->admin_state != current_adminState)
{
current_adminState = new_->admin_state;
*admin_state_changed = true;
}
// free up resources
if (sql_hdl)
sqlite3_close(sql_hdl);
if ((*cfg_changed) && (new_->admin_state == true))
*reboot_needed = true;
// per device, check if device should always be rebooted when Admin is set to False)
if ((*admin_state_changed) && (new_->admin_state == false) && (reboot_device_on_admin_disable()))
{
*reboot_needed = true;
}
// log it
if (new_->admin_state)
{
float dl_mhz = (float)dl_earfcn_to_hz(13, new_->earfcndl) / 1000000;
float ul_mhz = (float)ul_earfcn_to_hz(13, new_->earfcnul) / 1000000;
float ref_sig_pwr = (new_->admin_state) ? ((float)new_->ref_sig_power / 10.0) : -99.9;
float total_ref_sig_pwr = (new_->admin_state) ? ((float)new_->total_ref_sig_power / 10.0) : -99.9;
float ul_pmax = (new_->admin_state) ? ((float)new_->pmax / 10.0) : -99.9;
char log_j_str[300];
sprintf(log_j_str, "{\"reboot\":%d, \"CfgChanged\":%d, \"device_enabled\":%d, \"Limited\":%d, \"Bandwidth\":%d, \"EARFCNDL\":%d, \"DL_MHz\":%.2f, \"EARFCNUL\":%d, \"UL_MHz\":%.2f, \"RefSigPower\":%.2f, \"TotalRefSigPower\":%.2f, \"Pmax\":%.2f, \"DeviceAntennaGain\":%.2f, \"LRE\":%.2f, \"DeviceMinPower\":%.2f, \"DeviceMaxPower\":%.2f }",
*reboot_needed, *cfg_changed, new_->admin_state,
new_->limited, new_->bandwidth, new_->earfcndl, dl_mhz, new_->earfcnul, ul_mhz, ref_sig_pwr, total_ref_sig_pwr, ul_pmax,
(float)new_->antenna_gain / 10.0, (float)new_->x_000295_external_pa_gain / 10.0, (float)new_->capabilities_min_tx_power / 10.0, (float)new_->capabilities_max_tx_power / 10.0);
logger_log(logger, log_j_str, LOG_NOTICE, "Device-Cfg", true, true, NULL, 0, NULL, gPawsCloudLogger, gDeviceName, PAWS_LOG_TYPE);
// DeviceCfg Cloud log
if (gPawsCloudLogger)
{
cloud_logger_log(gPawsCloudLogger, "Device-Cfg", gDeviceName, CLOUD_LOGGER_DEVICE_CFG, PAWS_LOG_TYPE, log_j_str);
}
}
else
{
char log_j_str[300];
sprintf(log_j_str, "{\"reboot\":%d, \"CfgChanged\":%d, \"device_enabled\":%d, \"RefSigPower\":-99.9, \"TotalRefSigPower\":-99.9, \"Pmax\":-99.9, \"DeviceAntennaGain\":%.2f, \"LRE\":%.2f, \"DeviceMinPower\":%.2f, \"DeviceMaxPower\":%.2f }",
*reboot_needed, *cfg_changed, new_->admin_state,
(float)new_->antenna_gain / 10.0, (float)new_->x_000295_external_pa_gain / 10.0, (float)new_->capabilities_min_tx_power / 10.0, (float)new_->capabilities_max_tx_power / 10.0);
logger_log(logger, log_j_str, LOG_NOTICE, "Device-Cfg", true, true, NULL, 0, NULL, gPawsCloudLogger, gDeviceName, PAWS_LOG_TYPE);
// DeviceCfg Cloud log
if (gPawsCloudLogger)
{
cloud_logger_log(gPawsCloudLogger, "Device-Cfg", gDeviceName, CLOUD_LOGGER_DEVICE_CFG, PAWS_LOG_TYPE, log_j_str);
}
}
return true;
error_hdl:
*cfg_changed = false;
*reboot_needed = false;
*admin_state_changed = false;
if (sql_hdl) sqlite3_close(sql_hdl);
return false;
}
//#######################################################################################
bool paws_config_master_device(void* logger, device_cfg_t* paws_cfg, bool* admin_state_changed, bool* cfg_changed, bool* reboot_needed, paws_setting_override_t* spectrum_override, paws_antenna_info_t* antenna_info)
{
device_cfg_params_t curr_device_cfg;
device_cfg_params_t new_device_cfg;
if (!(sql_get_master_cfg(&curr_device_cfg, spectrum_override->present)))
return false;
// create new config
if (!(create_device_cfg_params(logger, &new_device_cfg, curr_device_cfg.capabilities_min_tx_power, curr_device_cfg.capabilities_max_tx_power, paws_cfg, antenna_info->gain, curr_device_cfg.x_000295_external_pa_gain)))
{
// force the FAP to be disabled
new_device_cfg.admin_state = 0;
}
// write the config if necessary
if (!(process_device_cfg_params(logger, &new_device_cfg, &curr_device_cfg, admin_state_changed, cfg_changed, reboot_needed, spectrum_override->present)))
return false;
return true;
}
//#######################################################################################
void paws_reboot_master_device(void)
{
system_reboot();
}
//#######################################################################################
bool paws_config_master_device_override(void* logger, paws_setting_override_t* spectrum_override, paws_antenna_info_t* antenna_info)
{
device_cfg_params_t curr_device_cfg;
device_cfg_params_t new_device_cfg;
memset(&curr_device_cfg, 0, sizeof(device_cfg_params_t));
memset(&new_device_cfg, 0, sizeof(device_cfg_params_t));
bool admin_state_changed, cfg_changed, reboot_needed;
UNUSED_PARAM(antenna_info);
if (spectrum_override->present)
{
if (!(sql_get_master_cfg(&curr_device_cfg, false)))
return false;
// create new config
new_device_cfg.admin_state = true;
new_device_cfg.bandwidth = spectrum_override->bandwidth_rb;
new_device_cfg.earfcndl = spectrum_override->earfcndl;
new_device_cfg.earfcnul = spectrum_override->earfcnul;
new_device_cfg.ref_sig_power = spectrum_override->ref_sig_pwr;
new_device_cfg.pmax = spectrum_override->pmax;
if (!(limit_and_validate_cfg(logger, &new_device_cfg, curr_device_cfg.capabilities_min_tx_power, curr_device_cfg.capabilities_max_tx_power, antenna_info->gain, (MAX_RADIATED_POWER_DBM * 10), curr_device_cfg.x_000295_external_pa_gain)))
{
// force the FAP to be disabled
new_device_cfg.admin_state = 0;
}
// write the config if necessary
if (!(process_device_cfg_params(logger, &new_device_cfg, &curr_device_cfg, &admin_state_changed, &cfg_changed, &reboot_needed, false)))
return false;
if (reboot_needed)
{
paws_reboot_master_device();
}
return true;
}
return false;
}

View File

@@ -0,0 +1,34 @@
/*
Copyright (c) Microsoft Corporation. All rights reserved.
Licensed under the MIT License.
*/
#ifndef PAWS_DAL_CFG_DEVICE_H_
#define PAWS_DAL_CFG_DEVICE_H_
#include "paws_types.h"
typedef struct
{
// NOTE: all power fields are stored in this structure in units of 0.1dB.
// Some are written to the SQL db in this form, and some are converted to dB. This is governed by the SQL schema on a per fields basis.
bool admin_state; // enabled/disabled [FAPServiceFAPControlLTE].[AdminState]
int x_000295_external_pa_gain; // [-500:+500] in 0.1dBm, SQL: 0.1db [FAPServiceCellConfigLTERANRF].[X_000295_ExternalPAGain]
int capabilities_max_tx_power; // converted from dbM to units of 0.1dBm SQL: db [FAPServiceCapabilities].[MaxTxPower]
int capabilities_min_tx_power; // [-500:+500] in 0.1dBm, SQL: 0.1db [FAPServiceCapabilitiesLTE].[X_000295_MinTxPower]
int bandwidth; // in Number-of-RB 5MHz=25, 10MHz=50, 20MHz=100 [FAPServiceCellConfigLTERANRF].[ULBandwidth]
int earfcndl; // [FAPServiceCellConfigLTERANRF].EARFCNDL
int earfcnul; // [FAPServiceCellConfigLTERANRF].EARFCNUL
int pmax; // converted from dbM to units of 0.1dBm SQL: db [FAPServiceCellConfigLTERANMobilityIdleModeIntraFreq].[PMax]
int ref_sig_power; // converted from dbM to units of 0.1dBm SQL: db This is the DL power per RB [FAPServiceCellConfigLTERANRF].[ReferenceSignalPower]
int total_ref_sig_power; // in units of 0.1dB
int antenna_gain; // in units of 0.1dB
bool limited; // is configured power limited by FAP
} device_cfg_params_t;
#endif // PAWS_DAL_CFG_DEVICE_H_

View File

@@ -0,0 +1,38 @@
{
"jsonrpc": "2.0",
"method": "spectrum.paws.getSpectrum",
"params": {
"type": "AVAIL_SPECTRUM_REQ",
"version": "1.0",
"deviceDesc": {
"serialNumber": "M01D201621592159",
"manufacturerId": "IPAccess",
"modelId": "Radio",
"rulesetIds": [
"ETSI-EN-301-598-1.1.1"
],
"etsiEnDeviceType": "A",
"etsiEnDeviceCategory": "master",
"etsiEnDeviceEmissionsClass": 3,
"etsiEnTechnologyId": "AngularJS"
},
"location": {
"point": {
"center": {
"latitude": 51.507611,
"longitude": -0.111162
},
"semiMajorAxis": 0,
"semiMinorAxis": 0,
"orientation": 0
},
"confidence": 95
},
"antenna": {
"height": 15,
"heightType": "AGL",
"heightUncertainty": 0
}
},
"id": 0
}

View File

@@ -0,0 +1,33 @@
{
"jsonrpc": "2.0",
"method": "spectrum.paws.init",
"params": {
"type": "INIT_REQ",
"version": "1.0",
"deviceDesc": {
"serialNumber": "M01D201621592159",
"manufacturerId": "IPAccess",
"modelId": "Radio",
"rulesetIds": [
"ETSI-EN-301-598-1.1.1"
],
"etsiEnDeviceType": "A",
"etsiEnDeviceCategory": "master",
"etsiEnDeviceEmissionsClass": 3,
"etsiEnTechnologyId": "AngularJS"
},
"location": {
"point": {
"center": {
"latitude": 51.507611,
"longitude": -0.111162
},
"semiMajorAxis": 0,
"semiMinorAxis": 0,
"orientation": 0
},
"confidence": 95
}
},
"id": 0
}

View File

@@ -0,0 +1,36 @@
{
"jsonrpc": "2.0",
"method": "spectrum.paws.getSpectrum",
"params": {
"type": "AVAIL_SPECTRUM_REQ",
"version": "1.0",
"deviceDesc": {
"serialNumber": "M01D201621592159",
"manufacturerId": "IPAccess",
"modelId": "Radio",
"rulesetIds": [
"ETSI-EN-301-598-1.1.1"
],
"etsiEnDeviceType": "A",
"etsiEnDeviceCategory": "master",
"etsiEnDeviceEmissionsClass": "4",
"etsiEnTechnologyId": "AngularJS"
},
"location": {
"point": {
"center": {
"latitude": 51.507611,
"longitude": -0.111162
},
"semiMajorAxis": 0,
"semiMinorAxis": 0,
"orientation": 0
},
"confidence": 95
},
"requestType": "Generic Slave"
},
"id": 0
}

View File

@@ -0,0 +1,62 @@
{
"jsonrpc": "2.0",
"method": "spectrum.paws.getSpectrum",
"params": {
"type": "AVAIL_SPECTRUM_REQ",
"version": "1.0",
"deviceDesc": {
"serialNumber": "S01D201621592159",
"manufacturerId": "IPAccess",
"modelId": "Radio",
"rulesetIds": [
"ETSI-EN-301-598-1.1.1"
],
"etsiEnDeviceType": "B",
"etsiEnDeviceCategory": "slave",
"etsiEnDeviceEmissionsClass": 5,
"etsiEnTechnologyId": "AngularJS"
},
"location": {
"point": {
"center": {
"latitude": 51.507611,
"longitude": -0.111162
},
"semiMajorAxis": 0,
"semiMinorAxis": 0,
"orientation": 0
},
"confidence": 95
},
"antenna": {
"height": 15,
"heightType": "AGL",
"heightUncertainty": 0
},
"masterDeviceDesc": {
"serialNumber": "M01D201621592159",
"manufacturerId": "IPAccess",
"modelId": "Radio",
"rulesetIds": [
"ETSI-EN-301-598-1.1.1"
],
"etsiEnDeviceType": "A",
"etsiEnDeviceCategory": "master",
"etsiEnDeviceEmissionsClass": 3,
"etsiEnTechnologyId": "AngularJS"
},
"masterDeviceLocation": {
"point": {
"center": {
"latitude": 51.507611,
"longitude": -0.111162
},
"semiMajorAxis": 0,
"semiMinorAxis": 0,
"orientation": 0
},
"confidence": 95
}
},
"id": 0
}

View File

@@ -0,0 +1,47 @@
{
"jsonrpc": "2.0",
"method": "spectrum.paws.notifySpectrumUse",
"id": 0,
"params": {
"type": "SPECTRUM_USE_NOTIFY",
"version": "1.0",
"deviceDesc": {
"serialNumber": "S01D201621592159",
"manufacturerId": "IPAccess",
"modelId": "Radio",
"rulesetIds": [
"ETSI-EN-301-598-1.1.1"
],
"etsiEnDeviceType": "A",
"etsiEnDeviceCategory": "master",
"etsiEnDeviceEmissionsClass": 3,
"etsiEnTechnologyId": "AngularJS"
},
"masterDeviceDesc": {
"serialNumber": "M01D201621592159",
"manufacturerId": "IPAccess",
"modelId": "Radio",
"rulesetIds": [
"ETSI-EN-301-598-1.1.1"
],
"etsiEnDeviceType": "A",
"etsiEnDeviceCategory": "master",
"etsiEnDeviceEmissionsClass": 3,
"etsiEnTechnologyId": "AngularJS"
},
"masterDeviceLocation": {
"point": {
"center": {
"latitude": 51.507611,
"longitude": -0.111162
},
"semiMajorAxis": 0,
"semiMinorAxis": 0,
"orientation": 0
},
"confidence": 95
},
"spectra": [ ]
}
}

View File

@@ -0,0 +1,35 @@
{
"jsonrpc": "2.0",
"method": "spectrum.paws.notifySpectrumUse",
"id": 0,
"params": {
"type": "SPECTRUM_USE_NOTIFY",
"version": "1.0",
"deviceDesc": {
"serialNumber": "M01D201621592159",
"manufacturerId": "IPAccess",
"modelId": "Radio",
"rulesetIds": [
"ETSI-EN-301-598-1.1.1"
],
"etsiEnDeviceType": "A",
"etsiEnDeviceCategory": "master",
"etsiEnDeviceEmissionsClass": 3,
"etsiEnTechnologyId": "AngularJS"
},
"location": {
"point": {
"center": {
"latitude": 51.507611,
"longitude": -0.111162
},
"semiMajorAxis": 0,
"semiMinorAxis": 0,
"orientation": 0
},
"confidence": 95
},
"spectra": []
}
}

View File

@@ -0,0 +1,72 @@
/*
Copyright (c) Microsoft Corporation. All rights reserved.
Licensed under the MIT License.
*/
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <unistd.h>
#include <time.h>
#include "paws_globals.h"
#include "lte_db_info.h"
#include "paws_db_info.h"
#include "sctp_agent_db_info.h"
#include "paws_common.h"
#include "paws_combiner_sm.h"
#include "utils/types.h"
#include "utils/utils.h"
int main()
{
paws_combiner_sm_t* comb = NULL;
uint32_t sctp_agent_port;
uint32_t sctp_agent_status_perdiocity;
if (!(set_paws_db_location("/media/sf_4Gclient/apps/paws/sql_db/paws_native.db")))
fatal_error("Cant set PAWS-DB location");
if (!(set_sctp_agent_db_location("/media/sf_4Gclient/apps/sctp-agent/sql_db/sctp_agent_native.db")))
fatal_error("Cant set SCTP-AGENT-DB location");
if (!(set_lte_db_location("/media/sf_4Gclient/apps/paws/sql_db/femto.db")))
fatal_error("Cant set Device-DB location");
// create the ssl context.
if (!(https_init()))
fatal_error("Problem in https_init");
// get the CloudLog settings
get_gPawsLoggerSettings();
// get the DeviceId
populate_gDeviceName();
// loop until the SCTP settings are read correctly
while (1)
{
if ((get_sctp_agent_info(&sctp_agent_port, &sctp_agent_status_perdiocity)))
break;
sleep(1); // try in a second
}
if (!(comb = paws_combiner_sm_create("combiner", sctp_agent_port, sctp_agent_status_perdiocity)))
fatal_error("Cant initialise sytem");
PUBLIC_FUNC(comb, Run)(comb);
paws_combiner_sm_free(&comb);
PawsGlobalsFree();
// free ssl txt.
https_free();
return 0;
}

View File

@@ -0,0 +1,22 @@
/*
Copyright (c) Microsoft Corporation. All rights reserved.
Licensed under the MIT License.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "paws_device_specific.h"
//#######################################################################################
void system_reboot(void)
{
printf("%s NATIVE \n", __func__);
}
//#######################################################################################
bool reboot_device_on_admin_disable(void)
{
return true;
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,17 @@
/*
Copyright (c) Microsoft Corporation. All rights reserved.
Licensed under the MIT License.
*/
#ifndef PAWS_SM_COMBINER_H_
#define PAWS_SM_COMBINER_H_
#include "paws_combiner_sm_types.h"
extern paws_combiner_sm_t* paws_combiner_sm_create(const char* sm_name, uint32_t control_plane_status_port, uint32_t control_plane_status_periodicity);
extern void paws_combiner_sm_free(paws_combiner_sm_t** paws_combiner_sm);
#endif // #define PAWS_SM_COMBINER_H_

View File

@@ -0,0 +1,115 @@
/*
Copyright (c) Microsoft Corporation. All rights reserved.
Licensed under the MIT License.
*/
#ifndef PAWS_COMBINER_SM_TYPES_H_
#define PAWS_COMBINER_SM_TYPES_H_
#include "state-machine/state-machine.h"
#include "https-client/https.h"
#include "lists/lists.h"
#include "paws_types.h"
#include "paws_sm_types.h"
#include "paws_master_sm_types.h"
#include "paws_slave_sm_types.h"
#include "paws_dal_settings.h"
#include "paws_dal_state.h"
#include "paws_dal_control_plane.h"
typedef struct {
paws_sm_func Run;
void (*select_DB)(void* sm_, void* caller);
void (*DBerror)(void* sm_, void* caller);
paws_sm_func LocalDBerror;
void (*ProcessDbUpdate)(void* sm_, json_value* new_db_spec);
paws_sm_func DlSpectrumNotAvailable;
paws_sm_func DlSpectrumAvailable;
paws_sm_func UlSpectrumNotAvailable;
paws_sm_func UlSpectrumAvailable;
paws_sm_func UlSOPSpectrumNotAvailable;
void (*UlSOPSpectrumAvailable)(void* sm_, avail_spectrum_t* spectrum_resp, void* caller);
paws_sm_func DlNotificationSuccess;
paws_sm_func UlNotificationSuccess;
void (*setDefaultInfo)(void* sm_, float default_max_location_change, uint32_t default_max_polling_secs);
} paws_combiner_public_funcs_t;
typedef struct {
device_name_t device_name;
paws_sop_slave_sm_t* sm;
llist_item_t* l_item; // pointer back to entity on list for quicker deletion
} sop_slave_sm_entity_t;
typedef struct {
// slave device info
paws_slave_info_t gop_slave_info;
paws_slave_info_t sop_slave_info;
// SMs
paws_master_sm_t* paws_master_sm;
paws_gop_slave_sm_t* paws_gop_slave_sm;
llist_t* sop_sm_list; // list of sop_slave_sm_entity_t
// SOP min info
// the SopMin indicates if a SOP is one of the ones which is used to limit the DLUl powers.
// It must be tracked to determine if future processing is needed on a subsequent UlSpectrumAvailable call from that SOP.
uint16_t num_sop_min;
paws_sop_slave_sm_t* sop_min[MAX_SLAVE_DEVICES]; // list of SM pointers whcih are sop_min
// DB and DB Discovery stuff
paws_db_info_t db_info;
paws_db_discovery_info_t db_discovery_info;
// paws selection config
bool paws_settings_read;
paws_settings_t paws_settings;
// pre-boot state info
paws_sm_state_info_t* state_info;
// spectrum states
paws_spectrum_state_e dl_spec_state;
paws_spectrum_state_e ul_spec_state;
ul_dl_spec_cfg_t* ul_dl_spec; // current paired spectrum in use
// gps
uint32_t gps_periodic_duration;
paws_gps_location_t gps;
// master device has been read
bool master_info_read;
// control plane - do we pass Control signalling. When this is false, it is assumed no control is given to the device so it will not be radiating.
void* control_plane;
bool control_plane_enabled;
// has a reboot been triggered
bool reboot_needed;
// logger for the DeviceCfg
logger_cfg_t DeviceCfg_LogCfg;
void* DeviceCfg_Logger; // this is the config for the log messages
} paws_combiner_private_data_t;
typedef struct {
paws_sm_header_t paws_sm_hdr; // THIS MUST BE FIRST ENTRY IN ANY SM WHICH HAS A PAWS_SM.
paws_sm_funcs_t paws_sm_func_store;
paws_combiner_private_data_t private_data_store;
paws_combiner_public_funcs_t public_func_store;
control_plane_cfg_t control_plane_cfg;
paws_sm_t* paws_sm;
} paws_combiner_sm_t;
#endif // #define PAWS_COMBINER_SM_TYPES_H_

View File

@@ -0,0 +1,43 @@
/*
Copyright (c) Microsoft Corporation. All rights reserved.
Licensed under the MIT License.
*/
#ifndef PAWS_COMMON_H_
#define PAWS_COMMON_H_
#include "paws_sm.h"
#include "utils/utils.h"
// common macros used by "users" of paws_sm
#define POPULATE_PAWS_SM_FUNC(sm,fnc) sm->paws_sm_hdr.funcs->fnc = fnc;
#define POPULATE_PUBLIC_FUNC(sm,fnc) sm->public_func_store.fnc = fnc;
#define PAWS_SM_FUNC(sm,fnc) (sm)->paws_sm->local_funcs.fnc // This is used to directly call a paws_sm function even though it might have overridden by this class
#define LOCAL_FUNC(sm,fnc) ((paws_sm_t*)sm)->paws_sm_hdr.funcs->fnc // This is used to call a paws_sm function which "might have" been overridden by this class
#define PUBLIC_FUNC(sm,fnc) (sm)->public_func_store.fnc
#define COMBINER_PUBLIC_FUNC(sm,fnc) PUBLIC_FUNC((paws_combiner_sm_t*)sm, fnc)
#define MASTER_PUBLIC_FUNC(sm,fnc) PUBLIC_FUNC((paws_master_sm_t*)sm, fnc)
#define GOP_PUBLIC_FUNC(sm,fnc) PUBLIC_FUNC((paws_gop_slave_sm_t*)sm, fnc)
#define SOP_PUBLIC_FUNC(sm,fnc) PUBLIC_FUNC((paws_sop_slave_sm_t*)sm, fnc)
#define GOP_FUNC(sm, fnc) (sm)->gop_slave_hdr.funcs->fnc
#define SOP_FUNC(sm, fnc) (sm)->sop_slave_hdr.funcs->fnc
#define PAWS_SM_DATA(sm) ((paws_sm_t*)sm)->paws_sm_hdr.data
#define PAWS_SM_STL_DATA(sm) ((paws_sm_t*)sm)->paws_sm_hdr.stl_data
#define PRIVATE_DATA(sm) (sm)->private_data_store
#define CREATOR_SM(sm_) ((paws_sm_t*)sm_)->paws_sm_hdr.creator
#define PAWS_LOG_TYPE "PAWS"
#define CLOUD_LOGGER_TVWSDB_MSG "TVWSDB-MSG"
#define CLOUD_LOGGER_DEVICE_CFG "DEVICE-CFG"
#endif // #define PAWS_COMMON_H_

View File

@@ -0,0 +1,186 @@
/*
Copyright (c) Microsoft Corporation. All rights reserved.
Licensed under the MIT License.
*/
// Platform headers
#ifdef _MSC_VER
#include <winsock2.h>
typedef unsigned socklen_t;
#else
#include <arpa/inet.h>
#include <errno.h>
#include <fcntl.h>
#include <netdb.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/socket.h>
#include "utils/utils.h"
#include "paws_dal_control_plane.h"
typedef struct {
control_plane_cfg_t cfg;
int sock;
} control_plane_t;
//#######################################################################################
static int make_outgoing_socket(const char *ip_addr_str, unsigned port)
{
int sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock == -1)
{
goto error_hdl;
}
struct sockaddr_in ip_addr = { 0 };
ip_addr.sin_family = AF_INET;
ip_addr.sin_port = htons(port);
if (inet_pton(AF_INET, ip_addr_str, &(ip_addr.sin_addr)) < 0)
{
goto error_hdl;
}
if (connect(sock, &ip_addr, sizeof(ip_addr)) < 0)
{
goto error_hdl;
}
return sock;
error_hdl:
if (sock >= 0) close(sock);
return -1;
}
//#######################################################################################
void* paws_dal_control_plane_create(control_plane_cfg_t* cfg)
{
control_plane_t* control_plane = NULL;
if (!cfg)
{
return NULL;
}
if (((strlen(cfg->status_ipaddr) == 0)) || (cfg->status_port == 0))
{
return NULL;
}
// malloc a new control_plane_t
if (!(control_plane = malloc(sizeof(control_plane_t))))
{
return NULL;
}
memset(control_plane, 0, sizeof(control_plane_t));
// copy the config
memcpy(&control_plane->cfg, cfg, sizeof(control_plane_cfg_t));
// open the socket
control_plane->sock = -1;
// if this fails, still return control_plane, and attempt to open it when we send data,
// This way we can start PAWS before control-plane-agent without any catastrophies
control_plane->sock = make_outgoing_socket(cfg->status_ipaddr, cfg->status_port);
return (void*)control_plane;
}
//#######################################################################################
void paws_dal_control_plane_free(void** control_plane_)
{
if (!((control_plane_) && (*control_plane_)))
return;
control_plane_t** control_plane = (control_plane_t**)control_plane_;
// free the socket
if ((*control_plane)->sock >= 0)
{
close((*control_plane)->sock);
(*control_plane)->sock = -1;
}
// free the struct
free_and_null(control_plane_);
}
//#######################################################################################
bool paws_dal_control_plane_send_status(void* control_plane_, bool status)
{
if (!control_plane_)
{
return false;
}
control_plane_t* control_plane = (control_plane_t*)control_plane_;
if (((strlen(control_plane->cfg.status_ipaddr) == 0)) || (control_plane->cfg.status_port == 0))
{
return false;
}
if (control_plane->sock == -1)
{
// open the socket
if ((control_plane->sock = make_outgoing_socket(control_plane->cfg.status_ipaddr, control_plane->cfg.status_port)) == -1)
{
return false;
}
}
// try to send a packet
size_t num_to_send = sizeof(status);
ssize_t num_sent = send(control_plane->sock, &status, num_to_send, MSG_DONTWAIT | MSG_NOSIGNAL);
if (num_sent != (ssize_t)num_to_send)
{
// try again
// delete and recreate the socket
if (control_plane->sock >= 0)
{
close(control_plane->sock);
control_plane->sock = -1;
}
if ((control_plane->sock = make_outgoing_socket(control_plane->cfg.status_ipaddr, control_plane->cfg.status_port)) == -1)
{
return false;
}
// re-send the data
num_sent = send(control_plane->sock, &status, num_to_send, MSG_DONTWAIT | MSG_NOSIGNAL);
if (num_sent != (ssize_t)num_to_send)
{
return false;
}
}
return true;
}

View File

@@ -0,0 +1,27 @@
/*
Copyright (c) Microsoft Corporation. All rights reserved.
Licensed under the MIT License.
*/
#ifndef PAWS_DAL_CONTROL_PLANE_H_
#define PAWS_DAL_CONTROL_PLANE_H_
#include <stdint.h>
#include <stdbool.h>
#include "utils/types.h"
typedef struct {
ip_addr_t status_ipaddr;
uint32_t status_port;
uint32_t status_periodicity;
} control_plane_cfg_t;
extern void* paws_dal_control_plane_create(control_plane_cfg_t* cfg);
extern void paws_dal_control_plane_free(void** control_plane);
extern bool paws_dal_control_plane_send_status(void* control_plane, bool status);
#endif // PAWS_DAL_CONTROL_PLANE_H_

View File

@@ -0,0 +1,92 @@
/*
Copyright (c) Microsoft Corporation. All rights reserved.
Licensed under the MIT License.
*/
#ifndef PAWS_DAL_DATABASE_H_
#define PAWS_DAL_DATABASE_H_
#include <stdint.h>
#include <stdbool.h>
#include <time.h>
// This is the PAWS Data Abstraction layer.
// It is responsible for reading and writing all data to stroage.
// It is expected that developers will implment individual source for this entity, on a per-platform basis.
// *********************************************************************
// Database
// *********************************************************************
#define MAX_URL_LENGTH (100)
#define MAX_WEBLIST_NAME_LENGTH (30)
#define MAX_DB_TOKEN_LENGTH (128)
#define MAX_DB_NAME_LENGTH (64)
typedef char paws_url_t[MAX_URL_LENGTH];
typedef char paws_weblist_name_t[MAX_WEBLIST_NAME_LENGTH];
typedef char paws_db_token_t[MAX_DB_TOKEN_LENGTH];
typedef char paws_db_name_t[MAX_DB_NAME_LENGTH];
typedef struct {
paws_url_t host;
paws_weblist_name_t fname;
} paws_weblist_url_t;
typedef struct {
paws_url_t host;
paws_db_token_t token;
} paws_db_url_t;
typedef struct {
paws_db_name_t name;
paws_url_t url;
bool mcwsd_support;
bool invalid;
} weblist_item_t;
typedef struct
{
uint32_t refresh_rate;
uint16_t num_items;
weblist_item_t* items;
} paws_weblist_t;
typedef struct
{
paws_db_name_t name;
paws_db_url_t db_url;
uint8_t valid; // is it present in the weblist
time_t barred_utc; // what time was it barred. 0 = not barred
} paws_db_item_t;
#define PAWS_MAX_DB_LIST (10)
typedef struct {
paws_weblist_url_t weblist_url;
uint32_t num_db;
paws_db_item_t db_list[PAWS_MAX_DB_LIST];
} paws_db_info_t;
// *********************************************************************
// Read/write functons
// *********************************************************************
// Return True if read OK.
extern bool paws_read_db(paws_db_info_t* db);
// Return True if written OK.
extern bool paws_write_db(paws_db_info_t* db);
#endif // PAWS_DAL_GPS_H_

View File

@@ -0,0 +1,106 @@
/*
Copyright (c) Microsoft Corporation. All rights reserved.
Licensed under the MIT License.
*/
#ifndef PAWS_DAL_DEVICES_H_
#define PAWS_DAL_DEVICES_H_
// This is the PAWS Data Abstraction layer.
// It is responsible for reading and writing all data to stroage.
// It is expected that developers will implment individual source for this entity, on a per-platform basis.
#include <stdint.h>
#include <stdbool.h>
#include "utils/types.h"
#include "paws_dal_settings.h"
#include "paws_dal_gps.h"
// *********************************************************************
// device info
// *********************************************************************
#define PAWS_MAX_DEVICE_TECHNOLOGY_LEN (30)
#define PAWS_MAX_DEVICE_MANUFACTURER_LEN (30)
#define PAWS_MAX_DEVICE_MODEL_LEN (20)
#define PAWS_MAX_DEVICE_TYPE_LEN (2)
#define PAWS_MAX_DEVICE_CATEGORY_LEN (7)
typedef char paws_device_tech_t[PAWS_MAX_DEVICE_TECHNOLOGY_LEN];
typedef char paws_device_manufacturer_t[PAWS_MAX_DEVICE_MANUFACTURER_LEN];
typedef char paws_device_model_t[PAWS_MAX_DEVICE_MODEL_LEN];
typedef char paws_device_type_t[PAWS_MAX_DEVICE_TYPE_LEN];
typedef char paws_device_category_t[PAWS_MAX_DEVICE_CATEGORY_LEN];
typedef struct {
int gain; // Stored in units of 0.1dB. SQL schema stores it as a float in unts of dB
} paws_antenna_info_t;
typedef struct {
paws_device_manufacturer_t manufacturer;
paws_device_model_t model;
} paws_device_identity_t;
typedef struct {
paws_device_type_t type;
paws_device_category_t cat;
int emission_class;
paws_device_tech_t technology_id;
} paws_device_characteristics_t;
typedef struct {
device_name_t unique_id;
paws_antenna_info_t antenna_info;
paws_device_identity_t device_identity;
paws_device_characteristics_t device_characteristics;
paws_gps_location_t gps;
} paws_device_info_t;
#define MAX_SLAVE_DEVICES (256)
typedef struct {
uint16_t num_devices;
paws_device_info_t device_info[MAX_SLAVE_DEVICES];
} paws_slave_info_t;
typedef struct
{
bool device_enabled; // enable/disable the master
int bandwidth;
int dl_start_hz;
float dl_dbm_per100k;
int ul_start_hz;
float ul_dbm_per100k;
} device_cfg_t;
// *********************************************************************
// Read/write functons
// *********************************************************************
// Return True if read OK.
extern bool paws_read_master_info(log_app_t app, paws_device_info_t* dev, bool* master_device_cfg_read);
// Return True if read OK.
extern bool paws_read_slave_info(log_app_t app, paws_slave_info_t* gop_slaves, paws_slave_info_t* sop_slaves);
// get the device Id
extern bool paws_get_device_name(device_name_t device_name);
// Return True if configured OK.
// Sets *reboot_needed to True if cfg changes require a reboot
extern bool paws_config_master_device(void* logger, device_cfg_t* paws_cfg, bool* admin_state_changed, bool* cfg_changed, bool* reboot_needed, paws_setting_override_t* spectrum_override, paws_antenna_info_t* antenna_info);
// trigger to reboot the device
extern void paws_reboot_master_device(void);
// Return True if configured OK.
// Sets *reboot_needed to True if cfg changes require a reboot
extern bool paws_config_master_device_override(void* logger, paws_setting_override_t* spectrum_override, paws_antenna_info_t* antenna_info);
#endif // PAWS_DAL_DEVICES_H_

View File

@@ -0,0 +1,44 @@
/*
Copyright (c) Microsoft Corporation. All rights reserved.
Licensed under the MIT License.
*/
#ifndef PAWS_DAL_GPS_H_
#define PAWS_DAL_GPS_H_
// This is the PAWS Data Abstraction layer.
// It is responsible for reading and writing all data to stroage.
// It is expected that developers will implment individual source for this entity, on a per-platform basis.
#include <stdint.h>
#include <stdbool.h>
// *********************************************************************
// GPS
// *********************************************************************
#define MAX_ANT_HEIGHT_TYPE_LEN (20)
typedef char paws_antenna_height_type_t[MAX_ANT_HEIGHT_TYPE_LEN];
typedef struct
{
device_name_t device_name;
bool fixed; // location has been acquired
float latitude;
float longitude;
uint16_t height;
paws_antenna_height_type_t height_type;
} paws_gps_location_t;
// *********************************************************************
// Read/write functons
// *********************************************************************
// Return True if read OK.
extern bool paws_read_gps_from_db(paws_gps_location_t* gps, device_name_t device_name);
extern void paws_read_gps(paws_gps_location_t* data, device_name_t device_name);
#endif // PAWS_DAL_GPS_H_

View File

@@ -0,0 +1,67 @@
/*
Copyright (c) Microsoft Corporation. All rights reserved.
Licensed under the MIT License.
*/
#ifndef PAWS_DAL_SETTINGS_H_
#define PAWS_DAL_SETTINGS_H_
// This is the PAWS Data Abstraction layer.
// It is responsible for reading and writing all data to stroage.
// It is expected that developers will implment individual source for this entity, on a per-platform basis.
#include <stdint.h>
#include <stdbool.h>
#include "utils/types.h"
#include "logger/logger.h"
// *********************************************************************
// Config
// *********************************************************************
typedef struct {
logger_cfg_t app_log;
logger_cfg_t msg_log;
cloud_logger_cfg_t cloud_log;
} paws_setting_loginfo_t;
typedef struct {
bool present;
uint16_t bandwidth_rb;
uint16_t earfcndl;
uint16_t earfcnul;
int16_t ref_sig_pwr; // stored in units of 0.1dB
int16_t pmax; // stored in units of 0.1dB
} paws_setting_override_t;
typedef struct
{
// spectrum selected criteria
float min_dl_dbm_100k; // min DL dbm per 100k to qualify for selection
float min_ul_dbm_100k; // min UL dbm per 100k to qualify for selection
// timer info
uint16_t db_retry_secs; // how often to retry events (default=15)
uint16_t db_barred_secs; // how long to barr a specific DB following failure (default=45)
uint16_t setting_periodic_secs; // how often to re-read paws-settings (default=300).
uint16_t devices_periodic_secs; // how often to re-read device info (default=60).
uint16_t gps_periodic_fast_check_secs; // how often to re-read GPS (default=15). Used when GPS is "NOT" acquired
uint16_t gps_periodic_slow_check_secs; // how often to re-read GPS (default=600). Used when GPS "IS" acquired
uint32_t max_polling_quick_secs; // quici maxPollingSecs. 0=disable
// logging
paws_setting_loginfo_t loginfo;
// override
paws_setting_override_t spectrum_override; // can override the spectrum which the TVWSDB provides in the AVAIL_SPEC_RESP.
} paws_settings_t;
// *********************************************************************
// Read/write functons
// *********************************************************************
extern bool paws_read_settings(paws_settings_t* settings);
#endif // PAWS_DAL_SETTINGS_H_

View File

@@ -0,0 +1,144 @@
/*
Copyright (c) Microsoft Corporation. All rights reserved.
Licensed under the MIT License.
*/
#ifndef PAWS_DAL_STATE_H_
#define PAWS_DAL_STATE_H_
#include "paws_dal_gps.h"
#include "paws_dal_database.h"
#include "lists/lists.h"
// This is the PAWS Data Abstraction layer.
// It is responsible for reading and writing all data to stroage.
// It is expected that developers will implment individual source for this entity, on a per-platform basis.
// *********************************************************************
// PAWS state info.
// This is stored prior to reboot, and read post-boot.
// *********************************************************************
typedef struct
{
uint32_t maxPollingSecs;
float maxLocationChange;
} ruleset_info_t;
typedef struct
{
time_t start_time;
time_t stop_time;
} time_range_t;
typedef struct spec_profile_type
{
uint32_t start_hz;
uint32_t end_hz;
float dbm;
struct spec_profile_type* next;
} spec_profile_type_t;
typedef struct spectrum_schedule
{
time_range_t event_time_range;
spec_profile_type_t* profiles;
struct spectrum_schedule* next;
uint8_t refcnt; // there can be multiple references, so use this to control the free
} spectrum_schedule_t;
typedef struct spectrum_spec
{
spectrum_schedule_t* spectrum_schedules;
float max_contiguous_bw_hz; // 0 if not present. 0 will mean no constraint
float max_contiguous_bw_hz_within_band; // max contiguous actually within band
bool needsSpectrumReport; // false if not preset
ruleset_info_t ruleset_info;
struct spectrum_spec* next;
uint8_t refcnt; // there can be multiple references, so use this to control the free
} spectrum_spec_t;
typedef struct
{
spectrum_spec_t* spectrum_specs;
uint8_t refcnt; // there can be multiple references, so use this to control the free
} avail_spectrum_t;
typedef struct {
spectrum_spec_t* spec;
spectrum_schedule_t* sched;
uint32_t start_hz;
float dbm;
uint32_t bandwidth;
uint8_t refcnt; // there can be multiple references, so use this to control the free
} spec_cfg_t;
typedef struct
{
spec_cfg_t* dl_cfg;
spec_cfg_t* ul_cfg;
uint8_t refcnt; // there can be multiple references, so use this to control the free
} ul_dl_spec_cfg_t;
typedef struct
{
device_name_t unique_id;
int stl_current_state;
char* timer_info;
float default_max_location_change;
uint32_t default_max_polling_secs;
float specific_max_location_change;
uint32_t specific_max_polling_secs;
paws_gps_location_t gps;
paws_db_item_t selected_db;
avail_spectrum_t* avail_spectrum_resp;
spec_cfg_t* available_spectrum;
spec_cfg_t* pending_spectrum;
spec_cfg_t* selected_spectrum;
spec_cfg_t* spectrum_in_use;
llist_item_t* l_item;
} sm_state_info_t;
typedef enum {
SPEC_STATE_NOT_AVAIL = 0,
SPEC_STATE_AVAIL,
SPEC_STATE_NOTIFICATION_SUCCESS
} paws_spectrum_state_e;
typedef struct
{
paws_weblist_t *wsbd_weblist;
int db_discovery_duration;
} paws_db_discovery_info_t;
typedef struct
{
paws_spectrum_state_e dl_spec_state;
paws_spectrum_state_e ul_spec_state;
paws_db_discovery_info_t db_discovery_info;
ul_dl_spec_cfg_t* ul_dl_spec;
llist_t* state_info_ll; // list of sm_state_info_t
} paws_sm_state_info_t;
// *********************************************************************
// Read/write functons
// *********************************************************************
// Return NULL if empty.
extern paws_sm_state_info_t* paws_read_state(void);
extern void paws_remove_state(void);
// Return True if read OK.
// state is not to be freed inside function
extern bool paws_write_state(paws_sm_state_info_t* state);
#endif // PAWS_DAL_STATE_H_

View File

@@ -0,0 +1,296 @@
/*
Copyright (c) Microsoft Corporation. All rights reserved.
Licensed under the MIT License.
*/
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <sys/stat.h>
#include <time.h>
#include "utils/utils.h"
#include "paws_types.h"
//#######################################################################################
spectrum_schedule_t* spectrum_sched_new(void)
{
spectrum_schedule_t* sched = NULL;
if ((sched = malloc(sizeof(spectrum_schedule_t))))
{
memset(sched, 0, sizeof(spectrum_schedule_t));
sched->refcnt = 1;
return sched;
}
return NULL;
}
spectrum_schedule_t* spectrum_sched_vcopy(spectrum_schedule_t* sched)
{
if (sched)
{
sched->refcnt++;
}
return sched;
}
void spectrum_sched_free(spectrum_schedule_t** sched)
{
if ((sched) && (*sched))
{
(*sched)->refcnt--;
if ((*sched)->refcnt == 0)
{
spec_profile_type_t* prof = (*sched)->profiles;
spec_profile_type_t* next = NULL;
while (prof)
{
next = prof->next;
free(prof);
prof = next;
}
free_and_null((void**)sched);
}
*sched = NULL;
}
}
//#######################################################################################
spectrum_spec_t* spectrum_spec_new(void)
{
spectrum_spec_t* spec = NULL;
if ((spec = malloc(sizeof(spectrum_spec_t))))
{
memset(spec, 0, sizeof(spectrum_spec_t));
spec->refcnt = 1;
return spec;
}
return NULL;
}
spectrum_spec_t* spectrum_spec_vcopy(spectrum_spec_t* spec)
{
if (spec)
{
spec->refcnt++;
}
return spec;
}
void spectrum_spec_free(spectrum_spec_t** spec)
{
if ((spec) && (*spec))
{
(*spec)->refcnt--;
if ((*spec)->refcnt == 0)
{
spectrum_schedule_t* sched = (*spec)->spectrum_schedules;
spectrum_schedule_t* next = NULL;
while (sched)
{
next = sched->next;
spectrum_sched_free(&sched);
sched = next;
}
free_and_null((void**)spec);
}
*spec = NULL;
}
}
//#######################################################################################
avail_spectrum_t* avail_spectrum_new(void)
{
avail_spectrum_t* spec = NULL;
if ((spec = malloc(sizeof(avail_spectrum_t))))
{
memset(spec, 0, sizeof(avail_spectrum_t));
spec->refcnt = 1;
return spec;
}
return NULL;
}
avail_spectrum_t* avail_spectrum_vcopy(avail_spectrum_t* spec)
{
if (spec)
{
spec->refcnt++;
}
return spec;
}
void avail_spectrum_free(avail_spectrum_t** avail_spec)
{
if ((avail_spec) && (*avail_spec))
{
(*avail_spec)->refcnt--;
if ((*avail_spec)->refcnt == 0)
{
avail_spectrum_t* s = *avail_spec;
spectrum_spec_t* spec = s->spectrum_specs;
spectrum_spec_t* next = NULL;
while (spec)
{
next = spec->next;
spectrum_spec_free(&spec);
spec = next;
}
free_and_null((void**)avail_spec);
}
*avail_spec = NULL;
}
}
//#######################################################################################
spec_cfg_t* spec_cfg_new(void)
{
spec_cfg_t* cfg = NULL;
if ((cfg = malloc(sizeof(spec_cfg_t))))
{
memset(cfg, 0, sizeof(spec_cfg_t));
cfg->refcnt = 1;
return cfg;
}
return NULL;
}
spec_cfg_t* spec_cfg_vcopy(spec_cfg_t* cfg)
{
if (cfg)
{
cfg->refcnt++;
}
return cfg;
}
void spec_cfg_free(spec_cfg_t** cfg)
{
if ((cfg) && (*cfg))
{
(*cfg)->refcnt--;
if ((*cfg)->refcnt == 0)
{
if ((*cfg)->spec)
spectrum_spec_free((spectrum_spec_t**)&((*cfg)->spec));
if ((*cfg)->sched)
spectrum_sched_free((spectrum_schedule_t**)&((*cfg)->sched));
free_and_null((void**)cfg);
}
*cfg = NULL;
}
}
//#######################################################################################
ul_dl_spec_cfg_t* ul_dl_spec_cfg_new(void)
{
ul_dl_spec_cfg_t* cfg = NULL;
if ((cfg = malloc(sizeof(ul_dl_spec_cfg_t))))
{
memset(cfg, 0, sizeof(ul_dl_spec_cfg_t));
cfg->refcnt = 1;
return cfg;
}
return NULL;
}
ul_dl_spec_cfg_t* ul_dl_spec_cfg_vcopy(ul_dl_spec_cfg_t* cfg)
{
if (cfg)
{
cfg->refcnt++;
}
return cfg;
}
void ul_dl_spec_cfg_free(ul_dl_spec_cfg_t** cfg)
{
if ((cfg) && (*cfg))
{
(*cfg)->refcnt--;
if ((*cfg)->refcnt == 0)
{
if ((*cfg)->dl_cfg)
spec_cfg_free(&((*cfg)->dl_cfg));
if ((*cfg)->ul_cfg)
spec_cfg_free(&((*cfg)->ul_cfg));
free_and_null((void**)cfg);
}
*cfg = NULL;
}
}
//#######################################################################################
sm_state_info_t* sm_state_info_new(void)
{
sm_state_info_t* info = NULL;
if ((info = malloc(sizeof(sm_state_info_t))))
{
memset(info, 0, sizeof(sm_state_info_t));
return info;
}
return NULL;
}
// this is used to free from llist too
int sm_state_info_free(void* info_)
{
sm_state_info_t* info = (sm_state_info_t*)info_;
if (info)
{
free_and_null((void**)&(info->timer_info));
avail_spectrum_free(&info->avail_spectrum_resp);
spec_cfg_free(&info->available_spectrum);
spec_cfg_free(&info->pending_spectrum);
spec_cfg_free(&info->selected_spectrum);
spec_cfg_free(&info->spectrum_in_use);
free(info);
}
return 0;
}
void sm_state_info_free_and_null(sm_state_info_t** info)
{
if ((info) && (*info))
{
sm_state_info_free((void*)*info);
*info = NULL;
}
}
paws_sm_state_info_t* paws_sm_state_info_new(void)
{
paws_sm_state_info_t* info = NULL;
if ((info = malloc(sizeof(paws_sm_state_info_t))))
{
memset(info, 0, sizeof(paws_sm_state_info_t));
return info;
}
return NULL;
}
extern void paws_sm_state_info_free(paws_sm_state_info_t** info)
{
if ((info) && (*info))
{
if ((*info)->ul_dl_spec) ul_dl_spec_cfg_free(&(*info)->ul_dl_spec);
llist_free(&(*info)->state_info_ll, sm_state_info_free);
free_and_null((void**)info);
}
}

View File

@@ -0,0 +1,45 @@
/*
Copyright (c) Microsoft Corporation. All rights reserved.
Licensed under the MIT License.
*/
#ifndef PAWS_DAL_TYPES_
#define PAWS_DAL_TYPES_
#include "paws_dal_devices.h"
#include "paws_dal_settings.h"
#include "paws_dal_state.h"
#include "paws_dal_database.h"
#include "paws_dal_control_plane.h"
extern spectrum_schedule_t* spectrum_sched_new(void);
extern spectrum_schedule_t* spectrum_sched_vcopy(spectrum_schedule_t* sched);
extern void spectrum_sched_free(spectrum_schedule_t** sched);
extern spectrum_spec_t* spectrum_spec_new(void);
extern spectrum_spec_t* spectrum_spec_vcopy(spectrum_spec_t* spec);
extern void spectrum_spec_free(spectrum_spec_t** spec);
extern avail_spectrum_t* avail_spectrum_new(void);
extern avail_spectrum_t* avail_spectrum_vcopy(avail_spectrum_t* spec);
extern void avail_spectrum_free(avail_spectrum_t** avail_spec);
extern spec_cfg_t* spec_cfg_new(void);
extern spec_cfg_t* spec_cfg_vcopy(spec_cfg_t* spec);
extern void spec_cfg_free(spec_cfg_t** cfg);
extern ul_dl_spec_cfg_t* ul_dl_spec_cfg_new(void);
extern ul_dl_spec_cfg_t* ul_dl_spec_cfg_vcopy(ul_dl_spec_cfg_t* cfg);
extern void ul_dl_spec_cfg_free(ul_dl_spec_cfg_t** cfg);
extern sm_state_info_t* sm_state_info_new(void);
extern int sm_state_info_free(void* info_);
extern void sm_state_info_free_and_null(sm_state_info_t** info);
extern paws_sm_state_info_t* paws_sm_state_info_new(void);
extern void paws_sm_state_info_free(paws_sm_state_info_t** info);
#endif // PAWS_DAL_TYPES_

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,24 @@
/*
Copyright (c) Microsoft Corporation. All rights reserved.
Licensed under the MIT License.
*/
#ifndef PAWS_DAL_UTILS_H_
#define PAWS_DAL_UTILS_H_
#include "json-parser/json.h"
#include "paws_dal_types.h"
extern char* get_init_paws_dal_encode_str(void);
extern char* paws_sm_state_info_2_jsonstr(paws_sm_state_info_t* paws_sm_state_info);
extern char* paws_db_info_2_jsonstr(paws_db_info_t* db_info);
extern bool json_2_paws_db_item(json_value* jval, paws_db_item_t* db_item);
extern paws_sm_state_info_t* json2_paws_sm_state_info(json_value* jval);
#endif

View File

@@ -0,0 +1,397 @@
/*
Copyright (c) Microsoft Corporation. All rights reserved.
Licensed under the MIT License.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/stat.h>
#include <time.h>
#include <sqlite3.h>
#include "utils/utils.h"
#include "json-parser/json.h"
#include "json-parser/json_utils.h"
#include "paws_db_info.h"
#include "paws_types.h"
#include "paws_utils.h"
#include "paws_dal_utils.h"
//#######################################################################################
#define MAX_SQL_LEN (200)
static char sql_str[MAX_SQL_LEN];
static char tmp[200];
#define SQL_STRCAT(s) strncat(sql_str, s, MAX_SQL_LEN - strlen(sql_str) - 1);
//#######################################################################################
static bool sql_get_weblist(sqlite3 *sql_hdl, paws_weblist_url_t* weblist_url)
{
// get the TVWSDBInfo info
sqlite3_stmt *stmt=NULL;
char sql[100];
sprintf(sql, "SELECT weblist_host, weblist_filename FROM TVWSDBInfo");
int rc = sqlite3_prepare_v2(sql_hdl, sql, -1, &stmt, NULL);
if (rc != SQLITE_OK)
{
goto error_hdl;
}
// clear host to start
weblist_url->host[0] = '\0';
while ((rc = sqlite3_step(stmt)) == SQLITE_ROW)
{
char *tmp;
tmp = (char*)sqlite3_column_text(stmt, 0); strcpy(weblist_url->host, tmp);
tmp = (char*)sqlite3_column_text(stmt, 1); strcpy(weblist_url->fname, tmp);
}
if (rc != SQLITE_DONE)
{
goto error_hdl;
}
sqlite3_finalize(stmt);
return true;
error_hdl:
if (stmt) sqlite3_finalize(stmt);
return false;
}
//#######################################################################################
bool paws_read_db(paws_db_info_t* db)
{
sqlite3 *sql_hdl = NULL;
sqlite3_stmt *stmt = NULL;
if (!db)
{
goto error_hdl;
}
memset(db, 0, sizeof(paws_db_info_t));
// get datafile location and open it
char* db_sql_file = get_paws_db_location();
if (!db_sql_file)
{
goto error_hdl;
}
sqlite3_open(db_sql_file, &sql_hdl);
if (!sql_hdl)
{
goto error_hdl;
}
// get the weblist info
if (!(sql_get_weblist(sql_hdl, &db->weblist_url)))
{
goto error_hdl;
}
// now get the database entries
const char *sql = "SELECT name, host, token, valid, barred_utc FROM TVWSDBInfoDB";
int rc = sqlite3_prepare_v2(sql_hdl, sql, -1, &stmt, NULL);
if (rc != SQLITE_OK)
{
goto error_hdl;
}
while ((rc = sqlite3_step(stmt)) == SQLITE_ROW)
{
paws_db_item_t* db_item = &db->db_list[db->num_db] ;
char *tmp;
tmp = (char*)sqlite3_column_text(stmt, 0); strcpy(db_item->name, tmp);
tmp = (char*)sqlite3_column_text(stmt, 1); strcpy(db_item->db_url.host, tmp);
tmp = (char*)sqlite3_column_text(stmt, 2); strcpy(db_item->db_url.token, tmp);
db_item->valid = sqlite3_column_int(stmt, 3);
tmp = (char*)sqlite3_column_text(stmt, 4);
if ((tmp) && (strlen(tmp) > 0))
{
if ((db_item->barred_utc = timestamp_to_timet(tmp)) == -1)
{
goto error_hdl;
}
}
db->num_db++;
}
if (rc != SQLITE_DONE)
{
goto error_hdl;
}
sqlite3_finalize(stmt);
stmt = NULL;
// free up resources
if (sql_hdl)
sqlite3_close(sql_hdl);
return true;
error_hdl:
if (stmt) sqlite3_finalize(stmt);
if (sql_hdl) sqlite3_close(sql_hdl);
db->num_db = 0;
return false;
}
//#######################################################################################
static paws_db_item_t* get_db_from_dblist(paws_db_item_t* db1, int num_db_in_list, paws_db_item_t* db_list)
{
for (int i = 0; i < num_db_in_list; i++)
{
paws_db_item_t* db2 = &db_list[i];
// they are the same if the url matches
if (strcmp(db1->db_url.host, db2->db_url.host) == 0)
return db2;
}
return NULL;
}
//#######################################################################################
static bool sql_add_db_item(paws_db_item_t* db_item)
{
sqlite3 *sql_hdl = NULL;
char* error_msg = NULL;
if (!db_item)
{
goto error_hdl;
}
// get datafile location and open it
char* db_sql_file = get_paws_db_location();
if (!db_sql_file)
{
goto error_hdl;
}
sqlite3_open(db_sql_file, &sql_hdl);
if (!sql_hdl)
{
goto error_hdl;
}
// build SQL command
sql_str[0] = '\0';
SQL_STRCAT("INSERT INTO TVWSDBInfoDB (name, host, token, valid");
if (db_item->barred_utc)
{
SQL_STRCAT(", barred_utc ");
}
SQL_STRCAT(") VALUES ( ");
sprintf(tmp, "'%s', '%s', '%s', %d", db_item->name, db_item->db_url.host, db_item->db_url.token, db_item->valid);
SQL_STRCAT(tmp);
if (db_item->barred_utc)
{
SQL_STRCAT(", '");
strftime(tmp, sizeof(tmp), "%Y-%m-%dT%H:%M:%SZ", gmtime(&db_item->barred_utc));
SQL_STRCAT(tmp);
SQL_STRCAT("'");
}
SQL_STRCAT(");");
// run command
int rc = sqlite3_exec(sql_hdl, sql_str, NULL, NULL, &error_msg);
if (rc != SQLITE_OK)
{
goto error_hdl;
}
// free up resources
if (error_msg) sqlite3_free(error_msg);
if (sql_hdl) sqlite3_close(sql_hdl);
return true;
error_hdl:
if (error_msg) sqlite3_free(error_msg);
if (sql_hdl) sqlite3_close(sql_hdl);
return false;
}
//#######################################################################################
static bool sql_update_db_item(paws_db_item_t* db_item)
{
sqlite3 *sql_hdl = NULL;
char* error_msg = NULL;
if (!db_item)
{
goto error_hdl;
}
// get datafile location and open it
char* db_sql_file = get_paws_db_location();
if (!db_sql_file)
{
goto error_hdl;
}
sqlite3_open(db_sql_file, &sql_hdl);
if (!sql_hdl)
{
goto error_hdl;
}
// build SQL command
sql_str[0] = '\0';
sprintf(tmp, "UPDATE TVWSDBInfoDB SET "); SQL_STRCAT(tmp);
sprintf(tmp, "name = '%s'", db_item->name); SQL_STRCAT(tmp);
sprintf(tmp, ", token = '%s'", db_item->db_url.token); SQL_STRCAT(tmp);
sprintf(tmp, ", valid = %d", db_item->valid); SQL_STRCAT(tmp);
SQL_STRCAT(", barred_utc='");
if (db_item->barred_utc)
{
strftime(tmp, sizeof(tmp), "%Y-%m-%dT%H:%M:%SZ", gmtime(&db_item->barred_utc));
SQL_STRCAT(tmp);
}
SQL_STRCAT("'");
sprintf(tmp, " WHERE host = '%s' ;", db_item->db_url.host); SQL_STRCAT(tmp);
// run command
int rc = sqlite3_exec(sql_hdl, sql_str, NULL, NULL, &error_msg);
if (rc != SQLITE_OK)
{
goto error_hdl;
}
// free up resources
if (error_msg) sqlite3_free(error_msg);
if (sql_hdl) sqlite3_close(sql_hdl);
return true;
error_hdl:
if (error_msg) sqlite3_free(error_msg);
if (sql_hdl) sqlite3_close(sql_hdl);
return false;
}
//#######################################################################################
static bool sql_delete_db_item(paws_db_item_t* db_item)
{
sqlite3 *sql_hdl = NULL;
char* error_msg = NULL;
if (!db_item)
{
goto error_hdl;
}
// get datafile location and open it
char* db_sql_file = get_paws_db_location();
if (!db_sql_file)
{
goto error_hdl;
}
sqlite3_open(db_sql_file, &sql_hdl);
if (!sql_hdl)
{
goto error_hdl;
}
// build SQL command
sprintf(sql_str, "DELETE FROM TVWSDBInfoDB WHERE host = '%s' ;", db_item->db_url.host);
// run command
int rc = sqlite3_exec(sql_hdl, sql_str, NULL, NULL, &error_msg);
if (rc != SQLITE_OK)
{
goto error_hdl;
}
// free up resources
if (error_msg) sqlite3_free(error_msg);
if (sql_hdl) sqlite3_close(sql_hdl);
return true;
error_hdl:
if (error_msg) sqlite3_free(error_msg);
if (sql_hdl) sqlite3_close(sql_hdl);
return false;
}
//#######################################################################################
bool paws_write_db(paws_db_info_t* db)
{
uint32_t i = 0;
if (!db)
{
goto error_hdl;
}
// read the current DB
paws_db_info_t curr_db;
if (!(paws_read_db(&curr_db)))
{
goto error_hdl;
}
// add or update DB
for (i = 0; i < db->num_db; i++) // walk new db
{
paws_db_item_t* db_item = &db->db_list[i];
paws_db_item_t* curr_db_item = NULL;
if (!(curr_db_item = get_db_from_dblist(db_item, curr_db.num_db, &curr_db.db_list[0]))) // if new db is not in curr db list, add it
{
// it is not there, so add it
if (!(sql_add_db_item(db_item)))
{
goto error_hdl;
}
}
else
{ // if new db is in curr db list, check if it is different, and if so update it
// it is there, so update it if different
if (memcmp(db_item, curr_db_item, sizeof(paws_db_item_t)) != 0)
{
// update it
if (!(sql_update_db_item(db_item)))
{
goto error_hdl;
}
}
}
}
// delete any which have been removed
for (i = 0; i < curr_db.num_db; i++) // walk curr db. If any DB from curr_db are not in new db list, delete it from the sql
{
paws_db_item_t* curr_db_item = &curr_db.db_list[i];
paws_db_item_t* new_db_item = NULL;
if (!(new_db_item = get_db_from_dblist(curr_db_item, db->num_db, &db->db_list[0]))) // if curr db is not in new db list, delete it
{
// delete it
if (!(sql_delete_db_item(curr_db_item)))
{
goto error_hdl;
}
}
}
return true;
error_hdl:
return false;
}

View File

@@ -0,0 +1,314 @@
/*
Copyright (c) Microsoft Corporation. All rights reserved.
Licensed under the MIT License.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/stat.h>
#include <time.h>
#include <sqlite3.h>
#include "utils/utils.h"
#include "json-parser/json.h"
#include "json-parser/json_utils.h"
#include "paws_globals.h"
#include "paws_common.h"
#include "paws_db_info.h"
#include "paws_types.h"
#include "paws_dal_utils.h"
//#######################################################################################
static bool sql_get_DeviceInfoAntenna(sqlite3 *sql_hdl, char* deviceid, paws_antenna_info_t* device_ant, bool* antenna_info_read)
{
*antenna_info_read = false;
// get the Antenna info
sqlite3_stmt *stmt=NULL;
char sql[200];
sprintf(sql, "SELECT gain FROM DeviceInfoAntenna where deviceid='%s'", deviceid);
int rc = sqlite3_prepare_v2(sql_hdl, sql, -1, &stmt, NULL);
if (rc != SQLITE_OK)
{
goto error_hdl;
}
while ((rc = sqlite3_step(stmt)) == SQLITE_ROW)
{
device_ant->gain = (int)((float)sqlite3_column_double(stmt, 0) * 10.0); // Stored in units of 0.1dB. SQL schema stores it as a float in uints of dB
*antenna_info_read = true;
}
if (rc != SQLITE_DONE)
{
goto error_hdl;
}
sqlite3_finalize(stmt);
return true;
error_hdl:
if (stmt) sqlite3_finalize(stmt);
return false;
}
//#######################################################################################
static bool sql_get_DeviceInfoId(sqlite3 *sql_hdl, char* deviceid, paws_device_identity_t* device_info_id, bool* device_name_read)
{
*device_name_read = false;
// get the Antenna info
sqlite3_stmt *stmt=NULL;
char sql[100];
sprintf(sql, "SELECT manufacturer, model FROM DeviceInfo where deviceid='%s'", deviceid);
int rc = sqlite3_prepare_v2(sql_hdl, sql, -1, &stmt, NULL);
if (rc != SQLITE_OK)
{
goto error_hdl;
}
while ((rc = sqlite3_step(stmt)) == SQLITE_ROW)
{
char *tmp;
tmp = (char*)sqlite3_column_text(stmt, 0); strcpy(device_info_id->manufacturer, tmp);
tmp = (char*)sqlite3_column_text(stmt, 1); strcpy(device_info_id->model, tmp);
*device_name_read = true;
}
if (rc != SQLITE_DONE)
{
goto error_hdl;
}
sqlite3_finalize(stmt);
return true;
error_hdl:
if (stmt) sqlite3_finalize(stmt);
return false;
}
//#######################################################################################
bool paws_read_master_info(log_app_t app, paws_device_info_t* dev, bool* master_device_cfg_read)
{
sqlite3 *sql_hdl = NULL;
sqlite3_stmt *stmt=NULL;
bool device_characteristics_read = false;
bool antenna_info_read = false;
bool device_name_read = false;
*master_device_cfg_read = false;
if (!dev)
{
goto error_hdl;
}
memset(dev, 0, sizeof(paws_device_info_t));
// get datafile location and open it
char* db_sql_file = get_paws_db_location();
if (!db_sql_file)
{
goto error_hdl;
}
sqlite3_open(db_sql_file, &sql_hdl);
if (!sql_hdl)
{
goto error_hdl;
}
// get the Device Characteristcs for the master device
const char *sql = "SELECT deviceid, type, cat, emission_class, technology_id FROM DeviceInfoCharacteristics where cat='master'";
int rc = sqlite3_prepare_v2(sql_hdl, sql, -1, &stmt, NULL);
if (rc != SQLITE_OK)
{
goto error_hdl;
}
paws_device_characteristics_t* device_characteristics = &dev->device_characteristics;
while ((rc = sqlite3_step(stmt)) == SQLITE_ROW)
{
char *tmp;
tmp = (char*)sqlite3_column_text(stmt, 0);
if (strcmp(gDeviceName, tmp) != 0)
{
char log[100];
snprintf(log, sizeof(log), "Device mismatch: femto_db='%s' paws_db='%s'", gDeviceName, tmp);
logger_log(gPawsAppLogger, log, LOG_ERROR, app, true, true, __FILENAME__, __LINE__, __func__, gPawsCloudLogger, gDeviceName, PAWS_LOG_TYPE);
goto error_hdl;
}
strcpy(dev->unique_id, tmp);
tmp = (char*)sqlite3_column_text(stmt, 1); strcpy(device_characteristics->type, tmp);
tmp = (char*)sqlite3_column_text(stmt, 2); strcpy(device_characteristics->cat, tmp);
device_characteristics->emission_class = sqlite3_column_int(stmt, 3);
tmp = (char*)sqlite3_column_text(stmt, 4); strcpy(device_characteristics->technology_id, tmp);
device_characteristics_read = true;
}
if (rc != SQLITE_DONE)
{
goto error_hdl;
}
sqlite3_finalize(stmt);
stmt = NULL;
// get the Antenna info
if (device_characteristics_read)
{
if (!(sql_get_DeviceInfoAntenna(sql_hdl, dev->unique_id, &dev->antenna_info, &antenna_info_read)))
{
goto error_hdl;
}
}
// get the Device info
if (antenna_info_read)
{
if (!(sql_get_DeviceInfoId(sql_hdl, dev->unique_id, &dev->device_identity, &device_name_read)))
{
goto error_hdl;
}
}
// free up resources
if (sql_hdl)
sqlite3_close(sql_hdl);
*master_device_cfg_read = (device_characteristics_read && antenna_info_read && device_name_read);
return true;
error_hdl:
if (stmt) sqlite3_finalize(stmt);
if (sql_hdl) sqlite3_close(sql_hdl);
*master_device_cfg_read = false;
return false;
}
//#######################################################################################
bool paws_read_slave_info(log_app_t app, paws_slave_info_t* gop_slaves, paws_slave_info_t* sop_slaves)
{
sqlite3 *sql_hdl = NULL;
sqlite3_stmt *stmt=NULL;
(void)app; // currently unused
if ((!gop_slaves) || (!sop_slaves))
{
goto error_hdl;
}
memset(gop_slaves, 0, sizeof(paws_slave_info_t));
memset(sop_slaves, 0, sizeof(paws_slave_info_t));
// get datafile location and open it
char* db_sql_file = get_paws_db_location();
if (!db_sql_file)
{
goto error_hdl;
}
sqlite3_open(db_sql_file, &sql_hdl);
if (!sql_hdl)
{
goto error_hdl;
}
// get the Device Characteristcs for the all slave devices
const char *sql = "SELECT deviceid, type, cat, emission_class, technology_id FROM DeviceInfoCharacteristics where cat='slave' ORDER BY deviceid";
int rc = sqlite3_prepare_v2(sql_hdl, sql, -1, &stmt, NULL);
if (rc != SQLITE_OK)
{
goto error_hdl;
}
while ((rc = sqlite3_step(stmt)) == SQLITE_ROW)
{
paws_device_info_t device;
paws_device_info_t* dev = &device;
memset(dev, 0, sizeof(paws_device_info_t));
paws_device_characteristics_t* device_characteristics = &dev->device_characteristics;
char *tmp;
tmp = (char*)sqlite3_column_text(stmt, 0); strcpy(dev->unique_id, tmp);
tmp = (char*)sqlite3_column_text(stmt, 1); strcpy(device_characteristics->type, tmp);
tmp = (char*)sqlite3_column_text(stmt, 2); strcpy(device_characteristics->cat, tmp);
device_characteristics->emission_class = sqlite3_column_int(stmt, 3);
tmp = (char*)sqlite3_column_text(stmt, 4); strcpy(device_characteristics->technology_id, tmp);
bool device_name_read = false;
// get the Device info
if (!(sql_get_DeviceInfoId(sql_hdl, dev->unique_id, &dev->device_identity, &device_name_read)))
{
goto error_hdl;
}
if (device_name_read)
{
// is this SOP - if a GPS is present and fixed it is a SOP slave, else it is a GOP slave
bool sop = ((paws_read_gps_from_db(&dev->gps, dev->unique_id)) && (dev->gps.fixed));
// if this is a GOP but there were previously SOPs counted, move all these SOPS to GOPs
if ((!sop) && (sop_slaves->num_devices > 0))
{
memcpy(&gop_slaves->device_info[gop_slaves->num_devices], &sop_slaves->device_info[0],
sizeof(paws_device_info_t) * sop_slaves->num_devices);
gop_slaves->num_devices += sop_slaves->num_devices;
sop_slaves->num_devices = 0;
}
// if there are any GOPs, we will not run any SOPs, so count SOP as GOP in this case
if (sop && (gop_slaves->num_devices == 0))
{
memcpy(&sop_slaves->device_info[sop_slaves->num_devices], dev, sizeof(paws_device_info_t));
sop_slaves->num_devices++;
}
else
{
memcpy(&gop_slaves->device_info[gop_slaves->num_devices], dev, sizeof(paws_device_info_t));
gop_slaves->num_devices++;
}
}
}
if (rc != SQLITE_DONE)
{
goto error_hdl;
}
sqlite3_finalize(stmt);
stmt = NULL;
// free up resources
if (sql_hdl)
sqlite3_close(sql_hdl);
return true;
error_hdl:
if (stmt) sqlite3_finalize(stmt);
if (sql_hdl) sqlite3_close(sql_hdl);
sop_slaves->num_devices = 0;
gop_slaves->num_devices = 0;
return false;
}

View File

@@ -0,0 +1,144 @@
/*
Copyright (c) Microsoft Corporation. All rights reserved.
Licensed under the MIT License.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/stat.h>
#include <time.h>
#include <sqlite3.h>
#include "utils/utils.h"
#include "json-parser/json.h"
#include "json-parser/json_utils.h"
#include "gps/gps.h"
#include "paws_db_info.h"
#include "paws_types.h"
#include "paws_dal_utils.h"
//#######################################################################################
bool paws_read_gps_from_db(paws_gps_location_t* gps, device_name_t device_name)
{
char **pazResult = NULL;
sqlite3 *sql_hdl = NULL;
gps->fixed = false;
if (!gps)
{
goto error_hdl;
}
memset(gps, 0, sizeof(paws_gps_location_t));
// get datafile location and open it
char* db_sql_file = get_paws_db_location();
if (!db_sql_file)
{
goto error_hdl;
}
sqlite3_open(db_sql_file, &sql_hdl);
if (!sql_hdl)
{
goto error_hdl;
}
char zSql[100];
sprintf(zSql, "SELECT * FROM Gps where deviceid='%s'", device_name);
int pnRow; /* Number of result rows written here */
int pnColumn; /* Number of result columns written here */
char *pzErrmsg = NULL;
int rc = sqlite3_get_table(
sql_hdl, /* An open database */
zSql, /* SQL to be evaluated */
&pazResult, /* Results of the query */
&pnRow, /* Number of result rows written here */
&pnColumn, /* Number of result columns written here */
&pzErrmsg /* Error msg written here */
);
if (rc != SQLITE_OK)
{
goto error_hdl;
}
if (!((pnRow == 1) && (pnColumn == 6)))
{
goto error_hdl;
}
for (int row = 0; row < pnRow; row++)
{
for (int col = 0; col < pnColumn; col++)
{
int index = (row * pnColumn) + pnColumn + col;
if (strcmp(pazResult[col], "deviceid") == 0)
strcpy(gps->device_name, pazResult[index]);
else if (strcmp(pazResult[col], "fixed") == 0)
gps->fixed =atoi(pazResult[index]) != 0;
else if (strcmp(pazResult[col], "latitude") == 0)
gps->latitude = (float)atof(pazResult[index]);
else if (strcmp(pazResult[col], "longitude") == 0)
gps->longitude = (float)atof(pazResult[index]);
else if (strcmp(pazResult[col], "height") == 0)
gps->height = atoi(pazResult[index]);
else if (strcmp(pazResult[col], "heightType") == 0)
strcpy(gps->height_type, pazResult[index]);
else
{
goto error_hdl;
}
}
}
// free up resources
if (pazResult)
sqlite3_free_table(pazResult);
if (sql_hdl)
sqlite3_close(sql_hdl);
return gps->fixed;
error_hdl:
if (pazResult) sqlite3_free_table(pazResult);
if (sql_hdl) sqlite3_close(sql_hdl);
return false;
}
//#######################################################################################
static void paws_read_gps_from_device(paws_gps_location_t* gps, device_name_t device_name)
{
GpsFixData fix;
if (gps_get_fix(&fix) == -1)
{
gps->fixed = false;
return;
}
// map from GpsFixData to paws_gps_location_t
strcpy(gps->device_name, device_name);
gps->fixed = true;
gps->latitude = fix.latitude;
gps->longitude = fix.longitude;
gps->height = fix.altitude;
snprintf(gps->height_type, sizeof(paws_antenna_height_type_t), "AMSL");
}
//#######################################################################################
void paws_read_gps(paws_gps_location_t* gps, device_name_t device_name)
{
bool ret = paws_read_gps_from_db(gps, device_name);
if (!ret)
{
paws_read_gps_from_device(gps, device_name);
}
}

View File

@@ -0,0 +1,336 @@
/*
Copyright (c) Microsoft Corporation. All rights reserved.
Licensed under the MIT License.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/stat.h>
#include <time.h>
#include <sqlite3.h>
#include "utils/utils.h"
#include "json-parser/json.h"
#include "json-parser/json_utils.h"
#include "paws_db_info.h"
#include "paws_types.h"
#include "paws_dal_utils.h"
// ########################################################################
static bool paws_read_settingsCloudLogInfo(sqlite3 *sql_hdl, cloud_logger_cfg_t* log_cfg)
{
if ((!sql_hdl) || (!log_cfg))
{
return false;
}
memset(log_cfg, 0, sizeof(cloud_logger_cfg_t));
const char *zSql = "SELECT * FROM SettingsCloudLogInfo";
int pnRow; /* Number of result rows written here */
int pnColumn; /* Number of result columns written here */
char *pzErrmsg = NULL;
char **pazResult = NULL;
int rc = sqlite3_get_table(
sql_hdl, /* An open database */
zSql, /* SQL to be evaluated */
&pazResult, /* Results of the query */
&pnRow, /* Number of result rows written here */
&pnColumn, /* Number of result columns written here */
&pzErrmsg /* Error msg written here */
);
if (!((rc == SQLITE_OK) && (pnRow == 1) && (pnColumn == 4)))
{
goto error_hdl;
}
for (int row = 0; row < pnRow; row++)
{
for (int col = 0; col < pnColumn; col++)
{
int index = (row * pnColumn) + pnColumn + col;
if (strcmp(pazResult[col], "level") == 0)
log_cfg->level = atoi(pazResult[index]);
else if (strcmp(pazResult[col], "logname") == 0)
{
if (pazResult[index])
strcpy(log_cfg->logname, pazResult[index]);
}
else if (strcmp(pazResult[col], "port") == 0)
log_cfg->port = atoi(pazResult[index]);
else if (strcmp(pazResult[col], "cloud_ip") == 0)
{
if (pazResult[index])
strcpy(log_cfg->cloud_addr, pazResult[index]);
}
else
{
goto error_hdl;
}
}
}
// free up resources
if (pazResult)
sqlite3_free_table(pazResult);
return true;
error_hdl:
if (pazResult) sqlite3_free_table(pazResult);
return false;
}
// ########################################################################
static bool paws_read_settingsLogInfo(sqlite3 *sql_hdl, paws_setting_loginfo_t* loginfo)
{
if ((!sql_hdl) || (!loginfo))
{
return false;
}
memset(loginfo, 0, sizeof(paws_setting_loginfo_t));
// first read the Cloud log
if (!(paws_read_settingsCloudLogInfo(sql_hdl, &loginfo->cloud_log)))
{
goto error_hdl;
}
const char *zSql = "SELECT * FROM SettingsLogInfo";
int pnRow; /* Number of result rows written here */
int pnColumn; /* Number of result columns written here */
char *pzErrmsg = NULL;
char **pazResult = NULL;
int rc = sqlite3_get_table(
sql_hdl, /* An open database */
zSql, /* SQL to be evaluated */
&pazResult, /* Results of the query */
&pnRow, /* Number of result rows written here */
&pnColumn, /* Number of result columns written here */
&pzErrmsg /* Error msg written here */
);
if (!((rc == SQLITE_OK) && (pnRow == 1) && (pnColumn == 6)))
{
goto error_hdl;
}
for (int row = 0; row < pnRow; row++)
{
for (int col = 0; col < pnColumn; col++)
{
int index = (row * pnColumn) + pnColumn + col;
if (strcmp(pazResult[col], "level") == 0)
loginfo->app_log.level = atoi(pazResult[index]);
else if (strcmp(pazResult[col], "logname") == 0)
strcpy(loginfo->app_log.logname, pazResult[index]);
else if (strcmp(pazResult[col], "tvwsdb_messages_logname") == 0)
strcpy(loginfo->msg_log.logname, pazResult[index]);
else if (strcmp(pazResult[col], "file_size") == 0)
strcpy(loginfo->app_log.size, pazResult[index]);
else if (strcmp(pazResult[col], "max_files") == 0)
loginfo->app_log.max = atoi(pazResult[index]);
else if (strcmp(pazResult[col], "compress") == 0)
loginfo->app_log.compress = atoi(pazResult[index]);
else
{
goto error_hdl;
}
}
}
loginfo->msg_log.level = loginfo->app_log.level;
loginfo->msg_log.level = loginfo->app_log.level;
strcpy(loginfo->msg_log.size, loginfo->app_log.size);
loginfo->msg_log.max = loginfo->app_log.max;
loginfo->msg_log.compress = loginfo->app_log.compress;
loginfo->app_log.cloud_level = loginfo->cloud_log.level;
loginfo->msg_log.cloud_level = loginfo->cloud_log.level;
// free up resources
if (pazResult)
sqlite3_free_table(pazResult);
return true;
error_hdl:
if (pazResult) sqlite3_free_table(pazResult);
return false;
}
// ########################################################################
static bool paws_read_settingsSpectrumOverride(sqlite3 *sql_hdl, paws_setting_override_t* override)
{
if ((!sql_hdl) || (!override))
{
return false;
}
memset(override, 0, sizeof(paws_setting_override_t));
const char *zSql = "SELECT * FROM SettingsSpectrumOverride";
int pnRow; /* Number of result rows written here */
int pnColumn; /* Number of result columns written here */
char *pzErrmsg = NULL;
char **pazResult = NULL;
int rc = sqlite3_get_table(
sql_hdl, /* An open database */
zSql, /* SQL to be evaluated */
&pazResult, /* Results of the query */
&pnRow, /* Number of result rows written here */
&pnColumn, /* Number of result columns written here */
&pzErrmsg /* Error msg written here */
);
if (!(rc == SQLITE_OK))
{
goto error_hdl;
}
if ((pnRow == 1) && (pnColumn == 6))
{
for (int row = 0; row < pnRow; row++)
{
for (int col = 0; col < pnColumn; col++)
{
int index = (row * pnColumn) + pnColumn + col;
if (strcmp(pazResult[col], "present") == 0)
override->present = atoi(pazResult[index]) != 0;
else if (strcmp(pazResult[col], "bandwidth_rb") == 0)
override->bandwidth_rb = atoi(pazResult[index]);
else if (strcmp(pazResult[col], "earfcndl") == 0)
override->earfcndl = atoi(pazResult[index]);
else if (strcmp(pazResult[col], "earfcnul") == 0)
override->earfcnul = atoi(pazResult[index]);
else if (strcmp(pazResult[col], "RefSigPower") == 0)
override->ref_sig_pwr = atoi(pazResult[index]) * 10; // convert to units of 0.1dB
else if (strcmp(pazResult[col], "PMax") == 0)
override->pmax = atoi(pazResult[index]) * 10; // convert to units of 0.1dB
else
{
goto error_hdl;
}
}
}
}
// free up resources
if (pazResult)
sqlite3_free_table(pazResult);
return true;
error_hdl:
if (pazResult) sqlite3_free_table(pazResult);
return false;
}
//#######################################################################################
bool paws_read_settings(paws_settings_t* settings)
{
sqlite3 *sql_hdl = NULL;
if (!settings)
{
return false;
}
memset(settings, 0, sizeof(paws_settings_t));
// get datafile location and open it
char* db_sql_file = get_paws_db_location();
if (!db_sql_file)
{
goto error_hdl;
}
sqlite3_open(db_sql_file, &sql_hdl);
if (!sql_hdl)
{
return false;
}
const char *zSql = "SELECT * FROM Settings";
int pnRow; /* Number of result rows written here */
int pnColumn; /* Number of result columns written here */
char *pzErrmsg=NULL;
char **pazResult=NULL;
int rc = sqlite3_get_table(
sql_hdl, /* An open database */
zSql, /* SQL to be evaluated */
&pazResult, /* Results of the query */
&pnRow, /* Number of result rows written here */
&pnColumn, /* Number of result columns written here */
&pzErrmsg /* Error msg written here */
);
if (!((rc == SQLITE_OK) && (pnRow == 1) && (pnColumn == 9)))
{
goto error_hdl;
}
for (int row = 0; row < pnRow; row++)
{
for (int col = 0; col < pnColumn; col++)
{
int index = (row * pnColumn) + pnColumn + col;
if (strcmp(pazResult[col], "min_dl_dbm_100k") == 0)
settings->min_dl_dbm_100k = (float)atof(pazResult[index]);
else if (strcmp(pazResult[col], "min_ul_dbm_100k") == 0)
settings->min_ul_dbm_100k = (float)atof(pazResult[index]);
else if (strcmp(pazResult[col], "db_retry_secs") == 0)
settings->db_retry_secs = atoi(pazResult[index]);
else if (strcmp(pazResult[col], "db_barred_secs") == 0)
settings->db_barred_secs = atoi(pazResult[index]);
else if (strcmp(pazResult[col], "setting_periodic_secs") == 0)
settings->setting_periodic_secs = atoi(pazResult[index]);
else if (strcmp(pazResult[col], "devices_periodic_secs") == 0)
settings->devices_periodic_secs = atoi(pazResult[index]);
else if (strcmp(pazResult[col], "gps_periodic_fast_check_secs") == 0)
settings->gps_periodic_fast_check_secs = atoi(pazResult[index]);
else if (strcmp(pazResult[col], "gps_periodic_slow_check_secs") == 0)
settings->gps_periodic_slow_check_secs = atoi(pazResult[index]);
else if (strcmp(pazResult[col], "max_polling_quick_secs") == 0)
settings->max_polling_quick_secs = atoi(pazResult[index]);
else
{
goto error_hdl;
}
}
}
// free up resources
if (pazResult)
sqlite3_free_table(pazResult);
if (!(paws_read_settingsLogInfo(sql_hdl, &settings->loginfo)))
{
goto error_hdl;
}
if (!(paws_read_settingsSpectrumOverride(sql_hdl, &settings->spectrum_override)))
{
goto error_hdl;
}
// free up resources
if (sql_hdl)
sqlite3_close(sql_hdl);
return true;
error_hdl:
if (pazResult) sqlite3_free_table(pazResult);
if (sql_hdl) sqlite3_close(sql_hdl);
return false;
}

View File

@@ -0,0 +1,200 @@
/*
Copyright (c) Microsoft Corporation. All rights reserved.
Licensed under the MIT License.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/stat.h>
#include <time.h>
#include <sqlite3.h>
#include "utils/utils.h"
#include "json-parser/json.h"
#include "json-parser/json_utils.h"
#include "paws_db_info.h"
#include "paws_types.h"
#include "paws_utils.h"
#include "paws_dal_utils.h"
//#######################################################################################
paws_sm_state_info_t* paws_read_state(void)
{
sqlite3 *sql_hdl = NULL;
char *json_str=NULL;
sqlite3_stmt *stmt=NULL;
paws_sm_state_info_t* sm_info = NULL;
json_value *jval = NULL;
// get datafile location and open it
char* db_sql_file = get_paws_db_location();
if (!db_sql_file)
{
goto error_hdl;
}
sqlite3_open(db_sql_file, &sql_hdl);
if (!sql_hdl)
{
goto error_hdl;
}
// get the state
const char *sql = "SELECT state_str FROM PreBootState";
int rc = sqlite3_prepare_v2(sql_hdl, sql, -1, &stmt, NULL);
if (rc != SQLITE_OK)
{
goto error_hdl;
}
while ((rc = sqlite3_step(stmt)) == SQLITE_ROW)
{
json_str = (char*)sqlite3_column_text(stmt, 0);
if (json_str) // if something was read
{
int len = strlen(json_str);
// now convert the json string to a paws_sm_state_info_t
// we have the contents, now convert to json
if (!(jval = json_parse((json_char*)json_str, len)))
{
goto error_hdl;
}
if (!(sm_info = json2_paws_sm_state_info(jval)))
{
goto error_hdl;
}
}
}
if (rc != SQLITE_DONE)
{
goto error_hdl;
}
// free up resources
if (stmt)
sqlite3_finalize(stmt);
stmt = NULL;
if (sql_hdl)
sqlite3_close(sql_hdl);
if (jval)
json_value_free(jval);
// return the sm info
return sm_info;
error_hdl:
if (stmt) sqlite3_finalize(stmt);
if (sql_hdl) sqlite3_close(sql_hdl);
if (jval) json_value_free(jval);
return NULL;
}
//#######################################################################################
void paws_remove_state(void)
{
sqlite3 *sql_hdl = NULL;
char* error_msg = NULL;
// get datafile location and open it
char* db_sql_file = get_paws_db_location();
if (!db_sql_file)
{
goto error_hdl;
}
sqlite3_open(db_sql_file, &sql_hdl);
if (!sql_hdl)
{
goto error_hdl;
}
// build SQL command
char sql_str[100];
sprintf(sql_str, "DELETE FROM PreBootState ;");
// run command
int rc = sqlite3_exec(sql_hdl, sql_str, NULL, NULL, &error_msg);
if (rc != SQLITE_OK)
{
goto error_hdl;
}
error_hdl:
// free up resources
if (error_msg) sqlite3_free(error_msg);
if (sql_hdl) sqlite3_close(sql_hdl);
}
//#######################################################################################
bool paws_write_state(paws_sm_state_info_t* sm_state_info)
{
sqlite3 *sql_hdl = NULL;
char* error_msg = NULL;
char* sql_str = NULL;
char* p_sql_str = NULL;
json_value* jval = NULL;
sql_str = get_init_paws_dal_encode_str();
// build SQL command
sprintf(sql_str, "INSERT INTO PreBootState (state_str) VALUES ( '");
// point to where the json is to be written
p_sql_str = sql_str + strlen(sql_str);
if (!(paws_sm_state_info_2_jsonstr(sm_state_info)))
return false;
// we have the contents, now convert to json to check it is valid
int slen = strlen(p_sql_str);
if (!(jval = json_parse((json_char*)p_sql_str, slen)))
{
return false;
}
// append the end
p_sql_str += slen;
sprintf(p_sql_str, "' ) ;");
// j contains a valid json string, so write it to the SQL
paws_remove_state(); // for safety remove any current state, however there shouldnt actually be any
// get datafile location and open it
char* db_sql_file = get_paws_db_location();
if (!db_sql_file)
{
goto error_hdl;
}
sqlite3_open(db_sql_file, &sql_hdl);
if (!sql_hdl)
{
goto error_hdl;
}
// run command
int rc = sqlite3_exec(sql_hdl, sql_str, NULL, NULL, &error_msg);
if (rc != SQLITE_OK)
{
goto error_hdl;
}
// free up resources
if (error_msg) sqlite3_free(error_msg);
if (sql_hdl) sqlite3_close(sql_hdl);
if (jval) json_value_free(jval);
return true;
error_hdl:
if (error_msg) sqlite3_free(error_msg);
if (sql_hdl) sqlite3_close(sql_hdl);
if (jval) json_value_free(jval);
return false;
}

View File

@@ -0,0 +1,35 @@
/*
Copyright (c) Microsoft Corporation. All rights reserved.
Licensed under the MIT License.
*/
#include <stdio.h>
#include "paws_db_info.h"
#define MAX_PAWS_DB_NAME (100)
static char g_paws_db[MAX_PAWS_DB_NAME] = "\0";
//#######################################################################################
bool set_paws_db_location(char* db)
{
if (!db)
return false;
int slen = snprintf(g_paws_db, MAX_PAWS_DB_NAME, "%s", db);
if ((slen <= 0) || (slen >= MAX_PAWS_DB_NAME))
return false;
return true;
}
//#######################################################################################
char* get_paws_db_location(void)
{
return &g_paws_db[0];
}

View File

@@ -0,0 +1,17 @@
/*
Copyright (c) Microsoft Corporation. All rights reserved.
Licensed under the MIT License.
*/
#include <stdint.h>
#include <stdbool.h>
#ifndef PAWS_DB_INFO_H_
#define PAWS_DB_INFO_H_
extern bool set_paws_db_location(char* db);
extern char* get_paws_db_location(void);
#endif // PAWS_DB_INFO_H_

View File

@@ -0,0 +1,17 @@
/*
Copyright (c) Microsoft Corporation. All rights reserved.
Licensed under the MIT License.
*/
#ifndef PAWS_DEVICE_SPECIFIC_H_
#define PAWS_DEVICE_SPECIFIC_H_
#include <stdbool.h>
extern void system_reboot(void);
extern bool reboot_device_on_admin_disable(void);
#endif // PAWS_DEVICE_SPECIFIC_H_

View File

@@ -0,0 +1,122 @@
/*
Copyright (c) Microsoft Corporation. All rights reserved.
Licensed under the MIT License.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/stat.h>
#include <time.h>
#include "paws_globals.h"
#include "paws_common.h"
#include "paws_dal_settings.h"
#include "paws_dal_devices.h"
// global vars are denoted by a leading 'g'
device_name_t gDeviceName = { 0 };
void* gPawsAppLogger = NULL;
logger_cfg_t gPawsAppLoggerCfg = { 0 };
void* gPawsCloudLogger = NULL;
static cloud_logger_cfg_t gPawsCloudLoggerCfg = { 0, { 0 }, { 0 }, 0, 0 };
paws_reg_domain_e g_paws_reg_domain = PAWS_REGDOMAIN_ETSI;
//#######################################################################################
void get_gPawsLoggerSettings(void)
{
paws_settings_t settings;
if (!(paws_read_settings(&settings)))
{
fprintf(stderr,"Unable to read settings");
return;
}
set_gPawsAppLoggerInfo(&settings.loginfo.app_log);
set_gPawsCloudLoggerInfo(&settings.loginfo.cloud_log);
}
//#######################################################################################
bool set_gPawsAppLoggerInfo(logger_cfg_t* cfg)
{
if (!cfg)
{
return false;
}
if ((!gPawsAppLogger) || (memcmp(&gPawsAppLoggerCfg, cfg, sizeof(logger_cfg_t)) != 0)) // if not already created, or config has changed
{
// copy the new config
memcpy(&gPawsAppLoggerCfg, cfg, sizeof(logger_cfg_t));
// if already created free old one
if (gPawsAppLogger)
logger_free(&gPawsAppLogger);
// if there is a filename configured
if (strlen(gPawsAppLoggerCfg.logname))
{
if (!(gPawsAppLogger = logger_create(cfg)))
return false;
}
}
return true;
}
//#######################################################################################
bool set_gPawsCloudLoggerInfo(cloud_logger_cfg_t* cfg)
{
if ((!cfg))
{
return false;
}
if ((!gPawsCloudLogger) || (memcmp(&gPawsCloudLoggerCfg, cfg, sizeof(cloud_logger_cfg_t)) != 0)) // if not already created, or config has changed
{
// copy the new config
memcpy(&gPawsCloudLoggerCfg, cfg, sizeof(cloud_logger_cfg_t));
// if already created free old one
if (gPawsCloudLogger)
cloud_logger_free(&gPawsCloudLogger);
// if there is an IP configured
if (strlen(gPawsCloudLoggerCfg.cloud_addr))
{
if (!(gPawsCloudLogger = cloud_logger_create(cfg)))
return false;
}
}
return true;
}
//#######################################################################################
extern void populate_gDeviceName(void)
{
if ((!(paws_get_device_name(gDeviceName))) || (strlen(gDeviceName) < 1))
{
char log[50];
sprintf(log, "%s", "Unable to read DeviceId");
logger_log(gPawsAppLogger, log, LOG_ERROR, "Init", true, true, __FILENAME__, __LINE__, __func__, gPawsCloudLogger, gDeviceName, PAWS_LOG_TYPE);
}
}
//#######################################################################################
void PawsGlobalsFree(void)
{
if (gPawsAppLogger)
logger_free(&gPawsAppLogger);
if (gPawsCloudLogger)
cloud_logger_free(&gPawsCloudLogger);
}

View File

@@ -0,0 +1,37 @@
/*
Copyright (c) Microsoft Corporation. All rights reserved.
Licensed under the MIT License.
*/
#ifndef PAWS_GLOBALS_H_
#define PAWS_GLOBALS_H_
#include "utils/types.h"
#include "logger/logger.h"
#include "logger/cloud_logger.h"
typedef enum {
PAWS_REGDOMAIN_GENERIC=0, // generic PAWS rfc 7545
PAWS_REGDOMAIN_ETSI // ETSI 301 598
} paws_reg_domain_e;
// global vars
extern device_name_t gDeviceName;
extern logger_cfg_t gPawsAppLoggerCfg;
extern void* gPawsAppLogger;
extern void* gPawsCloudLogger;
extern paws_reg_domain_e g_paws_reg_domain;
// prototypes
extern void get_gPawsLoggerSettings(void);
extern bool set_gPawsAppLoggerInfo(logger_cfg_t* cfg);
extern bool set_gPawsCloudLoggerInfo(cloud_logger_cfg_t* cfg);
extern void populate_gDeviceName(void);
extern void PawsGlobalsFree(void);
#endif

View File

@@ -0,0 +1,558 @@
/*
Copyright (c) Microsoft Corporation. All rights reserved.
Licensed under the MIT License.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <time.h>
#include "json-parser/json.h"
#include "json-parser/json_utils.h"
#include "utils/utils.h"
#include "paws_utils.h"
#include "paws_master_sm.h"
#include "paws_sm.h"
#include "paws_common.h"
#include "paws_combiner_sm_types.h"
#include "paws_messages.h"
#include "paws_dal_types.h"
// ##################### Function prototypes
// definition of all static class functions called from STL
// ---- called privately
PAWS_SM_FUNC_PROTO(Init_states);
PAWS_SM_FUNC_PROTO(Send_Init_Req);
PAWS_SM_FUNC_PROTO(Send_DeviceRegistration);
PAWS_SM_FUNC_PROTO(checkAvailableSpectrumDl);
PAWS_SM_FUNC_PROTO(Send_AvailableSpectrumReq);
PAWS_SM_FUNC_PROTO(Send_Spectrum_Use_Notify);
PAWS_SM_FUNC_PROTO(combiner_setDefaultInfo);
PAWS_SM_FUNC_PROTO(raiseRegistrationComplete);
PAWS_SM_FUNC_PROTO(combiner_DlNotificationSuccess);
PAWS_SM_FUNC_PROTO(combiner_DlSpectrumAvailable);
PAWS_SM_FUNC_PROTO(combiner_DlSpectrumNotAvailable);
// definition of static class functions which are not called directly by STL
static void Process_Init_Resp(void* sm_, json_value* resp);
static bool init_vars(void* sm_, paws_device_info_t* master_info, paws_gps_location_t* gps, float min_dbm_100k, uint16_t db_retry_secs, uint32_t max_polling_quick_secs);
static bool Init(void* sm_, State* stl, paws_device_info_t* master_info, paws_gps_location_t* gps, float min_dbm_100k, uint16_t db_retry_secs,
logger_cfg_t* msg_log_cfg, uint32_t max_polling_quick_secs, sm_state_info_t* sm_state_info);
// public funcs
static int run_tick(void* sm_);
static void paws_master_private_data_free(paws_master_sm_t* sm_, paws_master_private_data_t* data);
// #############################################################################################################################
// #############################################################################################################################
// ### STL definition
#define PAWSF(fnc) \
static void _##fnc(void* sm) \
{\
LOCAL_FUNC((paws_master_sm_t*)sm, fnc)(sm); \
}
PAWSF(Start_Retry_Timer)
PAWSF(Stop_Retry_Timer)
PAWSF(Start_maxPolling_Timer)
PAWSF(Start_SpectrumPending_Timer)
PAWSF(Stop_SpectrumPending_Timer)
PAWSF(Start_SpectrumExpiry_Timer)
PAWSF(Stop_SpectrumExpiry_Timer)
PAWSF(combiner_selectDB)
PAWSF(combiner_DBerror)
PAWSF(set_spectrum_InUse)
PAWSF(check_spectrum_InUse)
PAWSF(clear_spectrum_InUse)
PAWSF(activatePendingSpectrum)
PAWSF(ActivateSpectrumRuleset)
PAWSF(check_Notify_Required)
#define QUO SM_STATE_NO_CHANGE
// ######## STL states
#define FOREACH_STATE(STATE) \
STATE(INIT) \
STATE(DB_SELECT) \
STATE(PAWS_INIT) \
STATE(DEVICE_REG) \
STATE(REQUEST_NEW_SPECTRUM) \
STATE(SELECTING_NEW_SPECTRUM) \
STATE(SELECTING_NEXT_SPECTRUM) \
STATE(SPECTRUM_PENDING) \
STATE(SPECTRUM_AVAILABLE) \
STATE(SPECTRUM_NOTIFICATION) \
STATE(SPECTRUM_ACTIVE) \
STATE(NO_SPECTRUM_AVAILABLE) \
STATE(MASTER_STATE_END_MARKER)
// ######## STL events. Note also there are common events also defined in paws_sm.h
#define FOREACH_M_EV(EV) \
EV(Init_Resp_Received) \
EV(Device_reg_Resp_Received) \
EV(MASTER_EV_END_MARKER)
#define GEN_STATE_ENUM(ENUM) ENUM,
#define GEN_STATE_STR(STRING) #STRING,
enum master_state_e {
mDummyState = SM_STATE_START_OF_USER_IDS,
FOREACH_STATE(GEN_STATE_ENUM)
};
static const char *master_state_str[] = {
"dummy",
FOREACH_STATE(GEN_STATE_STR)
};
#define GEN_M_EV_ENUM(ENUM) ev_##ENUM,
#define GEN_M_EV_STR(STRING) #STRING,
enum master_event_e {
ev_mDummy = ev_PAWS_SM_END_EV_MARKER,
FOREACH_M_EV(GEN_M_EV_ENUM)
};
const char *master_ev_str[] = {
"dummy",
FOREACH_M_EV(GEN_M_EV_STR)
};
//#######################################################################################
// STL debug functions
static const char* state_id_2_str(void* sm_, int id)
{
UNUSED_PARAM(sm_);
if ((id > mDummyState) && (id < MASTER_STATE_END_MARKER))
{
return master_state_str[(id - mDummyState)];
}
// otherwise its unknown
return "Unknown";
}
static const char* event_id_2_str(void* sm_, int id)
{
paws_master_sm_t* sm = (paws_master_sm_t*)sm_;
if ((id > ev_mDummy) && (id < ev_MASTER_EV_END_MARKER))
{
return master_ev_str[(id - ev_mDummy)];
}
// otherwise call paws_sm
return (PAWS_SM_FUNC(sm, event_id_2_str)(sm_, id));
}
//################################################################################################################################################################################################
/* State-wide State-wide Event specific */
/* State 'pre' funcs 'post' funcs Event Next state 'post' funcs */
static State state_transition_table[] = {
{ INIT , { Init_states }, { NULL }, { { ev_Start, DB_SELECT, { _combiner_selectDB } } } },
{ DB_SELECT , { _Start_Retry_Timer}, {_Stop_Retry_Timer }, { { ev_Retry_Timeout, QUO, { _combiner_selectDB,
_Start_Retry_Timer } },
{ ev_DB_Found, PAWS_INIT, { Send_Init_Req } },
{ ev_DB_Updated, PAWS_INIT, { Send_Init_Req } },
{ ev_DB_NotFound, QUO, { _Start_Retry_Timer } } } },
{ PAWS_INIT , { NULL} , { NULL }, { { ev_DB_Error, DB_SELECT, { _combiner_DBerror,
combiner_DlSpectrumNotAvailable } },
{ ev_DB_Response_Failure, DB_SELECT, { _combiner_DBerror,
combiner_DlSpectrumNotAvailable } },
{ ev_Init_Resp_Received, DEVICE_REG, { _Start_maxPolling_Timer,
combiner_setDefaultInfo,
Send_DeviceRegistration } } } },
{ DEVICE_REG , { NULL } , { NULL }, { { ev_DB_Error, DB_SELECT, { _combiner_DBerror,
combiner_DlSpectrumNotAvailable } },
{ ev_DB_Response_Failure, DB_SELECT, { _combiner_DBerror,
combiner_DlSpectrumNotAvailable } },
{ ev_Device_reg_Resp_Received, REQUEST_NEW_SPECTRUM, { raiseRegistrationComplete } } } },
{ REQUEST_NEW_SPECTRUM , { _combiner_selectDB } , { NULL }, { { ev_DB_Error, QUO, { _combiner_DBerror,
_check_spectrum_InUse } },
{ ev_DB_Response_Failure, DB_SELECT, { _combiner_DBerror,
_check_spectrum_InUse } },
{ ev_DB_NotFound, QUO, { _check_spectrum_InUse } },
{ ev_DB_Found, QUO, { Send_AvailableSpectrumReq } },
{ ev_SpectrumActive, SPECTRUM_ACTIVE, { NULL } },
{ ev_SpectrumNotActive, DB_SELECT, { combiner_DlSpectrumNotAvailable } },
{ ev_maxPolling_Timeout, QUO, { _combiner_selectDB } },
{ ev_maxPollingQuick_Timeout, QUO, { _combiner_selectDB } },
{ ev_Available_Spectrum_Resp, SELECTING_NEW_SPECTRUM, { checkAvailableSpectrumDl } } } },
{ SELECTING_NEW_SPECTRUM , {NULL } , { NULL }, { { ev_GPS_location_changed, REQUEST_NEW_SPECTRUM, { _clear_spectrum_InUse } },
{ ev_maxPolling_Timeout, REQUEST_NEW_SPECTRUM, { NULL } },
{ ev_maxPollingQuick_Timeout, REQUEST_NEW_SPECTRUM, { NULL } },
{ ev_SpectrumAvailable, SPECTRUM_AVAILABLE, { NULL } },
{ ev_SpectrumPending, SPECTRUM_PENDING, { NULL } },
{ ev_SpectrumNotAvailable, NO_SPECTRUM_AVAILABLE, { NULL } } } },
{ SELECTING_NEXT_SPECTRUM , { _clear_spectrum_InUse,
checkAvailableSpectrumDl }, { NULL }, { { ev_GPS_location_changed, REQUEST_NEW_SPECTRUM, { _clear_spectrum_InUse } },
{ ev_maxPolling_Timeout, REQUEST_NEW_SPECTRUM, { NULL } },
{ ev_maxPollingQuick_Timeout, REQUEST_NEW_SPECTRUM, { NULL } },
{ ev_SpectrumAvailable, SPECTRUM_AVAILABLE, { NULL } },
{ ev_SpectrumPending, SPECTRUM_PENDING, { NULL } },
{ ev_SpectrumNotAvailable, REQUEST_NEW_SPECTRUM, { NULL } } } },
{ SPECTRUM_PENDING, { _Start_SpectrumPending_Timer,
_check_spectrum_InUse}, {_Stop_SpectrumPending_Timer }, { { ev_GPS_location_changed, REQUEST_NEW_SPECTRUM, { _clear_spectrum_InUse } },
{ ev_maxPolling_Timeout, REQUEST_NEW_SPECTRUM, { NULL } },
{ ev_maxPollingQuick_Timeout, REQUEST_NEW_SPECTRUM, { NULL } },
{ ev_SpectrumExpiry_Timeout, QUO, { _clear_spectrum_InUse,
combiner_DlSpectrumNotAvailable } },
{ ev_SpectrumActive, QUO, { NULL } },
{ ev_SpectrumNotActive, QUO, { combiner_DlSpectrumNotAvailable } },
{ ev_SpectrumPending_Timeout, SPECTRUM_AVAILABLE, { _activatePendingSpectrum } } } },
{ SPECTRUM_AVAILABLE, { _ActivateSpectrumRuleset,
_Start_SpectrumExpiry_Timer,
combiner_DlSpectrumAvailable }, { NULL }, { { ev_GPS_location_changed, REQUEST_NEW_SPECTRUM, { _clear_spectrum_InUse } },
{ ev_maxPolling_Timeout, REQUEST_NEW_SPECTRUM, { NULL } },
{ ev_maxPollingQuick_Timeout, REQUEST_NEW_SPECTRUM, { NULL } },
{ ev_SpectrumExpiry_Timeout, SELECTING_NEXT_SPECTRUM, { NULL } },
{ ev_DlUlSpectrumAvailable, SPECTRUM_NOTIFICATION, { NULL } } } },
{ SPECTRUM_NOTIFICATION , { _combiner_selectDB }, { NULL }, { { ev_DB_Error, QUO, { _check_spectrum_InUse,
_combiner_DBerror } },
{ ev_DB_Response_Failure, QUO, { _check_spectrum_InUse,
_combiner_DBerror } },
{ ev_DB_NotFound, QUO, { _check_spectrum_InUse } },
{ ev_DB_Found, QUO, { _check_Notify_Required } },
{ ev_SpectrumActive, SPECTRUM_ACTIVE, { NULL } },
{ ev_SpectrumNotActive, DB_SELECT, { combiner_DlSpectrumNotAvailable } },
{ ev_GPS_location_changed, REQUEST_NEW_SPECTRUM, { _clear_spectrum_InUse } },
{ ev_maxPolling_Timeout, REQUEST_NEW_SPECTRUM, { NULL } },
{ ev_maxPollingQuick_Timeout, REQUEST_NEW_SPECTRUM, { NULL } },
{ ev_SpectrumExpiry_Timeout, SELECTING_NEXT_SPECTRUM, { NULL } },
{ ev_Notification_Required, QUO, { Send_Spectrum_Use_Notify } },
{ ev_Notification_Not_Required, SPECTRUM_ACTIVE, { _set_spectrum_InUse,
combiner_DlNotificationSuccess } },
{ ev_Notification_Success, SPECTRUM_ACTIVE, { _set_spectrum_InUse,
combiner_DlNotificationSuccess } },
{ ev_Notification_Failure, QUO, { _check_spectrum_InUse } } } },
{ SPECTRUM_ACTIVE , { NULL }, { NULL }, { { ev_GPS_location_changed, REQUEST_NEW_SPECTRUM, { _clear_spectrum_InUse } },
{ ev_maxPolling_Timeout, REQUEST_NEW_SPECTRUM, { NULL } },
{ ev_maxPollingQuick_Timeout, REQUEST_NEW_SPECTRUM, { NULL } },
{ ev_SpectrumExpiry_Timeout, SELECTING_NEXT_SPECTRUM, { NULL } } } },
{ NO_SPECTRUM_AVAILABLE , { _Stop_SpectrumExpiry_Timer,
combiner_DlSpectrumNotAvailable}, { NULL }, { { ev_maxPolling_Timeout, REQUEST_NEW_SPECTRUM, { NULL } },
{ ev_maxPollingQuick_Timeout, REQUEST_NEW_SPECTRUM, { NULL } },
{ ev_GPS_location_changed, REQUEST_NEW_SPECTRUM, { _clear_spectrum_InUse } } } }
};
//#######################################################################################
static void Init_states(void* sm_)
{
paws_master_sm_t* sm = (paws_master_sm_t*)sm_;
paws_master_private_data_free(sm, &(PRIVATE_DATA(sm)));
// direct call
PAWS_SM_FUNC(sm, Init_states)(sm);
}
//#######################################################################################
static void Send_Init_Req(void* sm_)
{
FUNC_DBG(sm_);
paws_master_sm_t* sm = (paws_master_sm_t*)sm_;
LOG_PRINT(sm_, LOG_NOTICE, "----> INIT-REQ MASTER");
json_value* resp = post_Init_Request(sm_, &(PAWS_SM_DATA((paws_sm_t*)sm_)->master_info), &(PAWS_SM_DATA((paws_sm_t*)sm_)->gps),
&(PAWS_SM_DATA((paws_sm_t*)sm)->selected_db.db_url));
Process_Init_Resp(sm_, resp);
json_value_free(resp);
}
//#######################################################################################
static void Send_DeviceRegistration(void* sm_)
{
FUNC_DBG(sm_);
LOCAL_FUNC(sm_, raise_)(sm_, (int)ev_Device_reg_Resp_Received);
}
//#######################################################################################
static void checkAvailableSpectrumDl(void* sm_)
{
FUNC_DBG(sm_);
LOCAL_FUNC(sm_, checkAvailableSpectrum)(sm_);
}
//#######################################################################################
static void Send_AvailableSpectrumReq(void* sm_)
{
FUNC_DBG(sm_);
LOG_PRINT(sm_, LOG_NOTICE, "----> AVAIL-SPEC-REQ MASTER");
json_value* resp = post_Avail_Spectrum_Request(sm_, &(PAWS_SM_DATA((paws_sm_t*)sm_)->master_info), &(PAWS_SM_DATA((paws_sm_t*)sm_)->gps),
&(PAWS_SM_DATA((paws_sm_t*)sm_)->selected_db.db_url));
// make a note of reception time. This is used to compare time phase with TVWSDB server
LOCAL_FUNC(sm_, Process_Available_Spectrum_Resp)(sm_, resp, LTE_DL, time(NULL));
json_value_free(resp);
}
//#######################################################################################
static void Send_Spectrum_Use_Notify(void* sm_)
{
FUNC_DBG(sm_);
LOG_PRINT(sm_, LOG_NOTICE, "----> NOTIFY-REQ MASTER");
json_value* resp = post_Notify_Request(sm_, &(PAWS_SM_DATA((paws_sm_t*)sm_)->master_info), &(PAWS_SM_DATA((paws_sm_t*)sm_)->gps),
&(PAWS_SM_DATA((paws_sm_t*)sm_)->selected_db.db_url), PAWS_SM_DATA((paws_sm_t*)sm_)->selected_spectrum, 13);
LOCAL_FUNC(sm_, Process_Notify_Use_Resp)(sm_, resp);
json_value_free(resp);
}
//#######################################################################################
static void combiner_setDefaultInfo(void* sm_)
{
FUNC_DBG(sm_);
COMBINER_PUBLIC_FUNC(CREATOR_SM(sm_), setDefaultInfo)(CREATOR_SM(sm_), PAWS_SM_DATA(sm_)->default_max_location_change, PAWS_SM_DATA(sm_)->default_max_polling_secs);
}
//#######################################################################################
static void raiseRegistrationComplete(void* sm_)
{
FUNC_DBG(sm_);
}
//#######################################################################################
static void combiner_DlNotificationSuccess(void* sm_)
{
FUNC_DBG(sm_);
COMBINER_PUBLIC_FUNC(CREATOR_SM(sm_), DlNotificationSuccess)(CREATOR_SM(sm_));
}
//#######################################################################################
static void combiner_DlSpectrumAvailable(void* sm_)
{
FUNC_DBG(sm_);
COMBINER_PUBLIC_FUNC(CREATOR_SM(sm_), DlSpectrumAvailable)(CREATOR_SM(sm_));
}
//#######################################################################################
static void combiner_DlSpectrumNotAvailable(void* sm_)
{
FUNC_DBG(sm_);
COMBINER_PUBLIC_FUNC(CREATOR_SM(sm_), DlSpectrumNotAvailable)(CREATOR_SM(sm_));
}
//#######################################################################################
static void Process_Init_Resp(void* sm_, json_value* resp)
{
FUNC_DBG(sm_);
paws_master_sm_t* sm = (paws_master_sm_t*)sm_;
if (LOCAL_FUNC(sm, Check_HTTP_Result)(sm_, resp, true))
{
if (LOCAL_FUNC(sm, Check_Valid_Resp)(sm_, resp, true))
{
// parse the ruleset info
json_value* rulesetInfos = NULL;
if ((rulesetInfos = json_get(resp, "result/rulesetInfos")))
{
// walk list of rulesetInfo until we have processed a maxlocationChange param
if (rulesetInfos->type == json_array)
{
int64_t max_polling_secs = 0;
double max_location_change = 0;
for (uint32_t i=0; i < (rulesetInfos->u.array.length && ((max_location_change==0) || (max_polling_secs == 0))) ; i++)
{
json_value* ruleset_info = rulesetInfos->u.array.values[i];
if (ruleset_info->type == json_object)
{
if ((json_get_int(ruleset_info, "maxPollingSecs", &max_polling_secs)))
{
PAWS_SM_DATA(sm)->default_max_polling_secs = max_polling_secs;
}
if ((json_get_double(ruleset_info, "maxLocationChange", (double*)&max_location_change)))
{
PAWS_SM_DATA(sm)->default_max_location_change = (float)max_location_change;
}
}
}
}
}
LOG_PRINT(sm_, LOG_NOTICE, "<---- INIT-RESP MASTER");
LOCAL_FUNC(sm, raise_)(sm_, (int)ev_Init_Resp_Received);
}
}
}
//#######################################################################################
static bool init_vars(void* sm_, paws_device_info_t* master_info, paws_gps_location_t* gps, float min_dbm_100k, uint16_t db_retry_secs, uint32_t max_polling_quick_secs)
{
FUNC_DBG(sm_);
paws_master_sm_t* sm = (paws_master_sm_t*)sm_;
if (!(PAWS_SM_FUNC(sm, Init)(sm_, min_dbm_100k, db_retry_secs, max_polling_quick_secs)))
{
return false;
}
// store gps
LOCAL_FUNC(sm, set_gps)(sm, gps);
// store fap info
LOCAL_FUNC(sm, set_master_info)(sm, master_info);
return true;
}
//#######################################################################################
static bool Init(void* sm_, State* stl, paws_device_info_t* master_info, paws_gps_location_t* gps, float min_dbm_100k, uint16_t db_retry_secs,
logger_cfg_t* msg_log_cfg, uint32_t max_polling_quick_secs, sm_state_info_t* sm_state_info)
{
FUNC_DBG(sm_);
paws_master_sm_t* sm = (paws_master_sm_t*)sm_;
// determine initial state and whether we should run the "pre" functions
int initial_state = (sm_state_info) ? sm_state_info->stl_current_state : INIT;
bool run_pre = (sm_state_info == NULL);
LOG_PRINT(sm_, LOG_INFO, "Initialising STL. state = %s", LOCAL_FUNC(sm_, state_id_2_str)(sm_, initial_state));
// generic Init
if (!(LOCAL_FUNC(sm, stl_init)(sm_, stl, initial_state, run_pre)))
{
return false;
}
// initialise variables
if (!(init_vars(sm, master_info, gps, min_dbm_100k, db_retry_secs, max_polling_quick_secs)))
{
return false;
}
// create logger
LOCAL_FUNC(sm, set_msgLogInfo)(sm_, msg_log_cfg);
// process pre-boot state
if (sm_state_info)
{
LOCAL_FUNC(sm, process_state_attributes)(sm_, sm_state_info);
LOCAL_FUNC(sm, process_state_timers)(sm_, sm_state_info->timer_info);
}
return true;
}
//#######################################################################################
static int run_tick(void* sm_)
{
// FUNC_DBG(sm_);
paws_master_sm_t* sm = (paws_master_sm_t*)sm_;
// run the timer
LOCAL_FUNC(sm, process_next_timer_tick)(sm_);
// process any triggered events
return LOCAL_FUNC(sm, process_events)(sm_);
}
//#######################################################################################
paws_master_sm_t* paws_master_sm_create(void* creator, const char* sm_name, paws_device_info_t* master_info, paws_gps_location_t* gps, float min_dbm_100k, uint16_t db_retry_secs,
logger_cfg_t* msg_log_cfg, uint32_t max_polling_quick_secs, sm_state_info_t* sm_state_info)
{
// FUNC_DBG(sm_);
paws_master_sm_t* paws_master_sm = NULL;
if (!(paws_master_sm = malloc(sizeof(paws_master_sm_t))))
{
goto error_hdl;
}
memset(paws_master_sm, 0, sizeof(paws_master_sm_t));
// "inherit" the paws_sm
if (!(paws_master_sm->paws_sm = paws_sm_create(creator, &paws_master_sm->paws_sm_func_store, sm_name)))
{
goto error_hdl;
}
LOG_PRINT(creator, LOG_NOTICE, "Creating MASTER SM");
// copy the header from the paws_sm
memcpy(&paws_master_sm->paws_sm_hdr, &paws_master_sm->paws_sm->paws_sm_hdr, sizeof(paws_sm_header_t));
// ---- called by paws_sm
POPULATE_PAWS_SM_FUNC(paws_master_sm, Init_states);
POPULATE_PAWS_SM_FUNC(paws_master_sm, state_id_2_str);
POPULATE_PAWS_SM_FUNC(paws_master_sm, event_id_2_str);
// ---- called publicly
POPULATE_PUBLIC_FUNC(paws_master_sm, run_tick);
// Initialise
if (!(Init(paws_master_sm, state_transition_table, master_info, gps, min_dbm_100k, db_retry_secs, msg_log_cfg, max_polling_quick_secs, sm_state_info)))
{
goto error_hdl;
}
return paws_master_sm;
error_hdl:
paws_master_sm_free(&paws_master_sm);
return NULL;
}
static void paws_master_private_data_free(paws_master_sm_t* sm_, paws_master_private_data_t* data)
{
FUNC_DBG(sm_);
if (data)
{
// nothing to free
}
}
void paws_master_sm_free(paws_master_sm_t** paws_master_sm)
{
FUNC_DBG(*paws_master_sm);
// check that state machine exists
if ((paws_master_sm) && (*paws_master_sm))
{
LOG_PRINT(*paws_master_sm, LOG_NOTICE, "Deleting MASTER SM");
// free the private data attributes
paws_master_private_data_free(*paws_master_sm, &(PRIVATE_DATA(*paws_master_sm)));
// free the paws_sm
// This also free the paws_sm data
paws_sm_free(&(**paws_master_sm).paws_sm);
// free the struct
free_and_null((void**)paws_master_sm);
}
}
//#######################################################################################

View File

@@ -0,0 +1,15 @@
/*
Copyright (c) Microsoft Corporation. All rights reserved.
Licensed under the MIT License.
*/
#ifndef PAWS_SM_MASTER_H_
#define PAWS_SM_MASTER_H_
#include "paws_master_sm_types.h"
extern paws_master_sm_t* paws_master_sm_create(void* creator, const char* sm_name, paws_device_info_t* master_info, paws_gps_location_t* gps, float min_dbm_100k, uint16_t db_retry_secs,
logger_cfg_t* msg_log_cfg, uint32_t max_polling_quick_secs, sm_state_info_t* sm_state_info);
extern void paws_master_sm_free(paws_master_sm_t** paws_master_sm);
#endif // #define PAWS_SM_MASTER_H_

View File

@@ -0,0 +1,30 @@
/*
Copyright (c) Microsoft Corporation. All rights reserved.
Licensed under the MIT License.
*/
#ifndef PAWS_MASTER_SM_TYPES_H_
#define PAWS_MASTER_SM_TYPES_H_
#include "paws_sm_types.h"
typedef struct {
int(*run_tick)(void* sm_);
} paws_master_public_funcs_t;
typedef struct {
int dummy; // unused
} paws_master_private_data_t;
typedef struct {
paws_sm_header_t paws_sm_hdr; // THIS MUST BE FIRST IN ANY SM WHICH HAS A PAWS_SM.
paws_sm_funcs_t paws_sm_func_store;
paws_master_private_data_t private_data_store;
paws_master_public_funcs_t public_func_store;
paws_sm_t* paws_sm;
} paws_master_sm_t;
#endif // #define PAWS_MASTER_SM_TYPES_H_

View File

@@ -0,0 +1,103 @@
/*
Copyright (c) Microsoft Corporation. All rights reserved.
Licensed under the MIT License.
*/
#include <string.h>
#include "paws_message_templates.h"
#include "paws_utils.h"
#include "paws_common.h"
// #########################################################################################
// ### json templates
static char init_req_template[] = "{ \"jsonrpc\": \"2.0\", \"method\": \"spectrum.paws.init\", \"params\": { \"type\": \"INIT_REQ\", \"version\": \"1.0\", \"deviceDesc\": { \"serialNumber\": \"M01D201621592159\", \"manufacturerId\": \"IPAccess\", \"modelId\": \"Radio\", \"rulesetIds\": [ \"ETSI-EN-301-598-1.1.1\" ], \"etsiEnDeviceType\": \"A\", \"etsiEnDeviceCategory\": \"master\", \"etsiEnDeviceEmissionsClass\": 3, \"etsiEnTechnologyId\": \"AngularJS\" }, \"location\": { \"point\": { \"center\": { \"latitude\": 51.507611, \"longitude\": -0.111162 }, \"semiMajorAxis\": 0, \"semiMinorAxis\": 0, \"orientation\": 0 } } }, \"id\": 0}";
static char available_spectrum_req_template[] = "{ \"jsonrpc\": \"2.0\", \"method\": \"spectrum.paws.getSpectrum\", \"params\": { \"type\": \"AVAIL_SPECTRUM_REQ\", \"version\": \"1.0\", \"deviceDesc\": { \"serialNumber\": \"M01D201621592159\", \"manufacturerId\": \"IPAccess\", \"modelId\": \"Radio\", \"rulesetIds\": [ \"ETSI-EN-301-598-1.1.1\" ], \"etsiEnDeviceType\": \"A\", \"etsiEnDeviceCategory\": \"master\", \"etsiEnDeviceEmissionsClass\": 3, \"etsiEnTechnologyId\": \"AngularJS\" }, \"location\": { \"point\": { \"center\": { \"latitude\": 51.507611, \"longitude\": -0.111162 }, \"semiMajorAxis\": 0, \"semiMinorAxis\": 0, \"orientation\": 0 } }, \"antenna\": { \"height\": 15, \"heightType\": \"AGL\", \"heightUncertainty\": 0 } }, \"id\": 0}";
static char slave_gop_available_spectrum_req_template[] = "{ \"jsonrpc\": \"2.0\", \"method\": \"spectrum.paws.getSpectrum\", \"params\": { \"type\": \"AVAIL_SPECTRUM_REQ\", \"version\": \"1.0\", \"deviceDesc\": { \"serialNumber\": \"M01D201621592159\", \"manufacturerId\": \"IPAccess\", \"modelId\": \"Radio\", \"rulesetIds\": [ \"ETSI-EN-301-598-1.1.1\" ], \"etsiEnDeviceType\": \"A\", \"etsiEnDeviceCategory\": \"master\", \"etsiEnDeviceEmissionsClass\": \"4\", \"etsiEnTechnologyId\": \"AngularJS\" }, \"location\": { \"point\": { \"center\": { \"latitude\": 51.507611, \"longitude\": -0.111162 }, \"semiMajorAxis\": 0, \"semiMinorAxis\": 0, \"orientation\": 0 } }, \"requestType\": \"Generic Slave\" }, \"id\": 0}";
static char slave_sop_available_spectrum_req_template[] = "{ \"jsonrpc\": \"2.0\", \"method\": \"spectrum.paws.getSpectrum\", \"params\": { \"type\": \"AVAIL_SPECTRUM_REQ\", \"version\": \"1.0\", \"deviceDesc\": { \"serialNumber\": \"S01D201621592159\", \"manufacturerId\": \"IPAccess\", \"modelId\": \"Radio\", \"rulesetIds\": [ \"ETSI-EN-301-598-1.1.1\" ], \"etsiEnDeviceType\": \"B\", \"etsiEnDeviceCategory\": \"slave\", \"etsiEnDeviceEmissionsClass\": 5, \"etsiEnTechnologyId\": \"AngularJS\" }, \"location\": { \"point\": { \"center\": { \"latitude\": 51.507611, \"longitude\": -0.111162 }, \"semiMajorAxis\": 0, \"semiMinorAxis\": 0, \"orientation\": 0 } }, \"antenna\": { \"height\": 15, \"heightType\": \"AGL\", \"heightUncertainty\": 0 }, \"masterDeviceDesc\": { \"serialNumber\": \"M01D201621592159\", \"manufacturerId\": \"IPAccess\", \"modelId\": \"Radio\", \"rulesetIds\": [ \"ETSI-EN-301-598-1.1.1\" ], \"etsiEnDeviceType\": \"A\", \"etsiEnDeviceCategory\": \"master\", \"etsiEnDeviceEmissionsClass\": 3, \"etsiEnTechnologyId\": \"AngularJS\" }, \"masterDeviceLocation\": { \"point\": { \"center\": { \"latitude\": 51.507611, \"longitude\": -0.111162 }, \"semiMajorAxis\": 0, \"semiMinorAxis\": 0, \"orientation\": 0 } } }, \"id\": 0}";
static char spectrum_use_notify_req_template[] = "{ \"jsonrpc\": \"2.0\", \"method\": \"spectrum.paws.notifySpectrumUse\", \"id\": 0, \"params\": { \"type\": \"SPECTRUM_USE_NOTIFY\", \"version\": \"1.0\", \"deviceDesc\": { \"serialNumber\": \"M01D201621592159\", \"manufacturerId\": \"IPAccess\", \"modelId\": \"Radio\", \"rulesetIds\": [ \"ETSI-EN-301-598-1.1.1\" ], \"etsiEnDeviceType\": \"A\", \"etsiEnDeviceCategory\": \"master\", \"etsiEnDeviceEmissionsClass\": 3, \"etsiEnTechnologyId\": \"AngularJS\" }, \"location\": { \"point\": { \"center\": { \"latitude\": 51.507611, \"longitude\": -0.111162 }, \"semiMajorAxis\": 0, \"semiMinorAxis\": 0, \"orientation\": 0 } }, \"spectra\": [] } }";
static char gop_slave_spectrum_use_notify_req_template[] = "{ \"jsonrpc\": \"2.0\", \"method\": \"spectrum.paws.notifySpectrumUse\", \"id\": 0, \"params\": { \"type\": \"SPECTRUM_USE_NOTIFY\", \"version\": \"1.0\", \"deviceDesc\": { \"serialNumber\": \"S01D201621592159\", \"manufacturerId\": \"IPAccess\", \"modelId\": \"Radio\", \"rulesetIds\": [ \"ETSI-EN-301-598-1.1.1\" ], \"etsiEnDeviceType\": \"A\", \"etsiEnDeviceCategory\": \"slave\", \"etsiEnDeviceEmissionsClass\": 3, \"etsiEnTechnologyId\": \"AngularJS\" }, \"masterDeviceDesc\": { \"serialNumber\": \"M01D201621592159\", \"manufacturerId\": \"IPAccess\", \"modelId\": \"Radio\", \"rulesetIds\": [ \"ETSI-EN-301-598-1.1.1\" ], \"etsiEnDeviceType\": \"A\", \"etsiEnDeviceCategory\": \"master\", \"etsiEnDeviceEmissionsClass\": 3, \"etsiEnTechnologyId\": \"AngularJS\" }, \"masterDeviceLocation\": { \"point\": { \"center\": { \"latitude\": 51.507611, \"longitude\": -0.111162 }, \"semiMajorAxis\": 0, \"semiMinorAxis\": 0, \"orientation\": 0 } }, \"spectra\": [ ] } }";
static char sop_slave_spectrum_use_notify_req_template[] = "{ \"jsonrpc\": \"2.0\", \"method\": \"spectrum.paws.notifySpectrumUse\", \"id\": 0, \"params\": { \"type\": \"SPECTRUM_USE_NOTIFY\", \"version\": \"1.0\", \"deviceDesc\": { \"serialNumber\": \"S01D201621592159\", \"manufacturerId\": \"IPAccess\", \"modelId\": \"Radio\", \"rulesetIds\": [ \"ETSI-EN-301-598-1.1.1\" ], \"etsiEnDeviceType\": \"A\", \"etsiEnDeviceCategory\": \"slave\", \"etsiEnDeviceEmissionsClass\": 3, \"etsiEnTechnologyId\": \"AngularJS\" }, \"masterDeviceDesc\": { \"serialNumber\": \"M01D201621592159\", \"manufacturerId\": \"IPAccess\", \"modelId\": \"Radio\", \"rulesetIds\": [ \"ETSI-EN-301-598-1.1.1\" ], \"etsiEnDeviceType\": \"A\", \"etsiEnDeviceCategory\": \"master\", \"etsiEnDeviceEmissionsClass\": 3, \"etsiEnTechnologyId\": \"AngularJS\" }, \"location\": { \"point\": { \"center\": { \"latitude\": 51.507611, \"longitude\": -0.111162 }, \"semiMajorAxis\": 0, \"semiMinorAxis\": 0, \"orientation\": 0 } }, \"masterDeviceLocation\": { \"point\": { \"center\": { \"latitude\": 51.507611, \"longitude\": -0.111162 }, \"semiMajorAxis\": 0, \"semiMinorAxis\": 0, \"orientation\": 0 } }, \"spectra\": [ ] } }";
//#######################################################################################
static json_value* str2json(void* sm_, char* j_str)
{
json_value* jval = NULL;
if ((!j_str) || (strlen(j_str) == 0))
{
LOG_PRINT(sm_, LOG_ERROR, "Unable to parse data");
return NULL;
}
// we have the contents, now convert to json
if (!(jval = json_parse((json_char*)j_str, strlen(j_str))))
{
LOG_PRINT(sm_, LOG_ERROR, "Unable to parse data");
return NULL;
}
// success
return jval;
}
//#######################################################################################
json_value* get_init_req_template(void* sm_)
{
return str2json(sm_, init_req_template);
}
//#######################################################################################
json_value* get_available_spectrum_req_template(void* sm_)
{
return str2json(sm_, available_spectrum_req_template);
}
//#######################################################################################
json_value* get_slave_gop_available_spectrum_req_template(void* sm_)
{
return str2json(sm_, slave_gop_available_spectrum_req_template);
}
//#######################################################################################
json_value* get_slave_sop_available_spectrum_req_template(void* sm_)
{
return str2json(sm_, slave_sop_available_spectrum_req_template);
}
//#######################################################################################
json_value* get_spectrum_use_notify_req_template(void* sm_)
{
return str2json(sm_, spectrum_use_notify_req_template);
}
//#######################################################################################
json_value* get_gop_slave_spectrum_use_notify_req_template(void* sm_)
{
return str2json(sm_, gop_slave_spectrum_use_notify_req_template);
}
//#######################################################################################
json_value* get_sop_slave_spectrum_use_notify_req_template(void* sm_)
{
return str2json(sm_, sop_slave_spectrum_use_notify_req_template);
}

View File

@@ -0,0 +1,29 @@
/*
Copyright (c) Microsoft Corporation. All rights reserved.
Licensed under the MIT License.
*/
#ifndef PAWS_MESSAGE_TEMPLATES_H_
#define PAWS_MESSAGE_TEMPLATES_H_
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include "json-parser/json_utils.h"
//#######################################################################################
json_value* get_init_req_template(void* sm_);
json_value* get_available_spectrum_req_template(void* sm_);
json_value* get_slave_gop_available_spectrum_req_template(void* sm_);
json_value* get_slave_sop_available_spectrum_req_template(void* sm_);
json_value* get_spectrum_use_notify_req_template(void* sm_);
json_value* get_gop_slave_spectrum_use_notify_req_template(void* sm_);
json_value* get_sop_slave_spectrum_use_notify_req_template(void* sm_);
#endif // PAWS_MESSAGE_TEMPLATES_H_

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,48 @@
/*
Copyright (c) Microsoft Corporation. All rights reserved.
Licensed under the MIT License.
*/
#ifndef PAWS_MESSAGES_H_
#define PAWS_MESSAGES_H_
#include "gps/gps.h"
#include "json-parser/json.h"
#include "paws_types.h"
// PAWS error codes
#define PAWS_ERROR_RESERVED (-100)
#define PAWS_ERROR_VERSION (-101)
#define PAWS_ERROR_UNSUPPORTED (-102)
#define PAWS_ERROR_UNIMPLEMENTED (-103)
#define PAWS_ERROR_OUTSIDE_COVERAGE (-104)
#define PAWS_ERROR_DATABASE_CHANGE (-105)
#define PAWS_ERROR_COMPATIBILITY_MAX PAWS_ERROR_RESERVED
#define PAWS_ERROR_COMPATIBILITY_MIN PAWS_ERROR_DATABASE_CHANGE
#define PAWS_ERROR_RESERVED2 (-200)
#define PAWS_ERROR_MISSING (-201)
#define PAWS_ERROR_INVALID_VALUE (-202)
#define PAWS_ERROR_REQERROR_MAX PAWS_ERROR_RESERVED2
#define PAWS_ERROR_REQERROR_MIN PAWS_ERROR_INVALID_VALUE
#define PAWS_ERROR_RESERVED3 (-300)
#define PAWS_ERROR_UNAUTHORIZED (-301)
#define PAWS_ERROR_NOT_REGISTERED (-302)
#define PAWS_ERROR_AUTHORISATION_MAX PAWS_ERROR_RESERVED3
#define PAWS_ERROR_AUTHORISATION_MIN PAWS_ERROR_NOT_REGISTERED
#define MAX_DB_ACCESS_ATTEMPTS (5) /* how many to retry a connection before giving up */
extern json_value* post_Init_Request(void* sm_, paws_device_info_t *device_info, paws_gps_location_t* gps, paws_db_url_t* url);
extern json_value* post_Avail_Spectrum_Request(void* sm_, paws_device_info_t *device_info, paws_gps_location_t* gps, paws_db_url_t* url);
extern json_value* post_Slave_GOP_Available_Spectrum_Request(void* sm_, paws_device_info_t *device_info, paws_gps_location_t* gps, paws_db_url_t* url);
extern json_value* post_Slave_SOP_Available_Spectrum_Request(void* sm_, paws_device_info_t* master_info, paws_device_info_t* slave_device_info, paws_gps_location_t* gps, paws_db_url_t* url);
extern json_value* post_Notify_Request(void* sm_, paws_device_info_t *device_info, paws_gps_location_t* gps, paws_db_url_t* url, spec_cfg_t* cfg, uint8_t band_id);
extern json_value* post_GOP_slave_Notify_Request(void* sm_, paws_device_info_t* master_info, paws_device_info_t* slave_device_info, paws_gps_location_t* master_gps, paws_db_url_t* url, spec_cfg_t* cfg, uint8_t band_id);
extern json_value* post_SOP_slave_Notify_Request(void* sm_, paws_device_info_t* master_info, paws_device_info_t* slave_device_info, paws_gps_location_t* master_gps, paws_db_url_t* url, spec_cfg_t* cfg, uint8_t band_id);
extern void paws_messages_ssl_free(void* sm_);
#endif // PAWS_MESSAGES_H_

View File

@@ -0,0 +1,986 @@
/*
Copyright (c) Microsoft Corporation. All rights reserved.
Licensed under the MIT License.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "utils/utils.h"
#include "paws_utils.h"
#include "paws_slave_sm.h"
#include "paws_sm.h"
#include "paws_common.h"
#include "paws_combiner_sm_types.h"
#include "paws_messages.h"
// ##################### Function prototypes
// definition of all static class functions called from STL
// ---- called privately
PAWS_SM_FUNC_PROTO(checkAvailableSpectrumUl);
PAWS_SM_FUNC_PROTO(combiner_UlSpectrumAvailable);
PAWS_SM_FUNC_PROTO(combiner_UlSpectrumNotAvailable);
PAWS_SM_FUNC_PROTO(combiner_UlNotificationSuccess);
static int run_tick(void* sm_);
// GOP funcs
static void gop_Send_AvailableSpectrumReq(void* sm_);
static void gop_Send_Notifications(void* sm_, paws_slave_info_t* slave_info);
static void gop_Send_Spectrum_Use_Notify(void* sm_);
static void gop_Send_Spectrum_Use_Notify_New(void* sm_);
static bool gop_Process_Notify_Use_Resp(void* sm_, json_value* resp);
static void gop_set_slaveInfo(void* sm_, paws_slave_info_t* slave_info);
static paws_slave_info_t* gop_get_slaveInfo(void* sm_);
// SOP funcs
static void sop_Send_AvailableSpectrumReq(void* sm_);
static void sop_Send_Spectrum_Use_Notify(void* sm_);
static void sop_Send_Spectrum_Use_Notify_New(void* sm_);
static bool sop_Process_Notify_Use_Resp(void* sm_, json_value* resp);
static void sop_set_deviceInfo(void* sm_, paws_device_info_t* device_info);
static paws_device_info_t* sop_get_deviceInfo(void* sm_);
static bool sop_Init(void* sm_, State* stl, paws_device_info_t* master_info, paws_gps_location_t* gps, float default_max_location_change, uint32_t default_max_polling_secs,
paws_device_info_t *device_info, float min_dbm_100k, uint16_t db_retry_secs, logger_cfg_t* msg_log_cfg, uint32_t max_polling_quick_secs, sm_state_info_t* sm_state_info);
#define SLAVE_FUNC(sm, fnc) ((paws_slave_sm_t*)sm)->slave_hdr.funcs->fnc
#define PARENT_SLAVE_FUNC(sm, fnc) (sm)->slave_sm->local_slave_funcs.fnc
#define PARENT_SLAVE_SM_FUNC(sm, fnc) (sm)->slave_sm->local_paws_sm_funcs.fnc
#define SLAVE_SM_DATA(sm) ((paws_slave_sm_t*)sm)->slave_hdr.data
// #######################################################################################################################
// #######################################################################################################################
// #######################################################################################################################
// #######################################################################################################################
// slave_sm
// #######################################################################################################################
// #######################################################################################################################
// #######################################################################################################################
// #######################################################################################################################
#define PAWSF(fnc) \
static void _##fnc(void* sm) \
{\
LOCAL_FUNC((paws_slave_sm_t*)sm, fnc)(sm); \
}
#define SLAVEF(fnc) \
static void _##fnc(void* sm) \
{\
SLAVE_FUNC((paws_slave_sm_t*)sm, fnc)(sm); \
}
PAWSF(Clear_Spectrums)
PAWSF(Start_Retry_Timer)
PAWSF(Stop_Retry_Timer)
PAWSF(Start_maxPolling_Timer)
PAWSF(Start_SpectrumPending_Timer)
PAWSF(Stop_SpectrumPending_Timer)
PAWSF(Start_SpectrumExpiry_Timer)
PAWSF(Stop_SpectrumExpiry_Timer)
PAWSF(combiner_selectDB)
PAWSF(combiner_DBerror)
PAWSF(set_spectrum_InUse)
PAWSF(check_spectrum_InUse)
PAWSF(clear_spectrum_InUse)
PAWSF(activatePendingSpectrum)
PAWSF(ActivateSpectrumRuleset)
PAWSF(check_Notify_Required)
SLAVEF(Send_AvailableSpectrumReq)
SLAVEF(Send_Spectrum_Use_Notify)
SLAVEF(Send_Spectrum_Use_Notify_New)
SLAVEF(combiner_UlSpectrumAvailable)
SLAVEF(combiner_UlSpectrumNotAvailable)
#define QUO SM_STATE_NO_CHANGE
// ######## STL states
#define FOREACH_STATE(STATE) \
STATE(INIT) \
STATE(REQUEST_NEW_SPECTRUM) \
STATE(WAITING_SPECTRUM_RESP) \
STATE(SELECTING_NEW_SPECTRUM) \
STATE(SELECTING_NEXT_SPECTRUM) \
STATE(SPECTRUM_PENDING) \
STATE(SPECTRUM_AVAILABLE) \
STATE(SPECTRUM_NOTIFICATION) \
STATE(SPECTRUM_ACTIVE) \
STATE(NO_SPECTRUM_AVAILABLE) \
STATE(SLAVE_STATE_END_MARKER)
// ######## STL events. Note also there are common events also defined in paws_sm.h
#define FOREACH_M_EV(EV) \
EV(New_Slave_Info) \
EV(SLAVE_EV_END_MARKER)
#define GEN_STATE_ENUM(ENUM) ENUM,
#define GEN_STATE_STR(STRING) #STRING,
enum slave_state_e {
sDummyState = SM_STATE_START_OF_USER_IDS,
FOREACH_STATE(GEN_STATE_ENUM)
};
static const char *slave_state_str[] = {
"dummy",
FOREACH_STATE(GEN_STATE_STR)
};
#define GEN_M_EV_ENUM(ENUM) ev_##ENUM,
#define GEN_M_EV_STR(STRING) #STRING,
enum slave_event_e {
ev_sDummy = ev_PAWS_SM_END_EV_MARKER,
FOREACH_M_EV(GEN_M_EV_ENUM)
};
const char *slave_ev_str[] = {
"dummy",
FOREACH_M_EV(GEN_M_EV_STR)
};
//#######################################################################################
// STL debug functions
static const char* state_id_2_str(void* sm_, int id)
{
UNUSED_PARAM(sm_);
if ((id > sDummyState) && (id < SLAVE_STATE_END_MARKER))
{
return slave_state_str[(id - sDummyState)];
}
// otherwise its unknown
return "Unknown";
}
static const char* event_id_2_str(void* sm_, int id)
{
paws_slave_sm_t* sm = (paws_slave_sm_t*)sm_;
if ((id > ev_sDummy) && (id < ev_SLAVE_EV_END_MARKER))
{
return slave_ev_str[(id - ev_sDummy)];
}
// otherwise call paws_sm
return (PAWS_SM_FUNC(sm, event_id_2_str)(sm_, id));
}
//################################################################################################################################################################################################
/* State-wide State-wide Event specific */
/* State 'pre' funcs 'post' funcs Event Next state 'post' funcs */
static State state_transition_table[] = {
{ INIT , { _Clear_Spectrums }, { _Stop_Retry_Timer }, { { ev_Start, REQUEST_NEW_SPECTRUM, { _Start_maxPolling_Timer } },
{ ev_Retry_Timeout, REQUEST_NEW_SPECTRUM, { NULL } } } },
{ REQUEST_NEW_SPECTRUM , { _combiner_selectDB } , { NULL }, { { ev_DB_Error, QUO, { _combiner_DBerror,
_check_spectrum_InUse } },
{ ev_DB_Response_Failure, QUO, { _combiner_DBerror,
_check_spectrum_InUse } },
{ ev_DB_NotFound, QUO, { _combiner_DBerror,
_check_spectrum_InUse } },
{ ev_DB_Found, QUO, { _Send_AvailableSpectrumReq } },
{ ev_DB_Updated, QUO, { _Send_AvailableSpectrumReq } },
{ ev_SpectrumActive, SPECTRUM_ACTIVE, { NULL } },
{ ev_SpectrumNotActive, INIT, { _Start_Retry_Timer,
_combiner_UlSpectrumNotAvailable } },
{ ev_Retry_Timeout, QUO, { _combiner_selectDB } },
{ ev_maxPolling_Timeout, QUO, { _combiner_selectDB } },
{ ev_maxPollingQuick_Timeout, QUO, { _combiner_selectDB } },
{ ev_Available_Spectrum_Resp, SELECTING_NEW_SPECTRUM, { checkAvailableSpectrumUl } } } },
{ WAITING_SPECTRUM_RESP , { NULL } , { NULL }, { { ev_DB_Error, REQUEST_NEW_SPECTRUM, { _check_spectrum_InUse } },
{ ev_DB_Response_Failure, REQUEST_NEW_SPECTRUM, { _check_spectrum_InUse } },
{ ev_DB_NotFound, REQUEST_NEW_SPECTRUM, { _check_spectrum_InUse } },
{ ev_SpectrumActive, SPECTRUM_ACTIVE, { NULL } },
{ ev_SpectrumNotActive, INIT, { _Start_Retry_Timer,
_combiner_UlSpectrumNotAvailable } },
{ ev_Retry_Timeout, REQUEST_NEW_SPECTRUM, { NULL } },
{ ev_maxPolling_Timeout, REQUEST_NEW_SPECTRUM, { NULL } },
{ ev_maxPollingQuick_Timeout, REQUEST_NEW_SPECTRUM, { NULL } },
{ ev_Available_Spectrum_Resp, SELECTING_NEW_SPECTRUM, { checkAvailableSpectrumUl } } } },
{ SELECTING_NEW_SPECTRUM, {NULL } , { NULL }, { { ev_GPS_location_changed, REQUEST_NEW_SPECTRUM, { _clear_spectrum_InUse } },
{ ev_maxPolling_Timeout, REQUEST_NEW_SPECTRUM, { NULL } },
{ ev_maxPollingQuick_Timeout, REQUEST_NEW_SPECTRUM, { NULL } },
{ ev_SpectrumAvailable, SPECTRUM_AVAILABLE, { NULL } },
{ ev_SpectrumPending, SPECTRUM_PENDING, { NULL } },
{ ev_SpectrumNotAvailable, NO_SPECTRUM_AVAILABLE, { NULL } } } },
{ SELECTING_NEXT_SPECTRUM , { _clear_spectrum_InUse,
checkAvailableSpectrumUl }, { NULL }, { { ev_GPS_location_changed, REQUEST_NEW_SPECTRUM, { _clear_spectrum_InUse } },
{ ev_maxPolling_Timeout, REQUEST_NEW_SPECTRUM, { NULL } },
{ ev_maxPollingQuick_Timeout, REQUEST_NEW_SPECTRUM, { NULL } },
{ ev_SpectrumAvailable, SPECTRUM_AVAILABLE, { NULL } },
{ ev_SpectrumPending, SPECTRUM_PENDING, { NULL } },
{ ev_SpectrumNotAvailable, REQUEST_NEW_SPECTRUM, { NULL } } } },
{ SPECTRUM_PENDING, { _Start_SpectrumPending_Timer,
_check_spectrum_InUse}, {_Stop_SpectrumPending_Timer }, { { ev_GPS_location_changed, REQUEST_NEW_SPECTRUM, { _clear_spectrum_InUse } },
{ ev_maxPolling_Timeout, REQUEST_NEW_SPECTRUM, { NULL } },
{ ev_maxPollingQuick_Timeout, REQUEST_NEW_SPECTRUM, { NULL } },
{ ev_SpectrumExpiry_Timeout, QUO, { _clear_spectrum_InUse,
_combiner_UlSpectrumNotAvailable } },
{ ev_SpectrumActive, QUO, { NULL } },
{ ev_SpectrumNotActive, QUO, { _combiner_UlSpectrumNotAvailable } },
{ ev_SpectrumPending_Timeout, SPECTRUM_AVAILABLE, { _activatePendingSpectrum } } } },
{ SPECTRUM_AVAILABLE, { _ActivateSpectrumRuleset,
_Start_SpectrumExpiry_Timer,
_combiner_UlSpectrumAvailable }, { NULL }, { { ev_GPS_location_changed, REQUEST_NEW_SPECTRUM, { _clear_spectrum_InUse } },
{ ev_maxPolling_Timeout, REQUEST_NEW_SPECTRUM, { NULL } },
{ ev_maxPollingQuick_Timeout, REQUEST_NEW_SPECTRUM, { NULL } },
{ ev_SpectrumExpiry_Timeout, SELECTING_NEXT_SPECTRUM, { NULL } },
{ ev_DlUlSpectrumAvailable, SPECTRUM_NOTIFICATION, { NULL } } } },
{ SPECTRUM_NOTIFICATION , { _check_Notify_Required }, { NULL }, { { ev_DB_Error, INIT, { _combiner_DBerror,
_check_spectrum_InUse } },
{ ev_DB_Response_Failure, QUO, { _combiner_DBerror,
_check_spectrum_InUse } },
{ ev_DB_NotFound, QUO, { _combiner_DBerror,
_check_spectrum_InUse } },
{ ev_SpectrumActive, SPECTRUM_ACTIVE, { NULL } },
{ ev_SpectrumNotActive, INIT, { _Start_Retry_Timer,
_combiner_UlSpectrumNotAvailable } },
{ ev_GPS_location_changed, REQUEST_NEW_SPECTRUM, { _clear_spectrum_InUse } },
{ ev_maxPolling_Timeout, REQUEST_NEW_SPECTRUM, { NULL } },
{ ev_maxPollingQuick_Timeout, REQUEST_NEW_SPECTRUM, { NULL } },
{ ev_SpectrumExpiry_Timeout, SELECTING_NEXT_SPECTRUM, { NULL } },
{ ev_Notification_Required, QUO, { _Send_Spectrum_Use_Notify } },
{ ev_Notification_Not_Required, SPECTRUM_ACTIVE, { _set_spectrum_InUse,
combiner_UlNotificationSuccess } },
{ ev_Notification_Success, SPECTRUM_ACTIVE, { _set_spectrum_InUse,
combiner_UlNotificationSuccess } },
{ ev_Notification_Failure, QUO, { _check_spectrum_InUse } } } },
{ SPECTRUM_ACTIVE , { NULL }, { NULL }, { { ev_GPS_location_changed, REQUEST_NEW_SPECTRUM, { _clear_spectrum_InUse } },
{ ev_maxPolling_Timeout, REQUEST_NEW_SPECTRUM, { NULL } },
{ ev_maxPollingQuick_Timeout, REQUEST_NEW_SPECTRUM, { NULL } },
{ ev_SpectrumExpiry_Timeout, SELECTING_NEXT_SPECTRUM, { NULL } },
{ ev_New_Slave_Info, QUO, { _check_Notify_Required } },
{ ev_Notification_Required, QUO, { _Send_Spectrum_Use_Notify_New } } } },
{ NO_SPECTRUM_AVAILABLE , { _Stop_SpectrumExpiry_Timer,
_combiner_UlSpectrumNotAvailable}, { NULL }, { { ev_maxPolling_Timeout, REQUEST_NEW_SPECTRUM, { NULL } },
{ ev_maxPollingQuick_Timeout, REQUEST_NEW_SPECTRUM, { NULL } },
{ ev_GPS_location_changed, REQUEST_NEW_SPECTRUM, { _clear_spectrum_InUse } } } }
};
//#######################################################################################
static void checkAvailableSpectrumUl(void* sm_)
{
FUNC_DBG(sm_);
LOCAL_FUNC(sm_, checkAvailableSpectrum)(sm_);
}
//#######################################################################################
static void combiner_UlSpectrumAvailable(void* sm_)
{
FUNC_DBG(sm_);
COMBINER_PUBLIC_FUNC(CREATOR_SM(sm_), UlSpectrumAvailable)(CREATOR_SM(sm_));
}
//#######################################################################################
static void combiner_UlSpectrumNotAvailable(void* sm_)
{
FUNC_DBG(sm_);
COMBINER_PUBLIC_FUNC(CREATOR_SM(sm_), UlSpectrumNotAvailable)(CREATOR_SM(sm_));
}
//#######################################################################################
static void combiner_UlNotificationSuccess(void* sm_)
{
FUNC_DBG(sm_);
COMBINER_PUBLIC_FUNC(CREATOR_SM(sm_), UlNotificationSuccess)(CREATOR_SM(sm_));
}
//#######################################################################################
static void Start(void* sm_)
{
FUNC_DBG(sm_);
LOCAL_FUNC(sm_, raise_)(sm_, (int)ev_Start);
}
//#######################################################################################
static int run_tick(void* sm_)
{
// FUNC_DBG(sm_);
paws_slave_sm_t* sm = (paws_slave_sm_t*)sm_;
// run the timer
LOCAL_FUNC(sm, process_next_timer_tick)(sm_);
// process any triggered events
return LOCAL_FUNC(sm, process_events)(sm_);
}
//#######################################################################################
static bool init_vars(void* sm_, paws_device_info_t* set_master_info, paws_gps_location_t* gps, float default_max_location_change, uint32_t default_max_polling_secs,
float min_dbm_100k, uint16_t db_retry_secs, uint32_t max_polling_quick_secs)
{
FUNC_DBG(sm_);
paws_slave_sm_t* sm = (paws_slave_sm_t*)sm_;
if (!(PAWS_SM_FUNC(sm, Init)(sm_, min_dbm_100k, db_retry_secs, max_polling_quick_secs)))
{
return false;
}
// store gps
LOCAL_FUNC(sm, set_gps)(sm, gps);
// store fap info
LOCAL_FUNC(sm, set_master_info)(sm, set_master_info);
// default info
LOCAL_FUNC(sm, set_defaultInfo)(sm_, default_max_location_change, default_max_polling_secs);
return true;
}
//#######################################################################################
static bool slave_Init(void* sm_, State* stl, paws_device_info_t* master_info, paws_gps_location_t* gps, float default_max_location_change, uint32_t default_max_polling_secs,
float min_dbm_100k, uint16_t db_retry_secs, logger_cfg_t* msg_log_cfg, uint32_t max_polling_quick_secs, sm_state_info_t* sm_state_info)
{
FUNC_DBG(sm_);
paws_slave_sm_t* sm = (paws_slave_sm_t*)sm_;
// determine initial state and whether we should run the "pre" functions
int initial_state = (sm_state_info) ? sm_state_info->stl_current_state : INIT;
bool run_pre = (sm_state_info == NULL);
LOG_PRINT(sm_, LOG_INFO, "Initialising STL. state = %s", LOCAL_FUNC(sm_, state_id_2_str)(sm_, initial_state));
// generic Init
if (!(LOCAL_FUNC(sm, stl_init)(sm_, stl, initial_state, run_pre)))
{
return false;
}
// initialise variables
if (!(init_vars(sm, master_info, gps, default_max_location_change, default_max_polling_secs, min_dbm_100k, db_retry_secs, max_polling_quick_secs)))
{
return false;
}
// create logger
LOCAL_FUNC(sm, set_msgLogInfo)(sm_, msg_log_cfg);
// process pre-boot state
if (sm_state_info)
{
LOCAL_FUNC(sm, process_state_attributes)(sm_, sm_state_info);
LOCAL_FUNC(sm, process_state_timers)(sm_, sm_state_info->timer_info);
}
return true;
}
//#######################################################################################
static void paws_slave_sm_data_free(paws_slave_sm_t* sm_, paws_slave_sm_data_t* data)
{
FUNC_DBG(sm_);
if (data)
{
// nothing to free
}
}
//#######################################################################################
static void paws_slave_sm_free(paws_slave_sm_t** paws_slave_sm)
{
FUNC_DBG(*paws_slave_sm);
// check that state machine exists
if ((paws_slave_sm) && (*paws_slave_sm))
{
// free the private data attributes
paws_slave_sm_data_free(*paws_slave_sm, SLAVE_SM_DATA(*paws_slave_sm));
// free the paws_sm
// This also free the paws_sm data
paws_sm_free(&(**paws_slave_sm).paws_sm);
// free the struct
free_and_null((void**)paws_slave_sm);
}
}
//#######################################################################################
#define S_POPULATE_PAWS_SM_FUNC(sm,fnc) \
sm->paws_sm_hdr.funcs->fnc = fnc; \
sm->local_paws_sm_funcs.fnc = fnc;
#define POPULATE_SLAVE_FUNC(sm,fnc) \
sm->slave_hdr.funcs->fnc = fnc; \
sm->local_slave_funcs.fnc = fnc;
#define POPULATE_SLAVE_FUNC2(sm,fnc,fname) \
sm->slave_hdr.funcs->fnc = fname; \
sm->local_slave_funcs.fnc = fname;
#define S_POPULATE_PUBLIC_FUNC(sm,fnc) \
sm->slave_hdr.public_funcs->fnc = fnc; \
sm->local_public_funcs.fnc = fnc;
static paws_slave_sm_t* paws_slave_sm_create(void* creator, paws_sm_funcs_t* paws_sm_funcs, paws_slave_sm_funcs_t* slave_funcs, paws_slave_public_funcs_t* public_funcs, char* sm_name)
{
// FUNC_DBG(sm_);
paws_slave_sm_t* paws_slave_sm = NULL;
if (!(paws_slave_sm = malloc(sizeof(paws_slave_sm_t))))
{
goto error_hdl;
}
memset(paws_slave_sm, 0, sizeof(paws_slave_sm_t));
paws_slave_sm->slave_hdr.funcs = slave_funcs;
paws_slave_sm->slave_hdr.public_funcs = public_funcs;
paws_slave_sm->slave_hdr.data = &paws_slave_sm->slave_data_store;
// "inherit" the paws_sm
if (!(paws_slave_sm->paws_sm = paws_sm_create(creator, paws_sm_funcs, sm_name)))
{
goto error_hdl;
}
// copy the header from the paws_sm
memcpy(&paws_slave_sm->paws_sm_hdr, &paws_slave_sm->paws_sm->paws_sm_hdr, sizeof(paws_sm_header_t));
// ---- called by paws_sm
// for safety, copy the parent paws sm first, then overwrite
memcpy(&paws_slave_sm->local_paws_sm_funcs, paws_slave_sm->paws_sm_hdr.funcs, sizeof(paws_sm_funcs_t));
S_POPULATE_PAWS_SM_FUNC(paws_slave_sm, event_id_2_str);
S_POPULATE_PAWS_SM_FUNC(paws_slave_sm, state_id_2_str);
// ---- slave funcs
POPULATE_SLAVE_FUNC2(paws_slave_sm, Init, slave_Init);
POPULATE_SLAVE_FUNC(paws_slave_sm, init_vars);
POPULATE_SLAVE_FUNC(paws_slave_sm, checkAvailableSpectrumUl);
POPULATE_SLAVE_FUNC(paws_slave_sm, combiner_UlSpectrumAvailable);
POPULATE_SLAVE_FUNC(paws_slave_sm, combiner_UlSpectrumNotAvailable);
POPULATE_SLAVE_FUNC(paws_slave_sm, combiner_UlNotificationSuccess);
// ---- public funcs
S_POPULATE_PUBLIC_FUNC(paws_slave_sm, Start);
S_POPULATE_PUBLIC_FUNC(paws_slave_sm, run_tick);
return paws_slave_sm;
error_hdl:
paws_slave_sm_free(&paws_slave_sm);
return NULL;
}
// #######################################################################################################################
// #######################################################################################################################
// #######################################################################################################################
// GOP
// #######################################################################################################################
// #######################################################################################################################
// #######################################################################################################################
//#######################################################################################
static void gop_Send_AvailableSpectrumReq(void* sm_)
{
FUNC_DBG(sm_);
LOG_PRINT(sm_, LOG_NOTICE, "----> AVAIL-SPEC-REQ GOP");
json_value* resp = post_Slave_GOP_Available_Spectrum_Request(sm_, &(PAWS_SM_DATA((paws_sm_t*)sm_)->master_info), &(PAWS_SM_DATA((paws_sm_t*)sm_)->gps),
&(PAWS_SM_DATA((paws_sm_t*)sm_)->selected_db.db_url));
LOCAL_FUNC(sm_, Process_Available_Spectrum_Resp)(sm_, resp, LTE_UL, time(NULL));
json_value_free(resp);
}
//#######################################################################################
static void gop_Send_Notifications(void* sm_, paws_slave_info_t* slave_info)
{
FUNC_DBG(sm_);
paws_device_info_t* device = NULL;
int i = 0;
for (i = 0; i < slave_info->num_devices; i++)
{
device = &slave_info->device_info[i];
LOG_PRINT(sm_, LOG_NOTICE, "----> NOTIFY-REQ GOP(device = %s)", device->unique_id);
json_value* resp = post_GOP_slave_Notify_Request(sm_, &(PAWS_SM_DATA((paws_sm_t*)sm_)->master_info), device, &(PAWS_SM_DATA((paws_sm_t*)sm_)->gps),
&(PAWS_SM_DATA((paws_sm_t*)sm_)->selected_db.db_url), PAWS_SM_DATA((paws_sm_t*)sm_)->selected_spectrum, 13);
if (!(SLAVE_FUNC(sm_, Process_Notify_Use_Resp(sm_,resp))))
{
// Nothing defined
// possible enhancement is to block slave
}
json_value_free(resp);
}
LOCAL_FUNC(sm_, raise_)(sm_, (int)ev_Notification_Success);
}
//#######################################################################################
static void gop_Send_Spectrum_Use_Notify(void* sm_)
{
FUNC_DBG(sm_);
paws_gop_slave_sm_t* sm = (paws_gop_slave_sm_t*)sm_;
if ((!PAWS_SM_DATA((paws_sm_t*)sm_)->selected_spectrum))
{
LOCAL_FUNC(sm_, raise_)(sm_, (int)ev_DB_NotFound);
return;
}
SLAVE_FUNC(sm_, Send_Notifications(sm_, &PRIVATE_DATA(sm).slave_info));
}
//#######################################################################################
static void gop_Send_Spectrum_Use_Notify_New(void* sm_)
{
FUNC_DBG(sm_);
}
//#######################################################################################
static bool gop_Process_Notify_Use_Resp(void* sm_, json_value* resp)
{
FUNC_DBG(sm_);
if (LOCAL_FUNC(sm_, Check_HTTP_Result)(sm_, resp, false))
{
if (LOCAL_FUNC(sm_, Check_Valid_Resp)(sm_, resp, false))
{
// raise event to show a valid RESP was received
LOG_PRINT(sm_, LOG_NOTICE, "<---- NOTIFY-RESP");
return true;
}
}
return false;
}
//#######################################################################################
static void gop_set_slaveInfo(void* sm_, paws_slave_info_t* slave_info)
{
FUNC_DBG(sm_);
paws_gop_slave_sm_t* sm = (paws_gop_slave_sm_t*)sm_;
memcpy(&(PRIVATE_DATA(sm).slave_info), slave_info, sizeof(paws_slave_info_t));
}
//#######################################################################################
static paws_slave_info_t* gop_get_slaveInfo(void* sm_)
{
FUNC_DBG(sm_);
paws_gop_slave_sm_t* sm = (paws_gop_slave_sm_t*)sm_;
return &PRIVATE_DATA(sm).slave_info;
}
//#######################################################################################
static bool gop_Init(void* sm_, State* stl, paws_device_info_t* master_info, paws_gps_location_t* gps, float default_max_location_change, uint32_t default_max_polling_secs, paws_slave_info_t* slave_info,
float min_dbm_100k, uint16_t db_retry_secs, logger_cfg_t* msg_log_cfg, uint32_t max_polling_quick_secs, sm_state_info_t* sm_state_info)
{
paws_gop_slave_sm_t* sm = (paws_gop_slave_sm_t*)sm_;
// Initialise
if (!(PARENT_SLAVE_FUNC(sm, Init)(sm_, stl, master_info, gps, default_max_location_change, default_max_polling_secs, min_dbm_100k, db_retry_secs, msg_log_cfg, max_polling_quick_secs, sm_state_info)))
{
return false;
}
// GOP specific
GOP_FUNC(sm, set_slaveInfo)(sm, slave_info);
return true;
}
//#######################################################################################
#define POPULATE_GOP_SLAVE_FUNC(sm,fnc) sm->slave_hdr.funcs->fnc = gop_##fnc;
#define POPULATE_GOP_PUBLIC_FUNC(sm,fnc) sm->slave_hdr.public_funcs->fnc = gop_##fnc;
#define POPULATE_GOP_SPECIFIC_FUNC(sm,fnc) sm->gop_slave_hdr.funcs->fnc = gop_##fnc;
paws_gop_slave_sm_t* paws_gop_slave_sm_create(void* creator, char* sm_name, paws_device_info_t* master_info, paws_gps_location_t* gps, float default_max_location_change, uint32_t default_max_polling_secs,
paws_slave_info_t *slave_info, float min_dbm_100k, uint16_t db_retry_secs, logger_cfg_t* msg_log_cfg, uint32_t max_polling_quick_secs, sm_state_info_t* sm_state_info)
{
// FUNC_DBG(sm_);
paws_gop_slave_sm_t* paws_gop_slave_sm = NULL;
if (!(paws_gop_slave_sm = malloc(sizeof(paws_gop_slave_sm_t))))
{
goto error_hdl;
}
memset(paws_gop_slave_sm, 0, sizeof(paws_gop_slave_sm_t));
// "inherit" the slave_sm
if (!(paws_gop_slave_sm->slave_sm = paws_slave_sm_create(creator, &paws_gop_slave_sm->paws_sm_func_store, &paws_gop_slave_sm->slave_func_store, &paws_gop_slave_sm->public_func_store, sm_name )))
{
goto error_hdl;
}
// copy the paws_header from the slave_sm
memcpy(&paws_gop_slave_sm->paws_sm_hdr, &paws_gop_slave_sm->slave_sm->paws_sm_hdr, sizeof(paws_sm_header_t));
// copy the slave header
memcpy(&paws_gop_slave_sm->slave_hdr, &paws_gop_slave_sm->slave_sm->slave_hdr, sizeof(slave_sm_header_t));
// copy the paws_sm
paws_gop_slave_sm->paws_sm = paws_gop_slave_sm->slave_sm->paws_sm;
LOG_PRINT(creator, LOG_NOTICE, "Creating GOP SM");
// populate functions
// ---- paws_sm funcs
// --------none
// ---- slave funcs
POPULATE_GOP_SLAVE_FUNC(paws_gop_slave_sm, Send_AvailableSpectrumReq);
POPULATE_GOP_SLAVE_FUNC(paws_gop_slave_sm, Send_AvailableSpectrumReq);
POPULATE_GOP_SLAVE_FUNC(paws_gop_slave_sm, Send_Spectrum_Use_Notify);
POPULATE_GOP_SLAVE_FUNC(paws_gop_slave_sm, Send_Spectrum_Use_Notify_New);
POPULATE_GOP_SLAVE_FUNC(paws_gop_slave_sm, Send_Notifications);
POPULATE_GOP_SLAVE_FUNC(paws_gop_slave_sm, Process_Notify_Use_Resp);
// ---- public funcs
// --------none
// GOP-specific funcs
paws_gop_slave_sm->gop_slave_hdr.funcs = &paws_gop_slave_sm->gop_func_store;
POPULATE_GOP_SPECIFIC_FUNC(paws_gop_slave_sm, set_slaveInfo);
POPULATE_GOP_SPECIFIC_FUNC(paws_gop_slave_sm, get_slaveInfo);
// Initialise
if (!(gop_Init(paws_gop_slave_sm, state_transition_table, master_info, gps, default_max_location_change, default_max_polling_secs, slave_info, min_dbm_100k, db_retry_secs,
msg_log_cfg, max_polling_quick_secs, sm_state_info)))
{
goto error_hdl;
}
return paws_gop_slave_sm;
error_hdl:
paws_gop_slave_sm_free(&paws_gop_slave_sm);
return NULL;
}
//#######################################################################################
static void paws_gop_sm_data_free(paws_gop_slave_sm_t* sm_, paws_gop_private_data_t* data)
{
FUNC_DBG(sm_);
if (data)
{
// nothing to free
}
}
//#######################################################################################
void paws_gop_slave_sm_free(paws_gop_slave_sm_t** paws_gop_slave_sm)
{
FUNC_DBG(*paws_gop_slave_sm);
// check that state machine exists
if ((paws_gop_slave_sm) && (*paws_gop_slave_sm))
{
LOG_PRINT(*paws_gop_slave_sm, LOG_NOTICE, "Deleting GOP SM");
// free the private data attributes
paws_gop_sm_data_free(*paws_gop_slave_sm, &(PRIVATE_DATA(*paws_gop_slave_sm)));
// free the slace_sm
paws_slave_sm_free(&(**paws_gop_slave_sm).slave_sm);
// free the struct
free_and_null((void**)paws_gop_slave_sm);
}
}
// #######################################################################################################################
// #######################################################################################################################
// #######################################################################################################################
// SOP
// #######################################################################################################################
// #######################################################################################################################
// #######################################################################################################################
//#######################################################################################
static void sop_Send_AvailableSpectrumReq(void* sm_)
{
FUNC_DBG(sm_);
paws_sop_slave_sm_t* sm = (paws_sop_slave_sm_t*)sm_;
LOG_PRINT(sm_, LOG_NOTICE, "----> AVAIL-SPEC-REQ SOP (device=%s)", PRIVATE_DATA(sm).device_info.unique_id);
json_value* resp = post_Slave_SOP_Available_Spectrum_Request(sm_, &(PAWS_SM_DATA((paws_sm_t*)sm_)->master_info), &PRIVATE_DATA(sm).device_info, &PRIVATE_DATA(sm).device_info.gps,
&(PAWS_SM_DATA((paws_sm_t*)sm_)->selected_db.db_url));
LOCAL_FUNC(sm_, Process_Available_Spectrum_Resp)(sm_, resp, LTE_UL, time(NULL));
json_value_free(resp);
}
//#######################################################################################
static void sop_Send_Spectrum_Use_Notify(void* sm_)
{
FUNC_DBG(sm_);
paws_sop_slave_sm_t* sm = (paws_sop_slave_sm_t*)sm_;
if ((!PAWS_SM_DATA((paws_sm_t*)sm_)->selected_spectrum))
{
LOCAL_FUNC(sm_, raise_)(sm_, (int)ev_DB_NotFound);
return;
}
LOG_PRINT(sm_, LOG_NOTICE, "----> NOTIFY-REQ SOP (device=%s)", PRIVATE_DATA(sm).device_info.unique_id);
json_value* resp = post_SOP_slave_Notify_Request(sm_, &(PAWS_SM_DATA((paws_sm_t*)sm_)->master_info), &PRIVATE_DATA(sm).device_info, &(PAWS_SM_DATA((paws_sm_t*)sm_)->gps),
&(PAWS_SM_DATA((paws_sm_t*)sm_)->selected_db.db_url), PAWS_SM_DATA((paws_sm_t*)sm_)->selected_spectrum, 13);
if (!(SLAVE_FUNC(sm_, Process_Notify_Use_Resp(sm_, resp))))
{
LOCAL_FUNC(sm_, raise_)(sm_, (int)ev_Notification_Failure);
}
else
{
LOCAL_FUNC(sm_, raise_)(sm_, (int)ev_Notification_Success);
}
json_value_free(resp);
}
//#######################################################################################
static void sop_Send_Spectrum_Use_Notify_New(void* sm_)
{
FUNC_DBG(sm_);
}
//#######################################################################################
static bool sop_Process_Notify_Use_Resp(void* sm_, json_value* resp)
{
FUNC_DBG(sm_);
if (LOCAL_FUNC(sm_, Check_HTTP_Result)(sm_, resp, false))
{
if (LOCAL_FUNC(sm_, Check_Valid_Resp)(sm_, resp, false))
{
// raise event to show a valid RESP was received
LOG_PRINT(sm_, LOG_NOTICE, "<---- NOTIFY-RESP");
return true;
}
}
return false;
}
//#######################################################################################
static void sop_set_deviceInfo(void* sm_, paws_device_info_t* device_info)
{
FUNC_DBG(sm_);
paws_sop_slave_sm_t* sm = (paws_sop_slave_sm_t*)sm_;
memcpy(&(PRIVATE_DATA(sm).device_info), device_info, sizeof(paws_device_info_t));
}
//#######################################################################################
static paws_device_info_t* sop_get_deviceInfo(void* sm_)
{
FUNC_DBG(sm_);
paws_sop_slave_sm_t* sm = (paws_sop_slave_sm_t*)sm_;
return &PRIVATE_DATA(sm).device_info;
}
//#######################################################################################
static void sop_combiner_UlSpectrumAvailable(void* sm_)
{
FUNC_DBG(sm_);
paws_sop_slave_sm_t* sm = (paws_sop_slave_sm_t*)sm_;
avail_spectrum_t* spectrum_resp = LOCAL_FUNC(sm, GetAvailSpectrumResp)(sm);
COMBINER_PUBLIC_FUNC(CREATOR_SM(sm_), UlSOPSpectrumAvailable)(CREATOR_SM(sm_), spectrum_resp, sm_);
}
//#######################################################################################
static void sop_combiner_UlSpectrumNotAvailable(void* sm_)
{
FUNC_DBG(sm_);
COMBINER_PUBLIC_FUNC(CREATOR_SM(sm_), UlSOPSpectrumNotAvailable)(CREATOR_SM(sm_));
}
//#######################################################################################
static bool sop_Init(void* sm_, State* stl, paws_device_info_t* master_info, paws_gps_location_t* gps, float default_max_location_change, uint32_t default_max_polling_secs,
paws_device_info_t *device_info, float min_dbm_100k, uint16_t db_retry_secs, logger_cfg_t* msg_log_cfg, uint32_t max_polling_quick_secs, sm_state_info_t* sm_state_info)
{
paws_sop_slave_sm_t* sm = (paws_sop_slave_sm_t*)sm_;
// Initialise
if (!(PARENT_SLAVE_FUNC(sm, Init)(sm_, stl, master_info, gps, default_max_location_change, default_max_polling_secs, min_dbm_100k, db_retry_secs, msg_log_cfg, max_polling_quick_secs, sm_state_info)))
{
return false;
}
// SOP specific
SOP_FUNC(sm, set_deviceInfo)(sm, device_info);
return true;
}
//#######################################################################################
#define POPULATE_SOP_SLAVE_FUNC(sm,fnc) sm->slave_hdr.funcs->fnc = sop_##fnc;
#define POPULATE_SOP_PUBLIC_FUNC(sm,fnc) sm->slave_hdr.public_funcs->fnc = sop_##fnc;
#define POPULATE_SOP_SPECIFIC_FUNC(sm,fnc) sm->sop_slave_hdr.funcs->fnc = sop_##fnc;
paws_sop_slave_sm_t* paws_sop_slave_sm_create(void* creator, char* sm_name, paws_device_info_t* master_info, paws_gps_location_t* gps, float default_max_location_change, uint32_t default_max_polling_secs,
paws_device_info_t *device_info, float min_dbm_100k, uint16_t db_retry_secs, logger_cfg_t* msg_log_cfg, uint32_t max_polling_quick_secs, sm_state_info_t* sm_state_info)
{
// FUNC_DBG(sm_);
paws_sop_slave_sm_t* paws_sop_slave_sm = NULL;
if (!(paws_sop_slave_sm = malloc(sizeof(paws_sop_slave_sm_t))))
{
goto error_hdl;
}
memset(paws_sop_slave_sm, 0, sizeof(paws_sop_slave_sm_t));
// "inherit" the slave_sm
if (!(paws_sop_slave_sm->slave_sm = paws_slave_sm_create(creator, &paws_sop_slave_sm->paws_sm_func_store, &paws_sop_slave_sm->slave_func_store, &paws_sop_slave_sm->public_func_store, sm_name)))
{
goto error_hdl;
}
// copy the paws_header from the slave_sm
memcpy(&paws_sop_slave_sm->paws_sm_hdr, &paws_sop_slave_sm->slave_sm->paws_sm_hdr, sizeof(paws_sm_header_t));
// copy the slave header
memcpy(&paws_sop_slave_sm->slave_hdr, &paws_sop_slave_sm->slave_sm->slave_hdr, sizeof(slave_sm_header_t));
// copy the paws_sm
paws_sop_slave_sm->paws_sm = paws_sop_slave_sm->slave_sm->paws_sm;
LOG_PRINT(creator, LOG_NOTICE, "Creating SOP SM [%s]", sm_name);
// populate functions
// ---- paws_sm funcs
// --------none
// ---- slave funcs
POPULATE_SOP_SLAVE_FUNC(paws_sop_slave_sm, Send_AvailableSpectrumReq);
POPULATE_SOP_SLAVE_FUNC(paws_sop_slave_sm, Send_AvailableSpectrumReq);
POPULATE_SOP_SLAVE_FUNC(paws_sop_slave_sm, Send_Spectrum_Use_Notify);
POPULATE_SOP_SLAVE_FUNC(paws_sop_slave_sm, Send_Spectrum_Use_Notify_New);
POPULATE_SOP_SLAVE_FUNC(paws_sop_slave_sm, Process_Notify_Use_Resp);
POPULATE_SOP_SLAVE_FUNC(paws_sop_slave_sm, combiner_UlSpectrumAvailable);
POPULATE_SOP_SLAVE_FUNC(paws_sop_slave_sm, combiner_UlSpectrumNotAvailable);
// ---- public funcs
// --------none
// GOP-specific funcs
paws_sop_slave_sm->sop_slave_hdr.funcs = &paws_sop_slave_sm->sop_func_store;
POPULATE_SOP_SPECIFIC_FUNC(paws_sop_slave_sm, set_deviceInfo);
POPULATE_SOP_SPECIFIC_FUNC(paws_sop_slave_sm, get_deviceInfo);
// Initialise
if (!(sop_Init(paws_sop_slave_sm, state_transition_table, master_info, gps, default_max_location_change, default_max_polling_secs, device_info, min_dbm_100k, db_retry_secs,
msg_log_cfg, max_polling_quick_secs, sm_state_info)))
{
goto error_hdl;
}
return paws_sop_slave_sm;
error_hdl:
paws_sop_slave_sm_free(&paws_sop_slave_sm);
return NULL;
}
//#######################################################################################
static void paws_sop_sm_data_free(paws_sop_slave_sm_t* sm_, paws_sop_private_data_t* data)
{
FUNC_DBG(sm_);
if (data)
{
// nothing to free
}
}
//#######################################################################################
void paws_sop_slave_sm_free(paws_sop_slave_sm_t** paws_sop_slave_sm)
{
FUNC_DBG(*paws_sop_slave_sm);
// check that state machine exists
if ((paws_sop_slave_sm) && (*paws_sop_slave_sm))
{
LOG_PRINT(*paws_sop_slave_sm, LOG_NOTICE, "Deleting SOP SM [%s]", (*paws_sop_slave_sm)->paws_sm_hdr.unique_id);
// free the private data attributes
paws_sop_sm_data_free(*paws_sop_slave_sm, &(PRIVATE_DATA(*paws_sop_slave_sm)));
// free the slace_sm
paws_slave_sm_free(&(**paws_sop_slave_sm).slave_sm);
// free the struct
free_and_null((void**)paws_sop_slave_sm);
}
}

View File

@@ -0,0 +1,19 @@
/*
Copyright (c) Microsoft Corporation. All rights reserved.
Licensed under the MIT License.
*/
#ifndef PAWS_SM_SLAVE_H_
#define PAWS_SM_SLAVE_H_
#include "paws_slave_sm_types.h"
extern paws_gop_slave_sm_t* paws_gop_slave_sm_create(void* creator, char* sm_name, paws_device_info_t* master_info, paws_gps_location_t* gps, float default_max_location_change, uint32_t default_max_polling_secs,
paws_slave_info_t *slave_info, float min_dbm_100k, uint16_t db_retry_secs, logger_cfg_t* msg_log_cfg, uint32_t max_polling_quick_secs, sm_state_info_t* sm_state_info);
extern void paws_gop_slave_sm_free(paws_gop_slave_sm_t** paws_gop_slave_sm);
extern paws_sop_slave_sm_t* paws_sop_slave_sm_create(void* creator, char* sm_name, paws_device_info_t* master_info, paws_gps_location_t* gps, float default_max_location_change, uint32_t default_max_polling_secs,
paws_device_info_t *device_info, float min_dbm_100k, uint16_t db_retry_secs, logger_cfg_t* msg_log_cfg, uint32_t max_polling_quick_secs, sm_state_info_t* sm_state_info);
extern void paws_sop_slave_sm_free(paws_sop_slave_sm_t** paws_sop_slave_sm);
#endif // #define PAWS_SM_SLAVE_H_

View File

@@ -0,0 +1,118 @@
/*
Copyright (c) Microsoft Corporation. All rights reserved.
Licensed under the MIT License.
*/
#ifndef PAWS_SLAVE_SM_TYPES_H_
#define PAWS_SLAVE_SM_TYPES_H_
#include "paws_sm_types.h"
typedef struct {
bool (*Init)(void* sm_, State* stl, paws_device_info_t* master_info, paws_gps_location_t* gps, float default_max_location_change, uint32_t default_max_polling_secs, float min_dbm_100k, uint16_t db_retry_secs, logger_cfg_t* msg_log_cfg, uint32_t max_polling_quick_secs, sm_state_info_t* sm_state_info);
bool (*init_vars)(void* sm_, paws_device_info_t* master_info, paws_gps_location_t* gps, float default_max_location_change, uint32_t default_max_polling_secs, float min_dbm_100k, uint16_t db_retry_secs, uint32_t max_polling_quick_secs);
paws_sm_func checkAvailableSpectrumUl;
paws_sm_func combiner_UlSpectrumAvailable;
paws_sm_func combiner_UlSpectrumNotAvailable;
paws_sm_func combiner_UlNotificationSuccess;
//The following are all pure virtual
paws_sm_func Send_AvailableSpectrumReq;
paws_sm_func Send_Spectrum_Use_Notify;
paws_sm_func Send_Spectrum_Use_Notify_New;
void (*Send_Notifications)(void* sm_, paws_slave_info_t* slave_info);
bool (*Process_Notify_Use_Resp)(void* sm_, json_value* resp);
void (*update_slave_info)(void* sm_, paws_slave_info_t* slave_info);
} paws_slave_sm_funcs_t;
typedef struct {
int dummy1; // nothing
} paws_slave_sm_data_t;
typedef struct {
paws_sm_func Start;
int (*run_tick)(void* sm_);
} paws_slave_public_funcs_t;
typedef struct {
paws_slave_sm_funcs_t* funcs; // THIS MUST BE FIRST.
paws_slave_public_funcs_t* public_funcs;
paws_slave_sm_data_t* data;
} slave_sm_header_t;
typedef struct {
paws_sm_header_t paws_sm_hdr; // THIS MUST BE FIRST IN ANY SM WHICH HAS A PAWS_SM.
paws_sm_t* paws_sm;
slave_sm_header_t slave_hdr;
paws_sm_funcs_t local_paws_sm_funcs;
paws_slave_sm_funcs_t local_slave_funcs;
paws_slave_public_funcs_t local_public_funcs;
paws_slave_sm_data_t slave_data_store;
} paws_slave_sm_t;
typedef struct {
paws_slave_info_t slave_info;
} paws_gop_private_data_t;
typedef struct {
void (*set_slaveInfo)(void* sm_, paws_slave_info_t* slave_info);
paws_slave_info_t* (*get_slaveInfo)(void* sm_);
} paws_gop_slave_sm_funcs_t;
typedef struct {
paws_gop_slave_sm_funcs_t* funcs;
} gop_slave_sm_header_t;
typedef struct {
paws_sm_header_t paws_sm_hdr; // THIS MUST BE FIRST IN ANY SM WHICH HAS A PAWS_SM.
paws_sm_t* paws_sm; //
slave_sm_header_t slave_hdr; //
paws_sm_funcs_t paws_sm_func_store; //
paws_slave_sm_funcs_t slave_func_store; //
paws_slave_public_funcs_t public_func_store; // down to here must match paws_slave_sm_t
gop_slave_sm_header_t gop_slave_hdr;
paws_gop_private_data_t private_data_store;
paws_gop_slave_sm_funcs_t gop_func_store; // these are functions specific to GOP
paws_slave_sm_t* slave_sm;
} paws_gop_slave_sm_t;
typedef struct {
paws_device_info_t device_info;
} paws_sop_private_data_t;
typedef struct {
void (*set_deviceInfo)(void* sm_, paws_device_info_t* device_info);
paws_device_info_t* (*get_deviceInfo)(void* sm_);
} paws_sop_slave_sm_funcs_t;
typedef struct {
paws_sop_slave_sm_funcs_t* funcs;
} sop_slave_sm_header_t;
typedef struct {
paws_sm_header_t paws_sm_hdr; // THIS MUST BE FIRST IN ANY SM WHICH HAS A PAWS_SM.
paws_sm_t* paws_sm; //
slave_sm_header_t slave_hdr; //
paws_sm_funcs_t paws_sm_func_store; //
paws_slave_sm_funcs_t slave_func_store; //
paws_slave_public_funcs_t public_func_store; // down to here must match paws_slave_sm_t
sop_slave_sm_header_t sop_slave_hdr;
paws_sop_private_data_t private_data_store;
paws_sop_slave_sm_funcs_t sop_func_store; // these are functions specific to SOP
paws_slave_sm_t* slave_sm;
} paws_sop_slave_sm_t;
#endif // #define PAWS_SLAVE_SM_TYPES_H_

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,19 @@
/*
Copyright (c) Microsoft Corporation. All rights reserved.
Licensed under the MIT License.
*/
#ifndef PAWS_SM_H_
#define PAWS_SM_H_
#include "paws_sm_types.h"
// funntions
extern paws_sm_t* paws_sm_create(void* creator, paws_sm_funcs_t* child_funcs, const char* sm_name);
extern void paws_sm_free(paws_sm_t** paws_sm);
#endif // #define PAWS_SM_H_

View File

@@ -0,0 +1,209 @@
/*
Copyright (c) Microsoft Corporation. All rights reserved.
Licensed under the MIT License.
*/
#ifndef PAWS_SM_TYPES_H_
#define PAWS_SM_TYPES_H_
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <stdbool.h>
#include "utils/types.h"
#include "json-parser/json.h"
#include "gps/gps.h"
#include "state-machine/state-machine.h"
#include "timers/timer.h"
#include "logger/logger.h"
#include "logger/cloud_logger.h"
#include "paws_types.h"
typedef void (*paws_sm_func)(void* sm_);
typedef const char* (*IdToString)(void* sm_, int id);
#define PAWS_SM_FUNC_PROTO(fnc) static void fnc(void* sm_);
typedef struct {
logger_cfg_t cfg;
void* logger;
} paws_sm_logger_t;
typedef struct {
// defintion of all static class functions called from STL
void (*store_state)(void* sm_, sm_state_info_t* sm_state_info);
void (*free_state)(void* sm_, sm_state_info_t* sm_state_info);
paws_sm_func read_state;
void (*process_state_attributes)(void* sm_, sm_state_info_t* state_info);
void (*process_state_timers)(void* sm_, char* timer_info);
paws_sm_func Start;
paws_sm_func Init_states;
paws_sm_func Clear_Spectrums;
paws_sm_func DLULSpectrumAvailable;
paws_sm_func DLULSpectrumNotAvailable;
paws_sm_func set_spectrum_InUse;
paws_sm_func clear_spectrum_InUse;
paws_sm_func check_spectrum_InUse;
paws_sm_func ActivateSpectrumRuleset;
paws_sm_func check_Notify_Required;
paws_sm_func Start_Retry_Timer;
paws_sm_func Stop_Retry_Timer;
paws_sm_func Start_maxPolling_Timer;
paws_sm_func Stop_maxPolling_Timer;
paws_sm_func Start_maxPollingQuick_Timer;
paws_sm_func Stop_maxPollingQuick_Timer;
paws_sm_func Start_SpectrumPending_Timer;
paws_sm_func Stop_SpectrumPending_Timer;
paws_sm_func activatePendingSpectrum;
paws_sm_func Start_SpectrumExpiry_Timer;
paws_sm_func Stop_SpectrumExpiry_Timer;
paws_sm_func combiner_selectDB;
paws_sm_func combiner_DBerror;
// defintion of static class functions which are not called directly by STL
bool (*Check_HTTP_Result)(void* sm_, json_value* resp, bool raise);
void (*combiner_ProcessDbUpdate)(void* sm_, json_value* new_db_spec);
void (*set_db)(void* sm_, paws_db_item_t* db);
bool (*Check_Valid_Resp)(void* sm_, json_value* resp, bool raise);
void (*Process_Available_Spectrum_Resp)(void* sm_, json_value* resp, lte_direction_e dir, time_t resp_time);
avail_spectrum_t* (*GetAvailSpectrumResp)(void* sm_);
void (*checkAvailableSpectrum)(void* sm_);
bool (*set_selected_spectrum)(void* sm_, spec_cfg_t* spec_cfg);
spec_cfg_t* (*get_spectrum_InUse)(void* sm_);
void (*clear_Ruleset)(void* sm_);
float (*get_max_location_change)(void* sm_);
uint32_t (*get_max_polling_secs)(void* sm_);
void (*Process_Notify_Use_Resp)(void* sm_, json_value* resp);
void (*timeout_handler)(void* sm_, uint32_t id);
void (*Retry_Timer_Hdlr)(void* sm_);
void (*set_maxPollingQuick)(void* sm_, uint32_t dur_secs);
void (*maxPolling_Timer_Hdlr)(void* sm_);
void (*maxPollingQuick_Timer_Hdlr)(void* sm_);
void (*SpectrumPending_Timer_Hdlr)(void* sm_);
void (*SpectrumExpiry_Timer_Hdlr)(void* sm_);
void (*set_master_info)(void* sm_, paws_device_info_t* master_info);
void (*set_defaultInfo)(void* sm_, float max_location_change, uint32_t max_polling_secs);
void (*set_gps)(void* sm_, paws_gps_location_t* gps);
void (*gps_changed)(void* sm_);
const char* (*state_id_2_str)(void* sm_, int id);
const char* (*event_id_2_str)(void* sm_, int id);
void (*state_changed_dbg)(void* sm_, int old_state, int new_state);
void (*event_processed_dbg)(void* sm_, int event_id);
bool (*set_LogInfo)(void* sm_, paws_sm_logger_t* logger, logger_cfg_t* cfg);
bool (*set_msgLogInfo)(void* sm_, logger_cfg_t* cfg);
void (*app_log)(void* sm_, const char* file_, int line_, const char* func_, const char* logline, log_level_e level);
void (*app_log_tvwsdb_msg)(void* sm_, const char* msg);
void (*msg_log_tvwsdb_msg)(void* sm_, char* cloud_log_j);
void (*raise_)(void* sm_, int event_id);
bool (*Init)(void* sm_, float min_dbm_100k, uint16_t db_retry_secs, uint32_t max_polling_quick_secs);
paws_sm_func process_next_timer_tick;
int (*process_events)(void* sm_);
bool (*stl_init)(void* sm_, State *state_transition_table, int initial_state, bool run_pre);
void (*stl_set_state_explicit)(void* sm_, int state);
} paws_sm_funcs_t;
typedef struct {
paws_db_item_t selected_db;
uint8_t db_ok;
paws_gps_location_t gps;
// log info
paws_sm_logger_t msg_log;
// paws settings
float min_dbm_100k; // min dbm per 100k to qualify for selection
uint16_t db_retry_secs; // how often to retry events (default=15)
// ruleset
float default_max_location_change;
float specific_max_location_change;
uint32_t default_max_polling_secs;
uint32_t specific_max_polling_secs;
uint32_t max_polling_quick_secs;
avail_spectrum_t* avail_spectrum_resp; // PAWS SPECTRUM-AVAIL-RESP
spec_cfg_t* available_spectrum; // available, but might not have a corresponding paired spec.
spec_cfg_t* pending_spectrum; // resp has a spectrum, but start_time is in future.
spec_cfg_t* selected_spectrum; // selected to be used
spec_cfg_t* spectrum_in_use; // selected actually being used
paws_device_info_t master_info;
} paws_sm_data_t;
typedef struct {
StateMachine* stl;
TimerManager* timer_manager;
} paws_sm_stl_data_t;
typedef struct {
device_name_t unique_id;
void* creator; // state machine which has created this entity
paws_sm_funcs_t* funcs; // THIS MUST BE FIRST.
paws_sm_data_t* data;
paws_sm_stl_data_t* stl_data;
} paws_sm_header_t;
typedef struct {
paws_sm_header_t paws_sm_hdr; // THIS MUST BE FIRST IN ANY SM WHICH HAS A PAWS_SM.
paws_sm_data_t paws_sm_data_store;
paws_sm_stl_data_t paws_sm_stl_data_store;
paws_sm_funcs_t local_funcs;
} paws_sm_t;
#define FOREACH_EV(EV) \
EV(LocalDB_Error) \
EV(Start) \
EV(GPS_location_changed) \
EV(DB_UpdateTriggered) \
EV(DB_Error) \
EV(DB_Updated) \
EV(DB_Found) \
EV(DB_NotFound) \
EV(DB_Response_Failure) \
EV(Available_Spectrum_Resp) \
EV(SpectrumAvailable) \
EV(SpectrumNotAvailable) \
EV(SpectrumPending) \
EV(DlUlSpectrumAvailable) \
EV(DlUlSpectrumNotAvailable) \
EV(SpectrumActive) \
EV(SpectrumNotActive) \
EV(Notification_Required) \
EV(Notification_Not_Required) \
EV(Notification_Success) \
EV(Notification_Failure) \
EV(Retry_Timeout) \
EV(maxPolling_Timeout) \
EV(maxPollingQuick_Timeout) \
EV(SpectrumPending_Timeout) \
EV(SpectrumExpiry_Timeout) \
EV(PAWS_SM_END_EV_MARKER)
#define GEN_EV_ENUM(ENUM) ev_##ENUM,
enum paws_event_e {
ev_Dummy = SM_EVENT_START_OF_USER_IDS,
FOREACH_EV(GEN_EV_ENUM)
};
typedef enum {
RETRY_TIMER_ID = 1,
SPECTRUM_EXPIRY_TIMER_ID,
SPECTRUM_PENDING_TIMER_ID,
MAX_POLLING_TIMER_ID,
MAX_POLLING_QUICK_TIMER_ID,
PAWS_SM_TIMER_END
} paws_sm_timers_e;
#endif // #define PAWS_SM_TYPES_H_

View File

@@ -0,0 +1,24 @@
/*
Copyright (c) Microsoft Corporation. All rights reserved.
Licensed under the MIT License.
*/
#ifndef PAWS_TIMER_INFO_H_
#define PAWS_TIMER_INFO_H_
//####### Timer tolerance
// some timers experiencing max duration between actions. These tolerances specify how close to the end of max-duration to reach before expiring the timer
#define DB_DISCOVERY_TIMER_TOLERANCE (60)
#define SPECTRUM_EXPIRY_TIMER_TOLERANCE (15)
#define MAX_POLLING_TIMER_TOLERANCE (15)
// ####### Timer durations
#define DB_SETTINGS_INITIAL_DURATION (1 * 60) // start off every 1 mins, but this will get overwritten
#define DB_DEVICES_INITIAL_DURATION (1 * 60) // start off every 1 mins, but this will get overwritten
#define PERIODIC_GPS_DEVICES_INITIAL_DURATION (5) // quick check until we have SETIINGS defined
#define DB_DISCOVERY_TIMER_INITIAL_DURATION (DB_DISCOVERY_TIMER_TOLERANCE + 60) // start off every 1 min, but this will get overwritten by the received refreshRate.
#define DB_DISCOVERY_TIMER_QUICK_DURATION (75 * 60) // ## 75 minutes ## as per ETSI EN 301 598 v1.1.1
#define LOCAL_ISSUE_BACKOFF_TIMER_DURATION (10) // There has been a local problem. How long to wait before we re-init the whole system
#endif // #define PAWS_TIMER_INFO_H_

View File

@@ -0,0 +1,74 @@
/*
Copyright (c) Microsoft Corporation. All rights reserved.
Licensed under the MIT License.
*/
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <sys/stat.h>
#include <time.h>
#include "utils/utils.h"
#include "paws_types.h"
#include "paws_dal_types.h"
//#######################################################################################
// Return code as it per strcmp
// p1 < p2: return -1
// p1 == p2: return 0
// p1 > p2: return +2
int ul_dl_spec_cfg_freq_compare(ul_dl_spec_cfg_t* p1, ul_dl_spec_cfg_t* p2)
{
if ((!p1) || (!p1->dl_cfg) || (!p1->ul_cfg) || (!p2) || (!p2->dl_cfg) || (!p2->ul_cfg))
return -1;
// frequency
// dl
int ret = (p1->dl_cfg->start_hz < p2->dl_cfg->start_hz) ? -1 : ((p1->dl_cfg->start_hz == p2->dl_cfg->start_hz) ? 0 : 1);
if (ret != 0)
return ret;
// ul
ret = (p1->ul_cfg->start_hz < p2->ul_cfg->start_hz) ? -1 : ((p1->ul_cfg->start_hz == p2->ul_cfg->start_hz) ? 0 : 1);
return ret;
}
// Return code as it per strcmp
// p1 < p2: return -1
// p1 == p2: return 0
// p1 > p2: return +2
// Note that bandwidth is checked first, then power.
int ul_dl_spec_cfg_pwr_compare(ul_dl_spec_cfg_t* p1, ul_dl_spec_cfg_t* p2)
{
if ((!p1) || (!p1->dl_cfg) || (!p1->ul_cfg) || (!p2) || (!p2->dl_cfg) || (!p2->ul_cfg))
return -1;
// bandwidth
// dl
int ret = (p1->dl_cfg->bandwidth < p2->dl_cfg->bandwidth) ? -1 : ((p1->dl_cfg->bandwidth == p2->dl_cfg->bandwidth) ? 0 : 1);
if (ret != 0)
return ret;
// ul
ret = (p1->ul_cfg->bandwidth < p2->ul_cfg->bandwidth) ? -1 : ((p1->ul_cfg->bandwidth == p2->ul_cfg->bandwidth) ? 0 : 1);
if (ret != 0)
return ret;
// power
// dl
ret = (p1->dl_cfg->dbm < p2->dl_cfg->dbm) ? -1 : ((p1->dl_cfg->dbm == p2->dl_cfg->dbm) ? 0 : 1);
if (ret != 0)
return ret;
// ul
ret = (p1->ul_cfg->dbm < p2->ul_cfg->dbm) ? -1 : ((p1->ul_cfg->dbm == p2->ul_cfg->dbm) ? 0 : 1);
return ret;
}

View File

@@ -0,0 +1,24 @@
/*
Copyright (c) Microsoft Corporation. All rights reserved.
Licensed under the MIT License.
*/
#ifndef PAWS_TYPES_
#define PAWS_TYPES_
#include <time.h>
#include "utils/types.h"
#include "paws_dal_devices.h"
#include "paws_dal_settings.h"
#include "paws_dal_state.h"
#include "paws_dal_database.h"
int ul_dl_spec_cfg_freq_compare(ul_dl_spec_cfg_t* p1, ul_dl_spec_cfg_t* p2);
int ul_dl_spec_cfg_pwr_compare(ul_dl_spec_cfg_t* p1, ul_dl_spec_cfg_t* p2);
extern int ul_dl_spec_cfg_compare(ul_dl_spec_cfg_t* p1, ul_dl_spec_cfg_t* p2);
#endif // PAWS_TYPES_

View File

@@ -0,0 +1,565 @@
/*
Copyright (c) Microsoft Corporation. All rights reserved.
Licensed under the MIT License.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <sys/stat.h>
#include "utils/utils.h"
#include "json-parser/json_utils.h"
#include "paws_utils.h"
#include "paws_globals.h"
#include "paws_types.h"
#include "paws_dal_types.h"
#include "lte_utils.h"
char logline_[LOGGER_MAX_LENGTH];
#define DBM_NO_POWER (-999)
//#######################################################################################
static void set_stop_time(time_t* stop_time_t, time_t now_, uint32_t maxPollingSecs)
{
time_t forced_stop_t = now_ + maxPollingSecs;
if (g_paws_reg_domain == PAWS_REGDOMAIN_ETSI)
{
if (*stop_time_t > forced_stop_t) // ETSI 301 598 4.2.6.3.2
{
*stop_time_t = forced_stop_t;
}
}
}
//#######################################################################################
void weblist_free(paws_weblist_t** weblist)
{
if ((weblist) && (*weblist))
{
if ((*weblist)->items)
{
free_and_null((void*)&(*weblist)->items);
}
free_and_null((void**)weblist);
}
}
//#######################################################################################
paws_weblist_t* json_2_weblist(json_value* src)
{
paws_weblist_t* weblist = NULL;
// check src
if (!src)
goto error_hdl;
// malloc a new type
if (!(weblist = malloc(sizeof(paws_weblist_t))))
goto error_hdl;
memset(weblist, 0, (sizeof(paws_weblist_t)));
// get refresh rate
char* s = NULL;
weblist->refresh_rate = ((s = json_get_string(src, "ws_databases/refresh_rate"))) ? atoi(s) : 0;
// now fill in the rest
json_value* v = json_get(src, "ws_databases/db");
if (v && v->type == json_array)
{
weblist->num_items = v->u.array.length;
if (weblist->num_items)
{
if (!(weblist->items = malloc((sizeof(weblist_item_t) * weblist->num_items))))
goto error_hdl;
memset(weblist->items, 0, (sizeof(weblist_item_t) * weblist->num_items));
weblist_item_t* item = NULL;
for (int i=0; i<weblist->num_items; i++)
{
char *ss = NULL;
int slen;
json_value* d = v->u.array.values[i];
item = &(weblist->items[i]);
if ((!d) || (d->type!=json_object))
goto error_hdl;
// url
if (!(ss = json_get_string(d, "url")))
goto error_hdl;
slen = snprintf(item->url, MAX_URL_LENGTH, "%s", ss);
if ((slen < 0) || (slen >= MAX_URL_LENGTH))
goto error_hdl;
// db_provider_name
if (!(ss = json_get_string(d, "db_provider_name")))
goto error_hdl;
slen = snprintf(item->name, MAX_DB_NAME_LENGTH, "%s", ss);
if ((slen < 0) || (slen >= MAX_DB_NAME_LENGTH))
goto error_hdl;
// mcwsd_support
if (!(json_get_bool(d, "MCWSD_support", &item->mcwsd_support)))
goto error_hdl;
}
}
}
return weblist;
error_hdl:
if (weblist) weblist_free(&weblist);
return NULL;
}
//#######################################################################################
// convert timestamp to time_t
// returns -1 on failure
int timestamp_to_timet(char* src)
{
struct tm tm;
memset(&tm, 0, sizeof(tm));
if (!src)
return -1;
// remove micosecs
char *pos = strrchr(src, '.');
if (pos)
*pos = '\0';
// convert to tm
if (!(strptime(src, "%Y-%m-%dT%H:%M:%S", &tm)))
return -1;
else
return (mktime(&tm));
}
//#######################################################################################
avail_spectrum_t* json_resp_2_avail_spectrum(void *sm_, json_value* src, lte_direction_e dir, uint8_t lte_band_id, time_t resp_time, float min_dbm_100k)
{
uint32_t i, j, k, m, n;
uint32_t band_start_hz, band_end_hz;
int32_t band_spacing;
char *timestamp_str;
avail_spectrum_t* avail_spec = NULL;
spectrum_spec_t* spectrum_spec = NULL;
spectrum_schedule_t* spectrum_sched = NULL;
spec_profile_type_t* profile = NULL;
int contiguous;
if (!(get_lte_band_channel(lte_band_id, dir, &band_start_hz, &band_end_hz, &band_spacing)))
return NULL;
// calulate the wsdb time phase using the timesdtamp in the message and our local response time
// get the timestamp
if (!(timestamp_str = json_get_string(src, "result/timestamp")))
goto error_hdl;
// store timestamp as time_t
time_t db_timestamp, db_phase;
if ((db_timestamp = timestamp_to_timet(timestamp_str)) == -1)
goto error_hdl;
db_phase = db_timestamp - resp_time;
// malloc the main struct
if (!(avail_spec = avail_spectrum_new()))
goto error_hdl;
spectrum_spec_t* tail_spectrum_spec = NULL;
json_value* spectrum_specs_j=NULL;
if (!(spectrum_specs_j = json_get(src, "result/spectrumSpecs")))
goto error_hdl;
if (spectrum_specs_j->type != json_array)
goto error_hdl;
// for each spectrum spec
for (i = 0; i < spectrum_specs_j->u.array.length; i++)
{
if (!(spectrum_spec = spectrum_spec_new()))
goto error_hdl;
spectrum_schedule_t* tail_spectrum_sched = NULL;
json_value* spectrum_spec_j = spectrum_specs_j->u.array.values[i];
if (spectrum_spec_j->type != json_object)
goto error_hdl;
json_value* spectra_schedules_j = NULL;
if (!(spectra_schedules_j = json_get(spectrum_spec_j, "spectrumSchedules")))
continue;
if (spectra_schedules_j->type != json_array)
goto error_hdl;
// ruleset info
// we get this first because, for ETSI regulation domain, we limit the expiry time to the time of the tUpdate (max_polling_secs)
json_value* ruleset_j = NULL;
int64_t maxPollingSecs;
double maxLocationChange;
if (!(((ruleset_j = json_get(spectrum_spec_j, "rulesetInfo"))) &&
((json_get_int(ruleset_j, "maxPollingSecs", &maxPollingSecs))) &&
((json_get_double(ruleset_j, "maxLocationChange", (double*)&maxLocationChange)))))
{
goto error_hdl;
}
spectrum_spec->ruleset_info.maxPollingSecs = maxPollingSecs;
spectrum_spec->ruleset_info.maxLocationChange = (float)maxLocationChange;
spectrum_spec->max_contiguous_bw_hz_within_band = 0;
for (j = 0; j < spectra_schedules_j->u.array.length; j++)
{
json_value* spectrum_sched_j = spectra_schedules_j->u.array.values[i];
if (spectrum_sched_j->type != json_object)
goto error_hdl;
// get times and check if this spectrum has already expired
// get an event time if present
json_value* event_time_range_j = NULL;
char* start_time = NULL;
char* stop_time = NULL;
if (!(((event_time_range_j = json_get(spectrum_sched_j, "eventTime"))) &&
((start_time = json_get_string(event_time_range_j, "startTime"))) &&
((stop_time = json_get_string(event_time_range_j, "stopTime")))))
{
goto error_hdl;
}
// store times as time_t
time_t start_time_t, stop_time_t;
if ((start_time_t = timestamp_to_timet(start_time)) == -1)
goto error_hdl;
start_time_t -= db_phase;
if ((stop_time_t = timestamp_to_timet(stop_time)) == -1)
goto error_hdl;
stop_time_t -= db_phase;
time_t now_ = time(NULL);
// limit start/stop times if regulation body forces it
set_stop_time(&stop_time_t, now_, spectrum_spec->ruleset_info.maxPollingSecs);
// if start time > stop_time it is invalid. This could happen if domain has limited stop time
if (start_time_t > stop_time_t)
{
continue;
}
// if start_time is in the past, set it to 'now'
if (now_ > start_time_t)
start_time_t = now_;
// if stop time is already expired, drop this spectrum_sched
if (now_ > stop_time_t)
{
continue;
}
if(!(spectrum_sched = spectrum_sched_new()))
goto error_hdl;
spec_profile_type_t* tail_profile = NULL;
// populate the times
spectrum_sched->event_time_range.start_time = start_time_t;
spectrum_sched->event_time_range.stop_time = stop_time_t;
json_value* spectra_j = NULL;
if (!(spectra_j = json_get(spectrum_sched_j, "spectra")))
continue;
if (spectra_j->type != json_array)
goto error_hdl;
// for each spectra item
for (k = 0; k < spectra_j->u.array.length; k++)
{
json_value* spectra_item_j = spectra_j->u.array.values[k];
if (spectra_item_j->type != json_object)
goto error_hdl;
// is this for resolutionBwHx = 100000.0
double res_bw_hz;
if (!(json_get_double(spectra_item_j, "resolutionBwHz", &res_bw_hz)))
continue;
if (res_bw_hz != (double)100000)
continue;
json_value* profiles_j = NULL;
if (!(profiles_j = json_get(spectra_item_j, "profiles")))
continue;
if (profiles_j->type != json_array)
goto error_hdl;
contiguous = 0;
for (m = 0; m < profiles_j->u.array.length; m++)
{
json_value* profile_j = profiles_j->u.array.values[m];
if (profile_j->type != json_array)
goto error_hdl;
// check there are "pairs" of assignments provided
if (profile_j->u.array.length % 2)
goto error_hdl;
for (n = 0; n < (profile_j->u.array.length / 2); n++)
{
double start_hz_dbl, end_hz_dbl, dbm;
uint32_t start_hz, end_hz;
json_value* item_j = profile_j->u.array.values[n*2];
if (!(json_get_double(item_j, "hz", &start_hz_dbl)))
goto error_hdl;
if (!(json_get_double(item_j, "dbm", &dbm)))
goto error_hdl;
item_j = profile_j->u.array.values[(n*2)+1];
if (!(json_get_double(item_j, "hz", &end_hz_dbl)))
goto error_hdl;
start_hz = (uint32_t)start_hz_dbl;
end_hz = (uint32_t)end_hz_dbl;
// it is within the band range
if ((end_hz <= band_start_hz) || (start_hz >= band_end_hz))
{
// update contiguous
if (contiguous > spectrum_spec->max_contiguous_bw_hz_within_band)
spectrum_spec->max_contiguous_bw_hz_within_band = contiguous;
contiguous = 0;
continue;
}
// does it have ANY power
if (DBM_NO_POWER == dbm)
{
LOG_PRINT(sm_, LOG_NOTICE, "Channel has no power : %.2fMhz->%.2fMhz", start_hz_dbl / 1000000, end_hz_dbl / 1000000);
// update contiguous
if (contiguous > spectrum_spec->max_contiguous_bw_hz_within_band)
spectrum_spec->max_contiguous_bw_hz_within_band = contiguous;
contiguous = 0;
continue;
}
// does it have ENOUGH power
if (dbm < min_dbm_100k)
{
LOG_PRINT(sm_, LOG_NOTICE, "Channel has < min (%.2fdBm) power : %.2fMhz->%.2fMhz pwr:%.2fdBm", min_dbm_100k, start_hz_dbl/1000000, end_hz_dbl/1000000, dbm);
// update contiguous
if (contiguous > spectrum_spec->max_contiguous_bw_hz_within_band)
spectrum_spec->max_contiguous_bw_hz_within_band = contiguous;
contiguous = 0;
continue;
}
// add to contiguous
uint32_t prof_bw = end_hz - start_hz;
if (start_hz < band_start_hz)
prof_bw -= (band_start_hz - start_hz);
else if (band_end_hz < end_hz)
prof_bw -= (end_hz - band_end_hz);
contiguous += prof_bw;
// malloc an entry
profile = malloc(sizeof(spec_profile_type_t));
memset(profile, 0, sizeof(spec_profile_type_t));
profile->start_hz = start_hz;
profile->end_hz = end_hz;
profile->dbm = (float)dbm;
// append to spectrum_schedule->profiles
if (spectrum_sched->profiles == NULL)
{
spectrum_sched->profiles = profile;
tail_profile = profile;
}
else
{
tail_profile->next = profile;
tail_profile = profile;
}
profile = NULL;
}
} // profiles_j
} // spectra
// check if something was added for this spectrum_schedule
if (spectrum_sched->profiles == NULL)
spectrum_sched_free(&spectrum_sched);
else
{
// append to spectrum_spec->spectrum_schedules
if (spectrum_spec->spectrum_schedules == NULL)
{
spectrum_spec->spectrum_schedules = spectrum_sched;
tail_spectrum_sched = spectrum_sched;
}
else
{
tail_spectrum_sched->next = spectrum_sched;
tail_spectrum_sched = spectrum_sched;
}
spectrum_sched = NULL;
}
} // spectra_schedules_j
// update contiguous
if (contiguous > spectrum_spec->max_contiguous_bw_hz_within_band)
{
spectrum_spec->max_contiguous_bw_hz_within_band = contiguous;
}
// check if something was added for this spectrum_spec
if (spectrum_spec->spectrum_schedules == NULL)
spectrum_spec_free(&spectrum_spec);
else
{
// max contiguous bw hz
double max_contiguous_bw_hz;
if ((json_get_double(spectrum_spec_j, "maxContiguousBwHz", &max_contiguous_bw_hz)))
spectrum_spec->max_contiguous_bw_hz = (float)max_contiguous_bw_hz;
// need spectrum report
if (!(json_get_bool(spectrum_spec_j, "needsSpectrumReport", &spectrum_spec->needsSpectrumReport)))
spectrum_spec->needsSpectrumReport = false;
// append to avail_spectrum->spectrum_specs
if (avail_spec->spectrum_specs == NULL)
{
avail_spec->spectrum_specs = spectrum_spec;
}
else
{
tail_spectrum_spec->next = spectrum_spec;
}
tail_spectrum_spec = spectrum_spec;
spectrum_spec = NULL;
}
} // spectrum_specs
return avail_spec;
error_hdl:
if (profile) free(profile);
if (spectrum_spec) spectrum_spec_free(&spectrum_spec);
if (spectrum_sched) spectrum_sched_free(&spectrum_sched);
if (avail_spec) avail_spectrum_free(&avail_spec);
return NULL;
}
//#######################################################################################
static void spectrum_sched_print(spectrum_schedule_t* sched, int spec_id, int sched_id)
{
char tmptime1[50];
char tmptime2[50];
strftime(tmptime1, sizeof(tmptime1), "%Y-%m-%dT%H:%M:%S", gmtime(&sched->event_time_range.start_time));
strftime(tmptime2, sizeof(tmptime2), "%Y-%m-%dT%H:%M:%S", gmtime(&sched->event_time_range.stop_time));
printf("[spec %d][sched %d] start=%s stop=%s \n", spec_id, sched_id, tmptime1, tmptime2);
spec_profile_type_t* prof = sched->profiles;
if (prof == NULL)
printf("[spec %d][sched %d] profiles=%p\n", spec_id, sched_id, prof);
while (prof)
{
printf("[spec %d][sched %d] prof: start:%d end:%d dbm:%.2f \n", spec_id, sched_id, prof->start_hz, prof->end_hz, prof->dbm );
prof = prof->next;
}
}
static void spectrum_spec_print(spectrum_spec_t* spec, int spec_id)
{
int sched_id = 0;
printf("[spec %d] max_contiguous_bw_hz=%.4f \n", spec_id, spec->max_contiguous_bw_hz);
printf("[spec %d] max_contiguous_bw_hz_within_band=%.4f \n", spec_id, spec->max_contiguous_bw_hz_within_band);
printf("[spec %d] needsSpectrumReport=%d \n", spec_id, spec->needsSpectrumReport);
printf("[spec %d] ruleSetInfo [ maxPollingSecs=%d maxLocationChange=%.2f ] \n", spec_id, spec->ruleset_info.maxPollingSecs, spec->ruleset_info.maxLocationChange);
spectrum_schedule_t* spectrum_sched = spec->spectrum_schedules;
if (spectrum_sched == NULL)
printf(" spectrum_schedules = %p \n", spectrum_sched);
while (spectrum_sched)
{
spectrum_sched_print(spectrum_sched, spec_id, sched_id);
spectrum_sched = spectrum_sched->next;
sched_id += 1;
}
}
void avail_spectrum_print(avail_spectrum_t* s)
{
int spec_id = 0;
printf("avail_spectrum=%p \n", s);
if (s)
{
spectrum_spec_t* spectrum_spec = s->spectrum_specs;
if (spectrum_spec == NULL)
printf(" spectrum_specs = %p \n", spectrum_spec);
while (spectrum_spec)
{
spectrum_spec_print(spectrum_spec, spec_id);
spectrum_spec = spectrum_spec->next;
spec_id += 1;
}
}
}
//#######################################################################################
bool json_dbUpdate_2_dblist(json_value* dbUpdate_j, const char* token, uint32_t* num_db, paws_db_item_t* db_list)
{
if (!((dbUpdate_j) && (token) && (db_list)))
return false;
if (dbUpdate_j->type != json_array)
return false;
// clean the old DB
memset(db_list, 0, (sizeof(paws_db_item_t) * PAWS_MAX_DB_LIST));
*num_db = 0;
for (uint32_t i = 0; i < dbUpdate_j->u.array.length; i++)
{
json_value* db_j = dbUpdate_j->u.array.values[i];
char *name = NULL;
char *uri = NULL;
if (!(((db_j->type == json_object)) &&
((name = json_get_string(db_j, "name"))) &&
((uri = json_get_string(db_j, "uri")))))
{
goto error_hdl;
}
// add to db_info
memcpy(&(db_list[i].db_url.token[0]), token, strlen(token));
memcpy(&(db_list[i].db_url.host[0]), uri, strlen(uri));
memcpy(&(db_list[i].name[0]), name, strlen(name));
db_list[i].valid = true;
(*num_db)++;
}
return true;
error_hdl:
memset(db_list, 0, (sizeof(paws_db_item_t) * PAWS_MAX_DB_LIST));
*num_db = 0;
return false;
}

View File

@@ -0,0 +1,46 @@
/*
Copyright (c) Microsoft Corporation. All rights reserved.
Licensed under the MIT License.
*/
#ifndef PAWS_UTILS_H_
#define PAWS_UTILS_H_
#include "json-parser/json.h"
#include "logger/logger.h"
#include "paws_types.h"
#include "paws_globals.h"
#include "paws_common.h"
extern void weblist_free(paws_weblist_t** weblist);
extern paws_weblist_t* json_2_weblist(json_value* src);
extern avail_spectrum_t* json_resp_2_avail_spectrum(void *sm_, json_value* src, lte_direction_e dir, uint8_t lte_band_id, time_t resp_time, float min_dbm_100k);
extern void avail_spectrum_print(avail_spectrum_t* spec);
extern int timestamp_to_timet(char* src);
extern bool json_dbUpdate_2_dblist(json_value* dbUpdate_j, const char* token, uint32_t* num_db, paws_db_item_t* db_list);
extern char logline_[];
#define LOG_PRINT(sm, loglevel, fmt, args...) { \
if (loglevel >= gPawsAppLoggerCfg.level) \
{ \
int slen = snprintf(logline_, LOGGER_MAX_LENGTH, fmt, ##args); \
if (!((slen <= 0) || (slen >= LOGGER_MAX_LENGTH))) \
{ \
LOCAL_FUNC(sm, app_log)(sm, __FILENAME__, __LINE__, __func__, logline_, loglevel); \
} \
} \
}
#define APPLOG_TVWSDB_MSG(sm, msg) { LOCAL_FUNC(sm, app_log_tvwsdb_msg)(sm, msg); }
#define MSGLOG_TVWSDB_MSG(sm, jmsg) { LOCAL_FUNC(sm, msg_log_tvwsdb_msg)(sm, jmsg); }
#define FUNC_DBG(sm) LOG_PRINT(sm, LOG_FUNC, " ")
#endif // #define PAWS_UTILS_H_

View File

@@ -0,0 +1,120 @@
/*
Copyright (c) Microsoft Corporation. All rights reserved.
Licensed under the MIT License.
*/
#include <stdio.h>
#include <sqlite3.h>
#include "sctp_agent_db_info.h"
#define MAX_SCTP_AGENT_DB_NAME (100)
static char g_sctp_agent_db[MAX_SCTP_AGENT_DB_NAME] = "\0";
//#######################################################################################
bool set_sctp_agent_db_location(char* db)
{
if (!db)
return false;
int slen = snprintf(g_sctp_agent_db, MAX_SCTP_AGENT_DB_NAME, "%s", db);
if ((slen <= 0) || (slen >= MAX_SCTP_AGENT_DB_NAME))
return false;
return true;
}
//#######################################################################################
char* get_sctp_agent_db_location(void)
{
return &g_sctp_agent_db[0];
}
//#######################################################################################
bool get_sctp_agent_info(uint32_t* status_port, uint32_t* status_periodicity)
{
sqlite3 *sql_hdl = NULL;
sqlite3_stmt *stmt = NULL;
int port = -1;
int periodicity = -1;
// get datafile location and open it
char* db_sql_file = get_sctp_agent_db_location();
if (!db_sql_file)
{
goto error_hdl;
}
sqlite3_open(db_sql_file, &sql_hdl);
if (!sql_hdl)
{
goto error_hdl;
}
// get the port
const char *sql = "SELECT passthrough_ctl_port FROM SocketInfo";
int rc = sqlite3_prepare_v2(sql_hdl, sql, -1, &stmt, NULL);
if (rc != SQLITE_OK)
{
goto error_hdl;
}
while ((rc = sqlite3_step(stmt)) == SQLITE_ROW)
{
port = sqlite3_column_int(stmt, 0);
}
if (rc != SQLITE_DONE)
{
goto error_hdl;
}
sqlite3_finalize(stmt); stmt = NULL;
if (port == -1)
{
goto error_hdl;
}
// get the paws status periodicity i.e. how often the status must be sent to the sctp-agent
const char *sql2 = "SELECT passthrough_ctl_periodicity FROM Settings";
rc = sqlite3_prepare_v2(sql_hdl, sql2, -1, &stmt, NULL);
if (rc != SQLITE_OK)
{
goto error_hdl;
}
while ((rc = sqlite3_step(stmt)) == SQLITE_ROW)
{
periodicity = sqlite3_column_int(stmt, 0);
}
if (rc != SQLITE_DONE)
{
goto error_hdl;
}
sqlite3_finalize(stmt); stmt = NULL;
if (periodicity == -1)
{
goto error_hdl;
}
// release database
if (sql_hdl) sqlite3_close(sql_hdl);
*status_port = port;
*status_periodicity = periodicity;
return true;
error_hdl:
if (sql_hdl) sqlite3_close(sql_hdl);
if (stmt) sqlite3_finalize(stmt);
return false;
}

View File

@@ -0,0 +1,19 @@
/*
Copyright (c) Microsoft Corporation. All rights reserved.
Licensed under the MIT License.
*/
#include <stdint.h>
#include <stdbool.h>
#ifndef SCTP_AGENT_DB_INFO_H_
#define SCTP_AGENT_DB_INFO_H_
extern bool set_sctp_agent_db_location(char* db);
extern char* get_sctp_agent_db_location(void);
extern bool get_sctp_agent_info(uint32_t* port, uint32_t* status_periodicity);
#endif // SCTP_AGENT_DB_INFO_H_

View File

@@ -0,0 +1,34 @@
##
## Copyright (c) Microsoft Corporation. All rights reserved.
## Licensed under the MIT License.
##
include ${PRJROOT}/Makefile.common
DB_SCHEMA=paws_schema.json
COMMON_SRC=common_$(TARGET_PLATFORM).json
DEFAULT_SRC=$(COMMON_SRC) gps_$(TARGET_PLATFORM).json devices_$(TARGET_PLATFORM).json
native_SRC = $(COMMON_SRC) gps_$(TARGET_PLATFORM).json devices_$(TARGET_PLATFORM).json
fap_SRC = $(COMMON_SRC) devices_$(TARGET_PLATFORM).json
db=paws_$(TARGET_PLATFORM).db
.PHONY: db
db: $(db)
$(db): $(DB_SCHEMA) $(DEFAULT_SRC)
rm -f tmp_db
python ../../../libs/sql_db/create_db.py --schema "$(DB_SCHEMA)" --data_l "$($(TARGET_PLATFORM)_SRC)" --o tmp_db
cp -f tmp_db $(db)
.PHONY: natives
natives: native1_override.db
native1_override.db : $(DB_SCHEMA) $(DEFAULT_SRC) override_native.json
rm -f tmp_db
python ../../../libs/sql_db/create_db.py --schema "$(DB_SCHEMA)" --data_l "$(DEFAULT_SRC) override_native.json" --o tmp_db
cp -f tmp_db native1_override.db

View File

@@ -0,0 +1,43 @@
{
"VersionInfo": {
"version": 1
},
"TVWSDBInfo": {
"weblist_host": "http://sandbox-tvws-databases.wsdb.uk",
"weblist_filename": "/weblist.json"
},
"TVWSDBInfoDB": [
{
"name": "nominet-sandbox",
"host": "http://sandbox-paws.wsdb.uk",
"token": "your token",
"valid": true
}
],
"Settings": {
"min_dl_dbm_100k": -30.0,
"min_ul_dbm_100k": -30.0,
"db_retry_secs": 15,
"db_barred_secs": 45,
"setting_periodic_secs": 300,
"devices_periodic_secs": 60,
"gps_periodic_fast_check_secs": 10,
"gps_periodic_slow_check_secs": 120,
"max_polling_quick_secs": 300
},
"SettingsLogInfo": {
"level": 2,
"logname": "/var/log/paws_app_log.txt",
"tvwsdb_messages_logname": "/var/log/paws_messages.json",
"file_size": "2M",
"max_files": 5,
"compress": true
},
"SettingsCloudLogInfo": {
"level": 3,
"logname": "/var/log/paws_cloud_log.txt",
"cloud_ip": "",
"port": 8600
}
}

View File

@@ -0,0 +1,43 @@
{
"VersionInfo": {
"version": 1
},
"TVWSDBInfo": {
"weblist_host": "http://sandbox-tvws-databases.wsdb.uk",
"weblist_filename": "/weblist.json"
},
"TVWSDBInfoDB": [
{
"name": "nominet-sandbox",
"host": "http://sandbox-paws.wsdb.uk",
"token": "your token",
"valid": true
}
],
"Settings": {
"min_dl_dbm_100k": -30.0,
"min_ul_dbm_100k": -30.0,
"db_retry_secs": 15,
"db_barred_secs": 45,
"setting_periodic_secs": 300,
"devices_periodic_secs": 60,
"gps_periodic_fast_check_secs": 10,
"gps_periodic_slow_check_secs": 120,
"max_polling_quick_secs": 300
},
"SettingsLogInfo": {
"level": 0,
"logname": "tmp/log/paws_app_log.txt",
"tvwsdb_messages_logname": "tmp/log/paws_messages.json",
"file_size": "10M",
"max_files": 10,
"compress": true
},
"SettingsCloudLogInfo": {
"level": 3,
"logname": "test/log/paws_cloud_log.txt",
"cloud_ip": "10.5.1.134 or dns",
"port": 8600
}
}

View File

@@ -0,0 +1,60 @@
{
"DeviceInfo": [
{
"deviceid": "test.fap",
"manufacturer": "IPAccess",
"model": "E40"
},
{
"deviceid": "00101123001003",
"manufacturer": "Novatel",
"model": "6610L"
},
{
"deviceid": "00101123001001",
"manufacturer": "Novatel",
"model": "6610L"
},
{
"deviceid": "00101123001002",
"manufacturer": "Novatel",
"model": "6610L"
}
],
"DeviceInfoAntenna": [
{
"deviceid": "test.fap",
"gain": 4.0
}
],
"DeviceInfoCharacteristics": [
{
"deviceid": "test.fap",
"type": "A",
"cat": "master",
"emission_class": 3,
"technology_id": "AngularJS"
},
{
"deviceid": "00101123001003",
"type": "B",
"cat": "slave",
"emission_class": "5",
"technology_id": "AngularJS"
},
{
"deviceid": "00101123001001",
"type": "B",
"cat": "slave",
"emission_class": "5",
"technology_id": "AngularJS"
},
{
"deviceid": "00101123001002",
"type": "B",
"cat": "slave",
"emission_class": "5",
"technology_id": "AngularJS"
}
]
}

View File

@@ -0,0 +1 @@
{ }

View File

@@ -0,0 +1,37 @@
{
"Gps": [
{
"deviceid": "test.fap",
"fixed": true,
"latitude": 52.194903,
"longitude": 0.134992,
"height": 15,
"heightType": "AGL"
},
{
"deviceid": "00101123001001",
"fixed": true,
"latitude": 52.194903,
"longitude": 0.134992,
"height": 15,
"heightType": "AGL"
},
{
"deviceid": "00101123001002",
"fixed": true,
"latitude": 52.194903,
"longitude": 0.134992,
"height": 15,
"heightType": "AGL"
},
{
"deviceid": "00101123001003",
"fixed": true,
"latitude": 52.194903,
"longitude": 0.134992,
"height": 15,
"heightType": "AGL"
}
]
}

View File

@@ -0,0 +1,10 @@
{
"SettingsSpectrumOverride": {
"present": true,
"bandwidth_rb": 25,
"earfcndl": 5205,
"earfcnul": 23205,
"RefSigPower": -3,
"PMax": 10
}
}

View File

@@ -0,0 +1,77 @@
{
"VersionInfo": {
"version": "INTEGER"
},
"TVWSDBInfo": {
"weblist_host": "VARCHAR(100)",
"weblist_filename": "VARCHAR(30)"
},
"TVWSDBInfoDB": {
"name": "VARCHAR(64)",
"host": "VARCHAR(100)",
"token": "VARCHAR(128)",
"valid": "BOOLEAN",
"barred_utc": "VARCHAR(64)"
},
"Settings": {
"min_dl_dbm_100k": "FLOAT",
"min_ul_dbm_100k": "FLOAT",
"db_retry_secs": "INTEGER",
"db_barred_secs": "INTEGER",
"setting_periodic_secs": "INTEGER",
"devices_periodic_secs": "INTEGER",
"gps_periodic_fast_check_secs": "INTEGER",
"gps_periodic_slow_check_secs": "INTEGER",
"max_polling_quick_secs": "INTEGER"
},
"SettingsLogInfo": {
"level": "INTEGER",
"logname": "VARCHAR(100)",
"tvwsdb_messages_logname": "VARCHAR(100)",
"file_size": "VARCHAR(10)",
"max_files": "INTEGER",
"compress": "BOOLEAN"
},
"SettingsCloudLogInfo": {
"level": "INTEGER",
"logname": "VARCHAR(100)",
"cloud_ip": "VARCHAR(200)",
"port": "INTEGER"
},
"PreBootState": {
"state_str": "VARCHAR(25000)"
},
"DeviceInfo": {
"deviceid": "VARCHAR(30)",
"manufacturer": "VARCHAR(30)",
"model": "VARCHAR(20)"
},
"DeviceInfoAntenna": {
"deviceid": "VARCHAR(30)",
"gain": "FLOAT"
},
"DeviceInfoCharacteristics": {
"deviceid": "VARCHAR(30)",
"type": "VARCHAR(2)",
"cat": "VARCHAR(7)",
"emission_class": "INTEGER",
"technology_id": "VARCHAR(7)"
},
"Gps": {
"deviceid": "VARCHAR(30)",
"fixed": "BOOLEAN",
"latitude": "FLOAT",
"longitude": "FLOAT",
"height": "INTEGER",
"heightType": "VARCHAR(20)"
},
"SettingsSpectrumOverride": {
"present": "BOOLEAN",
"bandwidth_rb": "INTEGER",
"earfcndl": "INTEGER",
"earfcnul": "INTEGER",
"RefSigPower": "INTEGER",
"PMax": "INTEGER"
}
}

View File

@@ -0,0 +1,36 @@
##
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License.
##
include ${PRJROOT}/Makefile.common
APP = sctp-agent
C_LIBS += -l4gclient -lm
INC_DIRS += -I./$(TARGET_PLATFORM)
## tcps1
C_SRC += $(wildcard tcps1/*.c)
INC_DIRS += -I./tcps1
# ifeq ($(TARGET_PLATFORM),native)
# CFLAGS += -DTCPS1_TEST
# endif
## if TARGET_PLATFORM = fap or native
ifeq ($(TARGET_PLATFORM),$(filter $(TARGET_PLATFORM),fap native))
C_LIBS += -lsqlite3
INC_DIRS += -I./lte_db -I./sctp_agent_db
C_SRC += $(wildcard $(TARGET_PLATFORM)/*.c)
DB_SRC = $(wildcard sctp_agent_db/*.c)
DB_SRC += $(wildcard lte_db/*.c)
C_SRC += $(DB_SRC)
DEPS = $(patsubst %.o,%.d,$(C_OBJ))
endif
include ${PRJROOT}/rules.mk
.PHONY: db
db:
make -C sql_db db

View File

@@ -0,0 +1,71 @@
/*
Copyright(c) Microsoft Corporation.All rights reserved.
Licensed under the MIT License.
*/
// Standard headers
#include <ctype.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include "tcps1_api.h"
void tcps1_config(event_callback_func peer_ready_func,
socket_send_func passthru_to_enb_func, socket_send_func passthru_to_mme_func, socket_send_func send_to_mme_func,
event_callback_func drop_enb_socket_func, event_callback_func drop_mme_socket_func, event_callback_func reset_mme_socket_func,
void* logger, void* cloud_logger,
device_name_t device_name, device_id_t device_id,
uint32_t pkt_ack_guard_ms, uint32_t pkt_retx_max_attempts)
{
printf("%s: peer_ready_func=%p, passthru_to_enb_func=%p, passthru_to_mme_func=%p, send_to_mme_func=%p, drop_enb_socket_func=%p, drop_mme_socket_func=%p, reset_mme_socket_func=%p, logger=%p, cloud_logger=%p, device_name=%p, device_id=%d, pkt_ack_guard_ms=%d, pkt_retx_max_attempts=%d \n",
__func__, peer_ready_func, passthru_to_enb_func, passthru_to_mme_func, send_to_mme_func, drop_enb_socket_func, drop_mme_socket_func, reset_mme_socket_func, logger, cloud_logger, device_name, device_id, pkt_ack_guard_ms, pkt_retx_max_attempts);
}
void tcps1_reset(void)
{
printf("%s\n", __func__);
}
void tcps1_trigger_reset(void)
{
printf("%s\n", __func__);
}
void tcps1_free(void)
{
printf("%s\n", __func__);
}
void tcps1_process_ul(uint8_t* pkt, uint32_t pkt_len)
{
printf("%s: pkt=%p len=%d\n", __func__, pkt, pkt_len);
}
void tcps1_process_dl(uint8_t* pkt, uint32_t pkt_len)
{
printf("%s: pkt=%p len=%d\n", __func__, pkt, pkt_len);
}
void tcps1_process_timer_expiry(void)
{
printf("%s\n", __func__);
}
void tcps1_mme_disconnected(void)
{
printf("%s\n", __func__);
}
void tcps1_mme_connected(void)
{
printf("%s\n", __func__);
}
bool tcps1_is_mme_ready(void)
{
printf("%s\n", __func__);
return false;
}

View File

@@ -0,0 +1,40 @@
/*
Copyright(c) Microsoft Corporation.All rights reserved.
Licensed under the MIT License.
*/
// Platform headers
#ifdef _MSC_VER
#include <winsock2.h>
typedef unsigned socklen_t;
#else
#include <arpa/inet.h>
#include <errno.h>
#include <fcntl.h>
#include <netdb.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>
#endif
// Standard headers
#include <ctype.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <time.h>
#include "device_db_info.h"
// ##############################################################
uint16_t map_mme_sctp_port(uint16_t enb_sctp_port)
{
// use the same port
return enb_sctp_port;
}

View File

@@ -0,0 +1,16 @@
/*
Copyright(c) Microsoft Corporation.All rights reserved.
Licensed under the MIT License.
*/
#ifndef DEVICE_DB_INFO_H_
#define DEVICE_DB_INFO_H_
#define SCTP_AGENT_DB_LOCATION "/config/sctp_agent.db"
#define LTE_DB_LOCATION "/config/femto.db"
extern uint16_t map_mme_sctp_port(uint16_t enb_sctp_port);
#endif // DEVICE_DB_INFO_H_

View File

@@ -0,0 +1,252 @@
/*
Copyright(c) Microsoft Corporation.All rights reserved.
Licensed under the MIT License.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/stat.h>
#include <time.h>
#include <sqlite3.h>
#include "lte_db_info.h"
#define MAX_LTE_DB_NAME (100)
static char g_lte_db[MAX_LTE_DB_NAME] = "\0";
//#######################################################################################
bool lte_db_set_location(char* db)
{
if (!db)
return false;
int slen = snprintf(g_lte_db, MAX_LTE_DB_NAME, "%s", db);
if ((slen <= 0) || (slen >= MAX_LTE_DB_NAME))
return false;
return true;
}
//#######################################################################################
char* lte_db_get_location(void)
{
return &g_lte_db[0];
}
//#######################################################################################
static bool get_device_name(device_name_t device_name)
{
sqlite3 *sql_hdl = NULL;
sqlite3_stmt *stmt = NULL;
int rc;
memset(device_name, 0, sizeof(device_name_t));
// get datafile location and open it
char* db_sql_file = lte_db_get_location();
if (!db_sql_file)
{
goto error_hdl;
}
sqlite3_open(db_sql_file, &sql_hdl);
if (!sql_hdl)
{
goto error_hdl;
}
// get the DeviceId. We use FAPServiceAccessMgmtLTE.HNBName
const char *sql = "SELECT HNBName FROM FAPServiceAccessMgmtLTE";
rc = sqlite3_prepare_v2(sql_hdl, sql, -1, &stmt, NULL);
if (rc != SQLITE_OK)
{
goto error_hdl;
}
while ((rc = sqlite3_step(stmt)) == SQLITE_ROW)
{
char* tmp = (char*)sqlite3_column_text(stmt, 0);
if (tmp)
{
snprintf(device_name, sizeof(device_name_t), "%s", tmp);
}
}
if (rc != SQLITE_DONE)
{
goto error_hdl;
}
sqlite3_finalize(stmt); stmt = NULL;
// release database
if (sql_hdl) sqlite3_close(sql_hdl);
return true;
error_hdl:
if (sql_hdl) sqlite3_close(sql_hdl);
if (stmt) sqlite3_finalize(stmt);
return false;
}
//#######################################################################################
static bool get_device_id(device_id_t* device_id)
{
sqlite3 *sql_hdl = NULL;
sqlite3_stmt *stmt = NULL;
int rc;
*device_id = 0;
// get datafile location and open it
char* db_sql_file = lte_db_get_location();
if (!db_sql_file)
{
goto error_hdl;
}
sqlite3_open(db_sql_file, &sql_hdl);
if (!sql_hdl)
{
goto error_hdl;
}
// get the DeviceId. We use FAPServiceAccessMgmtLTE.HNBName
const char *sql = "SELECT CellIdentity FROM FAPServiceCellConfigLTERANCommon";
rc = sqlite3_prepare_v2(sql_hdl, sql, -1, &stmt, NULL);
if (rc != SQLITE_OK)
{
goto error_hdl;
}
while ((rc = sqlite3_step(stmt)) == SQLITE_ROW)
{
*device_id = sqlite3_column_int(stmt, 0);
}
if (rc != SQLITE_DONE)
{
goto error_hdl;
}
sqlite3_finalize(stmt); stmt = NULL;
// release database
if (sql_hdl) sqlite3_close(sql_hdl);
return true;
error_hdl:
if (sql_hdl) sqlite3_close(sql_hdl);
if (stmt) sqlite3_finalize(stmt);
return false;
}
//#######################################################################################
bool lte_db_get_enb_info(int *port, device_name_t device_name, device_id_t *device_id)
{
sqlite3 *sql_hdl = NULL;
sqlite3_stmt *stmt = NULL;
*port = -1;
if (!(get_device_name(device_name)))
{
goto error_hdl;
}
if (!(get_device_id(device_id)))
{
goto error_hdl;
}
// get datafile location and open it
char* db_sql_file = lte_db_get_location();
if (!db_sql_file)
{
goto error_hdl;
}
sqlite3_open(db_sql_file, &sql_hdl);
if (!sql_hdl)
{
goto error_hdl;
}
// #################################################################################################################
// get the sctp port used for the eNB software to connect to the SCTP database
const char *sql = "SELECT S1SigLinkPort FROM FAPServiceFAPControlLTEGateway";
int rc = sqlite3_prepare_v2(sql_hdl, sql, -1, &stmt, NULL);
if (rc != SQLITE_OK)
{
goto error_hdl;
}
while ((rc = sqlite3_step(stmt)) == SQLITE_ROW)
{
*port = sqlite3_column_int(stmt, 0);
}
if (rc != SQLITE_DONE)
{
goto error_hdl;
}
sqlite3_finalize(stmt); stmt = NULL;
// release database
if (sql_hdl) sqlite3_close(sql_hdl);
return true;
error_hdl:
if (sql_hdl) sqlite3_close(sql_hdl);
if (stmt) sqlite3_finalize(stmt);
return false;
}
//#######################################################################################
bool lte_db_get_RxTxStatus(int *tx_status)
{
sqlite3 *sql_hdl = NULL;
sqlite3_stmt *stmt = NULL;
// get datafile location and open it
char* db_sql_file = lte_db_get_location();
if (!db_sql_file)
{
goto error_hdl;
}
sqlite3_open(db_sql_file, &sql_hdl);
if (!sql_hdl)
{
goto error_hdl;
}
// #################################################################################################################
// get the sctp port used for the eNB software to connect to the SCTP database
const char *sql = "SELECT RFTxStatus FROM FAPServiceFAPControlLTE";
int rc = sqlite3_prepare_v2(sql_hdl, sql, -1, &stmt, NULL);
if (rc != SQLITE_OK)
{
goto error_hdl;
}
while ((rc = sqlite3_step(stmt)) == SQLITE_ROW)
{
*tx_status = sqlite3_column_int(stmt, 0);
}
if (rc != SQLITE_DONE)
{
goto error_hdl;
}
sqlite3_finalize(stmt); stmt = NULL;
// release database
if (sql_hdl) sqlite3_close(sql_hdl);
return true;
error_hdl:
if (sql_hdl) sqlite3_close(sql_hdl);
if (stmt) sqlite3_finalize(stmt);
return false;
}

View File

@@ -0,0 +1,23 @@
/*
Copyright(c) Microsoft Corporation.All rights reserved.
Licensed under the MIT License.
*/
#include <stdint.h>
#include <stdbool.h>
#ifndef LTE_DB_INFO_H_
#define LTE_DB_INFO_H_
#include "utils/types.h"
extern bool lte_db_set_location(char* db);
extern char* lte_db_get_location(void);
extern bool lte_db_get_enb_info(int *port, device_name_t device_name, device_id_t *device_id);
extern bool lte_db_get_RxTxStatus(int *tx_status);
#endif // LTE_DB_INFO_H_

View File

@@ -0,0 +1,108 @@
/*
Copyright(c) Microsoft Corporation.All rights reserved.
Licensed under the MIT License.
*/
// Platform headers
#ifdef _MSC_VER
#include <winsock2.h>
typedef unsigned socklen_t;
#else
#include <arpa/inet.h>
#include <errno.h>
#include <fcntl.h>
#include <netdb.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>
#endif
// Standard headers
#include <ctype.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <time.h>
#include "device_db_info.h"
#include "lte_db_info.h"
#include "sctp_agent_db_info.h"
#include "sctp_agent.h"
#define sctp_fatal_error(msg, ...) \
{ \
fprintf(stderr, "FATAL ERROR in %s, line %d: ", __FILE__, __LINE__); \
printf(msg, ##__VA_ARGS__); \
putchar('\n'); \
exit(-1); \
}
#define sctp_fatal_perror(msg) \
{ \
fprintf(stderr, "FATAL ERROR in %s, line %d: ", __FILE__, __LINE__); \
perror(msg); \
exit(-1); \
}
// Cfg
sctp_agent_cfg_t g_sctp_agent_cfg;
// globals
device_name_t gDeviceName = { 0 };
device_id_t gDeviceId = 0;
// #########################################################################################################
static void get_database_configs(void)
{
if (!(set_sctp_agent_db_location(SCTP_AGENT_DB_LOCATION)))
sctp_fatal_error("Cant set SCTP-AGENT-DB location");
if (!(lte_db_set_location(LTE_DB_LOCATION)))
sctp_fatal_error("Cant set Device-DB location");
// loop until the SCTP settings are read correctly
while (1)
{
if ((get_sctp_agent_cfg(&g_sctp_agent_cfg)))
break;
sleep(1); // try in a second
}
// loop until the LTE-DB settings are read correctly
while (1)
{
int port = -1;
if (lte_db_get_enb_info(&port, gDeviceName, &gDeviceId))
{
g_sctp_agent_cfg.socket_info.enb_sctp_port = port;
break;
}
sleep(1); // try in a second
}
// use the same SCTP port as the destination MME SCTP port
g_sctp_agent_cfg.socket_info.mme_sctp_port = map_mme_sctp_port(g_sctp_agent_cfg.socket_info.enb_sctp_port);
}
// #########################################################################################################
int main()
{
// wait a while for other services to come up
sleep(10);
memset(&g_sctp_agent_cfg, 0, sizeof(sctp_agent_cfg_t));
// this will loop until the databases are read
get_database_configs();
// it wont return from the function unless there is a failure
sctp_agent_run(&g_sctp_agent_cfg);
return 0;
}

View File

@@ -0,0 +1,275 @@
/*
Copyright(c) Microsoft Corporation.All rights reserved.
Licensed under the MIT License.
*/
// Platform headers
#ifdef _MSC_VER
#include <winsock2.h>
typedef unsigned socklen_t;
#else
#include <arpa/inet.h>
#include <errno.h>
#include <fcntl.h>
#include <netdb.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/time.h>
#include <unistd.h>
#include <signal.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/stat.h>
#include <time.h>
#include "mme_address.h"
#include "sctp_globals.h"
#include "sctp_agent_db_info.h"
// MME address info
static mme_address_list_t* mme_address_list = NULL; // address list
// current MME DNS info
static struct addrinfo *mme_servinfo = NULL;
static bool dns_triggered = false; // do DNS next time we try and open socket
static bool mme_address_dns_lookup(int protocol, int port)
{
char* mme_addr = NULL;
// release current servinfo
if (mme_servinfo)
{
freeaddrinfo(mme_servinfo);
mme_servinfo = NULL;
}
if (!(mme_addr = mme_address_get_head_addr()))
goto error_hdl;
LOG_PRINT(LOG_NOTICE, "Doing dns lookup for [addr=%s]", mme_addr);
// init the hints
struct addrinfo hints;
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = protocol;
// convert port to a string
char snum[7];
snprintf(snum, sizeof(snum), "%d", port);
if ((getaddrinfo(mme_addr, snum, &hints, &mme_servinfo)) != 0)
{
LOG_PRINT(LOG_ERROR, "Failure from getaddrinfo [addr=%s]", mme_addr);
goto error_hdl;
}
LOG_PRINT(LOG_NOTICE, "Successful dns-lookup for [addr=%s]", mme_addr);
return true;
error_hdl:
if (mme_servinfo)
freeaddrinfo(mme_servinfo);
mme_servinfo = NULL;
return false;
}
//#######################################################################################
// add as circular list
bool mme_address_list_add(mme_address_t* addr)
{
if (!addr)
return false;
if (!mme_address_list)
{
if (!(mme_address_list = calloc(1, sizeof(mme_address_list_t))))
return false;
}
mme_address_t* tail = NULL;
if (mme_address_list->head == NULL)
{
mme_address_list->head = addr;
}
else
{
tail = mme_address_list->head;
while (tail->next != mme_address_list->head)
tail = tail->next;
tail->next = addr;
}
addr->next = mme_address_list->head;
return true;
}
//#######################################################################################
void mme_address_list_free(void)
{
if (!mme_address_list)
return;
mme_address_t *head = mme_address_list->head;
mme_address_t *curr = mme_address_list->head;
if (!curr)
return; // nothing in list
while (mme_address_list->head != head)
{
curr = mme_address_list->head;
mme_address_list->head = curr->next;
free(curr);
}
mme_address_list->head = NULL;
}
//#######################################################################################
char* mme_address_list_get_curr(void)
{
if ((!mme_address_list) || (!mme_address_list->head))
return NULL;
mme_address_t* head = mme_address_list->head;
return head->mme_addr;
}
//#######################################################################################
// returns True if address actually changes
bool mme_address_list_goto_next(void)
{
bool ret = false;
if (!mme_address_list)
return ret;
if (mme_address_list->head)
{
ret = (mme_address_list->head != mme_address_list->head->next);
mme_address_list->head = mme_address_list->head->next;
if (ret)
mme_address_write_head_to_db(mme_address_list->head->mme_addr);
}
// trigger DNS
dns_triggered = true;
return ret;
}
//#######################################################################################
// Set the head to the address in use. Retunr TRUE is present
int mme_address_list_set_head(char* in_use)
{
if (!mme_address_list)
return 0;
if ((!in_use) || (strlen(in_use) == 0))
return 0;
mme_address_t *head = mme_address_list->head;
mme_address_t *curr = mme_address_list->head;
if (!curr)
return 0; // nothing in list
// move to position after head, and then walk until we're back to head
curr = curr->next;
while (curr != head)
{
if (strcmp(in_use, curr->mme_addr) == 0)
{
mme_address_list->head = curr;
break;
}
curr = curr->next;
}
mme_address_write_head_to_db(mme_address_list->head->mme_addr);
return 1;
}
//#######################################################################################
char* mme_address_get_head_addr()
{
if ((!mme_address_list) || (!mme_address_list->head) || (!mme_address_list->head->mme_addr) || (strlen(mme_address_list->head->mme_addr) == 0))
{
LOG_PRINT(LOG_ERROR, "No MME address head defined\n");
return NULL;
}
return mme_address_list->head->mme_addr;
}
// #########################################################################################################
int32_t mme_address_make_outgoing_socket(const char *addr_str, uint16_t port, int protocol)
{
LOG_PRINT(LOG_FUNC, "addr=%s port=%d\n", addr_str, port);
int32_t sockfd = -1;
// do DNS if not done yet
if ((!mme_servinfo) || (dns_triggered))
{
dns_triggered = false;
if (!mme_address_dns_lookup(protocol, port))
goto error_hdl;
}
// loop through all the results and connect to the first we can
struct addrinfo *p = NULL;
for (p = mme_servinfo; p != NULL; p = p->ai_next)
{
if ((sockfd = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == -1)
{
continue;
}
if (protocol == IPPROTO_TCP)
{
int flag = 1;
setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY, (char *)&flag, sizeof(flag));
}
if (connect(sockfd, p->ai_addr, p->ai_addrlen) == -1)
{
close(sockfd);
sockfd = -1;
continue;
}
break; // if we get here, we must have connected successfully
}
if (p == NULL)
{
// looped off the end of the list with no connection
goto error_hdl;
}
return sockfd;
error_hdl:
return -1;
}

View File

@@ -0,0 +1,29 @@
/*
Copyright(c) Microsoft Corporation.All rights reserved.
Licensed under the MIT License.
*/
#ifndef MME_ADDRESS_INFO_H_
#define MME_ADDRESS_INFO_H_
#include "utils/types.h"
typedef struct mme_address {
host_addr_t mme_addr;
struct mme_address *next;
} mme_address_t;
typedef struct
{
mme_address_t *head;
} mme_address_list_t;
extern bool mme_address_list_add(mme_address_t* addr);
extern void mme_address_list_free(void);
extern char* mme_address_list_get_curr(void);
extern bool mme_address_list_goto_next(void);
extern int mme_address_list_set_head(char* in_use);
extern char* mme_address_get_head_addr(void);
extern int32_t mme_address_make_outgoing_socket(const char *addr_str, uint16_t port, int protocol);
#endif // SCTP_AGENT_DB_INFO_H_

View File

@@ -0,0 +1,43 @@
/*
Copyright(c) Microsoft Corporation.All rights reserved.
Licensed under the MIT License.
*/
// Platform headers
#ifdef _MSC_VER
#include <winsock2.h>
typedef unsigned socklen_t;
#else
#include <arpa/inet.h>
#include <errno.h>
#include <fcntl.h>
#include <netdb.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>
#endif
// Standard headers
#include <ctype.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <time.h>
#include "device_db_info.h"
// ##############################################################
uint16_t map_mme_sctp_port(uint16_t enb_sctp_port)
{
// use the same port
return enb_sctp_port;
// return enb_sctp_port + 1; // Use a different port if testing on the local VirtualBox VM.
// This allows a test mme to be run on the VM at the same time
}

View File

@@ -0,0 +1,16 @@
/*
Copyright(c) Microsoft Corporation.All rights reserved.
Licensed under the MIT License.
*/
#ifndef DEVICE_DB_INFO_H_
#define DEVICE_DB_INFO_H_
#define SCTP_AGENT_DB_LOCATION "./sql_db/sctp_agent_native.db"
#define LTE_DB_LOCATION "./sql_db/femto.db"
extern uint16_t map_mme_sctp_port(uint16_t enb_sctp_port);
#endif // DEVICE_DB_INFO_H_

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,15 @@
/*
Copyright(c) Microsoft Corporation.All rights reserved.
Licensed under the MIT License.
*/
#ifndef SCTP_AGENT_
#define SCTP_AGENT_
#include "sctp_agent_db_info.h"
extern void sctp_agent_run(sctp_agent_cfg_t* g_sctp_agent_cfg);
#endif

View File

@@ -0,0 +1,442 @@
/*
Copyright(c) Microsoft Corporation.All rights reserved.
Licensed under the MIT License.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/stat.h>
#include <time.h>
#include <sqlite3.h>
#include "sctp_agent_db_info.h"
#include "mme_address.h"
#define MAX_SCTP_AGENT_DB_NAME (100)
static char g_sctp_agent_db[MAX_SCTP_AGENT_DB_NAME] = "\0";
//#######################################################################################
bool set_sctp_agent_db_location(char* db)
{
if (!db)
return false;
int slen = snprintf(g_sctp_agent_db, MAX_SCTP_AGENT_DB_NAME, "%s", db);
if ((slen <= 0) || (slen >= MAX_SCTP_AGENT_DB_NAME))
return false;
return true;
}
//#######################################################################################
char* get_sctp_agent_db_location(void)
{
return &g_sctp_agent_db[0];
}
// ########################################################################
static bool read_CloudLogInfo(sqlite3 *sql_hdl, cloud_logger_cfg_t* log_cfg)
{
if ((!sql_hdl) || (!log_cfg))
{
return false;
}
memset(log_cfg, 0, sizeof(cloud_logger_cfg_t));
const char *zSql = "SELECT * FROM SettingsCloudLogInfo";
int pnRow; /* Number of result rows written here */
int pnColumn; /* Number of result columns written here */
char *pzErrmsg = NULL;
char **pazResult = NULL;
int rc = sqlite3_get_table(
sql_hdl, /* An open database */
zSql, /* SQL to be evaluated */
&pazResult, /* Results of the query */
&pnRow, /* Number of result rows written here */
&pnColumn, /* Number of result columns written here */
&pzErrmsg /* Error msg written here */
);
if (!((rc == SQLITE_OK) && (pnRow == 1) && (pnColumn == 4)))
{
goto error_hdl;
}
for (int row = 0; row < pnRow; row++)
{
for (int col = 0; col < pnColumn; col++)
{
int index = (row * pnColumn) + pnColumn + col;
if (strcmp(pazResult[col], "level") == 0)
log_cfg->level = atoi(pazResult[index]);
else if (strcmp(pazResult[col], "logname") == 0)
{
if (pazResult[index])
strcpy(log_cfg->logname, pazResult[index]);
}
else if (strcmp(pazResult[col], "port") == 0)
log_cfg->port = atoi(pazResult[index]);
else if (strcmp(pazResult[col], "cloud_ip") == 0)
{
if (pazResult[index])
strcpy(log_cfg->cloud_addr, pazResult[index]);
}
else
{
goto error_hdl;
}
}
}
// free up resources
if (pazResult)
sqlite3_free_table(pazResult);
return true;
error_hdl:
if (pazResult) sqlite3_free_table(pazResult);
return false;
}
// ########################################################################
static bool read_LogInfo(sqlite3 *sql_hdl, logger_cfg_t* loginfo)
{
if ((!sql_hdl) || (!loginfo))
{
return false;
}
memset(loginfo, 0, sizeof(logger_cfg_t));
const char *zSql = "SELECT * FROM SettingsLogInfo";
int pnRow; /* Number of result rows written here */
int pnColumn; /* Number of result columns written here */
char *pzErrmsg = NULL;
char **pazResult = NULL;
int rc = sqlite3_get_table(
sql_hdl, /* An open database */
zSql, /* SQL to be evaluated */
&pazResult, /* Results of the query */
&pnRow, /* Number of result rows written here */
&pnColumn, /* Number of result columns written here */
&pzErrmsg /* Error msg written here */
);
if (!((rc == 0) && (pnRow == 1) && (pnColumn == 5)))
{
goto error_hdl;
}
for (int row = 0; row < pnRow; row++)
{
for (int col = 0; col < pnColumn; col++)
{
int index = (row * pnColumn) + pnColumn + col;
if (strcmp(pazResult[col], "level") == 0)
loginfo->level = atoi(pazResult[index]);
else if (strcmp(pazResult[col], "logname") == 0)
strcpy(loginfo->logname, pazResult[index]);
else if (strcmp(pazResult[col], "file_size") == 0)
strcpy(loginfo->size, pazResult[index]);
else if (strcmp(pazResult[col], "max_files") == 0)
loginfo->max = atoi(pazResult[index]);
else if (strcmp(pazResult[col], "compress") == 0)
loginfo->compress = (bool)(pazResult[index]);
else
{
goto error_hdl;
}
}
}
// free up resources
if (pazResult)
sqlite3_free_table(pazResult);
return true;
error_hdl:
if (pazResult) sqlite3_free_table(pazResult);
return false;
}
//#######################################################################################
void mme_address_write_head_to_db(char* mme_addr)
{
sqlite3 *sql_hdl = NULL;
char sql_str[200];
if ((!mme_addr) || (strlen(mme_addr) == 0))
return;
// get datafile location and open it
char* db_sql_file = get_sctp_agent_db_location();
if (!db_sql_file)
{
goto error_hdl;
}
sqlite3_open(db_sql_file, &sql_hdl);
if (!sql_hdl)
{
goto error_hdl;
}
// build SQL command
sprintf(sql_str, "UPDATE SocketInfo set SocketInfoMmeCurrent='%s'", mme_addr);
char* error_msg = NULL;
int rc = sqlite3_exec(sql_hdl, sql_str, NULL, NULL, &error_msg);
if (rc != SQLITE_OK)
{
goto error_hdl;
}
error_hdl:
// free up resources
if (sql_hdl) sqlite3_close(sql_hdl);
}
//#######################################################################################
// note this does not populate "enb_sctp_port". This parameter is read from the LTE DB
//
static bool get_mme_address_list(void)
{
sqlite3 *sql_hdl = NULL;
sqlite3_stmt *stmt = NULL;
mme_address_t* mme_address = NULL;
// get datafile location and open it
char* db_sql_file = get_sctp_agent_db_location();
if (!db_sql_file)
{
goto error_hdl;
}
sqlite3_open(db_sql_file, &sql_hdl);
if (!sql_hdl)
{
goto error_hdl;
}
// get the MME addresses
const char *sql = "SELECT ip_address FROM SocketInfoMmeList";
int rc = sqlite3_prepare_v2(sql_hdl, sql, -1, &stmt, NULL);
if (rc != SQLITE_OK)
{
goto error_hdl;
}
while ((rc = sqlite3_step(stmt)) == SQLITE_ROW)
{
if (!(mme_address = calloc(1,sizeof(mme_address_t))))
goto error_hdl;
char *tmp;
tmp = (char*)sqlite3_column_text(stmt, 0); strcpy(mme_address->mme_addr, tmp);
// check that mme address is actually populated
if (strlen(mme_address->mme_addr) == 0)
{
goto error_hdl;
}
// add to list
if (!(mme_address_list_add(mme_address)))
{
goto error_hdl;
}
mme_address = NULL;
}
// get the Current address in use
char in_use[200];
in_use[0] = 0;
const char *sql2 = "SELECT SocketInfoMmeCurrent FROM SocketInfo";
rc = sqlite3_prepare_v2(sql_hdl, sql2, -1, &stmt, NULL);
if (rc == SQLITE_OK)
{
while ((rc = sqlite3_step(stmt)) == SQLITE_ROW)
{
char* tmp = (char*)sqlite3_column_text(stmt, 0);
if ((tmp) && (strlen(tmp) > 0))
{
strcpy(in_use, tmp);
}
}
}
// free up resources
if (stmt) sqlite3_finalize(stmt);
if (sql_hdl) sqlite3_close(sql_hdl);
// update database
int curr_written = 0;
if (strlen(in_use) > 0)
{
curr_written = mme_address_list_set_head(in_use);
}
if (!curr_written)
{
// use head as "current"
char *mme_addr = mme_address_get_head_addr();
if (!mme_addr)
{
goto error_hdl;
}
mme_address_write_head_to_db(mme_addr);
}
return true;
error_hdl:
if (mme_address) free(mme_address);
mme_address_list_free();
if (stmt) sqlite3_finalize(stmt);
if (sql_hdl) sqlite3_close(sql_hdl);
return false;
}
//#######################################################################################
// note this does not populate "enb_sctp_port". This parameter is read from the LTE DB
//
bool get_sctp_agent_cfg(sctp_agent_cfg_t* cfg)
{
sqlite3 *sql_hdl = NULL;
sqlite3_stmt *stmt = NULL;
if (!cfg)
{
goto error_hdl;
}
// get datafile location and open it
char* db_sql_file = get_sctp_agent_db_location();
if (!db_sql_file)
{
goto error_hdl;
}
sqlite3_open(db_sql_file, &sql_hdl);
if (!sql_hdl)
{
goto error_hdl;
}
// #################################################################################################################
// get the socket info
const char *sql = "SELECT passthrough_ctl_port, mme_connection_type FROM SocketInfo";
int rc = sqlite3_prepare_v2(sql_hdl, sql, -1, &stmt, NULL);
if (rc != SQLITE_OK)
{
goto error_hdl;
}
while ((rc = sqlite3_step(stmt)) == SQLITE_ROW)
{
char *tmp;
cfg->socket_info.passthrough_ctl_port = sqlite3_column_int(stmt, 0);
tmp = (char*)sqlite3_column_text(stmt, 1); cfg->socket_info.mme_conn_type = (strcmp(tmp, "sctp") == 0) ? CONN_SCTP : CONN_TCP;
}
if (rc != SQLITE_DONE)
{
goto error_hdl;
}
sqlite3_finalize(stmt); stmt = NULL;
// release database - release here as we might write to the dateabase in get_mme_address_list
if (sql_hdl) sqlite3_close(sql_hdl);
sql_hdl = NULL;
if (!(get_mme_address_list()))
{
goto error_hdl;
}
sqlite3_open(db_sql_file, &sql_hdl);
if (!sql_hdl)
{
goto error_hdl;
}
// #################################################################################################################
// get the log info
if (!(read_LogInfo(sql_hdl, &cfg->log_info)))
{
goto error_hdl;
}
// #################################################################################################################
// get the log info
if (!(read_CloudLogInfo(sql_hdl, &cfg->cloud_log_info)))
{
goto error_hdl;
}
// copy cloud level
cfg->log_info.cloud_level = cfg->cloud_log_info.level;
// #################################################################################################################
// get the paws status periodicity i.e. how often the status must be sent to the sctp-agent
const char *sql2 = "SELECT use_passthrough_ctl, passthrough_ctl_periodicity, azure_mme_socket_retry_s, azure_mme_socket_drop_enb_s, azure_mme_socket_swap_mme_s, azure_mme_pkt_retx_guard_ms, azure_mme_pkt_retx_max_attempts FROM Settings";
rc = sqlite3_prepare_v2(sql_hdl, sql2, -1, &stmt, NULL);
if (rc != SQLITE_OK)
{
goto error_hdl;
}
while ((rc = sqlite3_step(stmt)) == SQLITE_ROW)
{
cfg->settings.use_passthrough_ctl = (bool)sqlite3_column_int(stmt, 0);
cfg->settings.passthrough_ctl_periodicity = sqlite3_column_int(stmt, 1);
cfg->settings.azure_mme_socket_retry_s = sqlite3_column_int(stmt, 2);
cfg->settings.azure_mme_socket_drop_enb_s = sqlite3_column_int(stmt, 3);
cfg->settings.azure_mme_socket_swap_mme_s = sqlite3_column_int(stmt, 4);
cfg->settings.azure_mme_pkt_retx_guard_ms = sqlite3_column_int(stmt, 5);
cfg->settings.azure_mme_pkt_retx_max_attempts = sqlite3_column_int(stmt, 6);
}
if (rc != SQLITE_DONE)
{
goto error_hdl;
}
sqlite3_finalize(stmt); stmt = NULL;
// validate settings
if (cfg->settings.azure_mme_socket_retry_s < AZURE_MME_SOCKET_RETRY_S_MIN)
cfg->settings.azure_mme_socket_retry_s = AZURE_MME_SOCKET_RETRY_S_MIN;
if (cfg->settings.azure_mme_pkt_retx_guard_ms < AZURE_MME_PKT_GUARD_MS_MIN)
cfg->settings.azure_mme_pkt_retx_guard_ms = AZURE_MME_PKT_GUARD_MS_MIN;
// release database
if (sql_hdl) sqlite3_close(sql_hdl);
return true;
error_hdl:
if (sql_hdl) sqlite3_close(sql_hdl);
if (stmt) sqlite3_finalize(stmt);
return false;
}

View File

@@ -0,0 +1,61 @@
/*
Copyright(c) Microsoft Corporation.All rights reserved.
Licensed under the MIT License.
*/
#ifndef SCTP_AGENT_DB_INFO_H_
#define SCTP_AGENT_DB_INFO_H_
#include <stdint.h>
#include <stdbool.h>
#include "utils/types.h"
#include "logger/logger.h"
#include "mme_address.h"
#include "sctp_agent_db_info.h"
typedef enum
{
CONN_SCTP = 0,
CONN_TCP
} mme_conn_type_e;
#define AZURE_MME_SOCKET_RETRY_S_MIN (1)
#define AZURE_MME_PKT_GUARD_MS_MIN (20)
typedef struct {
uint16_t passthrough_ctl_port;
uint16_t enb_sctp_port;
uint16_t mme_sctp_port;
mme_conn_type_e mme_conn_type;
} sctp_agent_socket_cfg_t;
typedef struct {
bool use_passthrough_ctl;
uint32_t passthrough_ctl_periodicity;
uint32_t azure_mme_socket_retry_s; // how often to try to re-open a socket to MME
uint32_t azure_mme_socket_drop_enb_s; // duration of a socket being disconnected which will cause an eNB socket drop and RESET
uint32_t azure_mme_socket_swap_mme_s; // duration of a socket being disconnected which will cause an attempt to swap MME
uint32_t azure_mme_pkt_retx_guard_ms; // how long to wait for packet acknowledgement , before doing a retx
uint32_t azure_mme_pkt_retx_max_attempts; // max number of retx (not including initial tx). At max attempts, MME socket is dropped
} sctp_agent_settings_cfg_t;
typedef struct {
sctp_agent_socket_cfg_t socket_info;
sctp_agent_settings_cfg_t settings;
logger_cfg_t log_info;
cloud_logger_cfg_t cloud_log_info;
} sctp_agent_cfg_t;
extern bool set_sctp_agent_db_location(char* db);
extern char* get_sctp_agent_db_location(void);
extern bool get_sctp_agent_cfg(sctp_agent_cfg_t* cfg); // note this does not populate "enb_sctp_port"
extern void mme_address_write_head_to_db(char* mme_addr);
#endif // SCTP_AGENT_DB_INFO_H_

View File

@@ -0,0 +1,15 @@
/*
Copyright(c) Microsoft Corporation.All rights reserved.
Licensed under the MIT License.
*/
#ifndef SCTP_CFG_OPTIONS_H_
#define SCTP_CFG_OPTIONS_H_
#define REBOOT_AFTER_RFTXSTATUS_DROP // some FAPs do not automatically restart the radio once it had been turned off.
// With this setting, we will force a reboot if the eNB socket is opened folliwng a radio drop.
#endif // SCTP_CFG_OPTIONS_H_

View File

@@ -0,0 +1,45 @@
/*
Copyright(c) Microsoft Corporation.All rights reserved.
Licensed under the MIT License.
*/
#ifndef SCTP_GLOBALS_H_
#define SCTP_GLOBALS_H_
#include "utils/types.h"
#include "utils/utils.h"
#include "logger/logger.h"
#include "sctp_cfg_options.h"
// reference to globals
extern device_name_t gDeviceName;
extern device_id_t gDeviceId;
extern void* g_logger;
extern void* g_cloud_logger;
#define SCTP_LOGGER_TYPE "SCTPAGENT"
#define MAX_LOG_LINE_LENGTH (200)
static char logline_[MAX_LOG_LINE_LENGTH];
#define LOG_PRINT(loglevel, fmt, args...) { \
if (g_logger) \
{ \
int slen = snprintf(logline_, MAX_LOG_LINE_LENGTH, fmt, ##args); \
if (!((slen <= 0) || (slen >= MAX_LOG_LINE_LENGTH))) \
{ \
logger_log(g_logger, logline_, loglevel, SCTP_LOGGER_TYPE, true, true, __FILENAME__, __LINE__, __func__, g_cloud_logger, gDeviceName, SCTP_LOGGER_TYPE); \
} \
} \
}
#define sctp_fatal_error(fmt, args...) { \
LOG_PRINT(LOG_CRITICAL, fmt, ##args); \
fatal_error("%s %d " fmt, __FILE__, __LINE__, ##args) \
}
#endif // SCTP_GLOBALS_H_

Some files were not shown because too many files have changed in this diff Show More